Skip to content

feat: complete runtime isolation and cloning phases 10-16 - #926

Merged
fglock merged 8 commits into
masterfrom
feature/perl-threads-phases-10-12
Aug 12, 2026
Merged

feat: complete runtime isolation and cloning phases 10-16#926
fglock merged 8 commits into
masterfrom
feature/perl-threads-phases-10-12

Conversation

@fglock

@fglock fglock commented Aug 11, 2026

Copy link
Copy Markdown
Owner

Summary

  • complete Perl threads plan phases 10–12 by isolating remaining mutable runtime state and exposing lifecycle-managed independent runtimes
  • complete phase 13 with all six measured hot paths inside the 5% regression budget
  • complete phase 14 with an identity-preserving non-code value graph cloner for aliases, cycles, blessings, weak refs, readonly values, ties, and explicit resource policy
  • complete phase 15 with explicit generated JVM capture metadata and interpreter closure cloning through the same identity map
  • complete phase 16 with runtime package snapshots, parent-side CLONE_SKIP, child-side CLONE, and fresh child execution/resource state
  • repair the Windows CI regressions exposed by runtime isolation, including File::Spec::Unix host independence and quoted qx command handling
  • keep Config thread flags disabled; this PR does not expose the Perl threads API

Validation

  • make — pass after each significant phase; final gate pass
  • Windows and Ubuntu CI — pass for the prerequisite runtime-state/Windows-fix head before phases 13–16
  • focused graph tests — aliases, cycles, blessings, weak refs, readonly values, source immutability, and resource policy pass in all shards
  • focused closure tests — independent scalar/array/hash captures pass on JVM and interpreter backends
  • focused snapshot tests — global aliases, CLONE_SKIP, CLONE, parent immutability, and fresh execution stacks pass on JVM and interpreter backends
  • prior comprehensive compatibility gate: Perl core 83.1%, bundled modules 81.0%, Scalar::Util 1.70 on both backends

Performance

Three fresh-JVM runs per tree, comparing median rates against the exact merged base:

Benchmark Base Current Delta
global 35671 37030 +3.8%
lexical 118820 127349 +7.2%
method 94.40 91.45 -3.1%
closure 32.37 34.68 +7.1%
regex 22048.45 21657.60 -1.8%
eval-string 14910.07 15070.22 +1.1%

Design notes

  • one identity map spans all cloned roots; Storable hooks and reflective field ordering are not used
  • generated JVM closures expose constructor-ordered captures through CloneablePerlSubroutine
  • nonportable Java I/O resources conservatively become undef in cloned value graphs; child standard I/O remains fresh
  • child execution, lifecycle, signal/alarm, native, classloader, cache, and I/O state is not copied
  • completed phase history remains in commit and PR messages rather than a growing section in dev/design/concurrency.md

fglock and others added 8 commits August 11, 2026 21:51
Implement Perl threads plan phases 10, 11, and 12 as one maintainer-requested
change while keeping both compiler backends functional and thread feature
flags disabled.

Phase 10 moves lexical hints, warning registries, feature flags, source maps,
source filters, and end-of-scope hook state into the bound PerlRuntime. The
global compilation lock continues to protect compiler-only parser scratch.

Phase 11 completes the mutable runtime-state inventory across lifecycle and
reachability tracking, weak references and DESTROY dispatch, signals and
alarms, filesystem/stat/random/data-section state, debugger state, process and
I/O registries, native/module registries, and blessing identity. Background
callbacks that access Perl state capture and bind their owning runtime, while
immutable caches and synchronized process services remain process-global.

Phase 12 adds idempotent initialization and close plus exclusive reentrant
managed execution. Runtime close releases alarms, signals, handles, native
registries, and lifecycle roots. Direct bind remains the explicit context
propagation primitive; managed execute serializes ownership of one runtime.

Tests cover nested and concurrent compilation state, conflicting source
locations, runtime-owned miscellaneous state, independent JVM/interpreter
programs, close cleanup, and alarm callback binding. The full make passes.
make test-all reaches 83.1% Perl core and 81.0% bundled modules. Scalar::Util
1.70 and lifecycle smokes pass on both backends; the JVM Moo constructor smoke
passes, while the known interpreter Moo syntax limitation remains unchanged.

Same-base three-run benchmark medians remain within the 5% gate: global +3.8%,
lexical +7.2%, method -3.1%, closure +7.1%, regex -1.8%, and eval-string +1.1%.
Profile-guided runtime lookup batching and idle lifecycle fast paths recover
the initially observed hot-path regressions without weakening state isolation.

Update dev/design/concurrency.md with the validation record and Phase 13
handoff. Completed implementation history remains recoverable from commit and
pull-request messages rather than a growing completed-phases section.

Generated with [Codex](https://openai.com/codex)

Co-Authored-By: Codex <223018245+openai-codex[bot]@users.noreply.github.com>
Keep runtime-isolation tests platform-native, execute string-form Windows
pipe commands through cmd.exe so built-ins remain available, validate relative
Windows PATH entries in taint mode, and preserve lexical Windows SYSTEM IDs
after Xerces URI normalization.

Generated with [Codex](https://openai.com/codex)

Co-Authored-By: Codex <223018245+openai-codex[bot]@users.noreply.github.com>
Keep File::Spec::Unix path operations host-independent, use stable cmd
command parsing, and support the portable bare type output-pipe idiom on
Windows. This completes the fixes for the remaining PR 926 CI failures.

Generated with [Codex](https://openai.com/codex)

Co-Authored-By: Codex <223018245+openai-codex[bot]@users.noreply.github.com>
Parse quoted Windows one-string commands into argv when shell syntax appears
only inside arguments. This keeps quoted jperl.bat invocations out of cmd.exe's
nested quote handling while retaining cmd for real shell expressions.

Generated with [Codex](https://openai.com/codex)

Co-Authored-By: Codex <223018245+openai-codex[bot]@users.noreply.github.com>
Record the measured Phase 13 benchmark gate as complete and advance the
threads implementation plan to the identity-preserving graph cloner.

The six same-base benchmark medians are all within the required five percent
regression limit. Historical implementation and validation details remain in
the phase commit and pull-request history.

Generated with [Codex](https://openai.com/codex)

Co-Authored-By: Codex <223018245+openai-codex[bot]@users.noreply.github.com>
Implement the Phase 14 ithread graph-cloning foundation with a single identity
map across roots. Preserve scalar-slot identity, aggregate aliases and cycles,
blessings, weak edges, readonly values, and tie wrappers without Storable hooks.

Define the initial conservative resource policy: nonportable Java I/O handles
become undef in the cloned graph. Register aggregate shells before recursion and
defer weak-edge installation until the strong graph is complete, leaving the
source graph untouched.

Validation: full make gate and focused graph tests pass in all five shards.

Generated with [Codex](https://openai.com/codex)

Co-Authored-By: Codex <223018245+openai-codex[bot]@users.noreply.github.com>
Add explicit generated capture metadata for JVM closures and clone them without
reflecting over Java field order. Rebuild interpreter closures from immutable
bytecode metadata while cloning their constants, captures, state variables,
recursive self references, and lexical maps through the Phase 14 identity map.

Cross-backend tests prove cloned scalar, array, and hash captures evolve
independently from their source closures. The full make gate passes.

Generated with [Codex](https://openai.com/codex)

Co-Authored-By: Codex <223018245+openai-codex[bot]@users.noreply.github.com>
Compose runtime package state and the identity-preserving graph cloner into
PerlRuntime.snapshotClone(). Materialize lazy hook definitions and run
CLONE_SKIP in the parent before copying, then invoke CLONE in deterministic
package order after the child graph is installed.

Clone globals and CODE slots through one graph map while leaving execution,
lifecycle, signal/alarm, native, classloader, cache, and I/O state fresh in the
child. Preserve provider-initialized runtimes without resetting their live
package graph when they enter the managed lifecycle API.

Cross-backend snapshot tests cover global alias isolation, skipped blessed
objects, hook context, parent immutability, and fresh execution stacks. The full
make gate passes; Config thread capability flags remain disabled.

Generated with [Codex](https://openai.com/codex)

Co-Authored-By: Codex <223018245+openai-codex[bot]@users.noreply.github.com>
@fglock fglock changed the title feat: isolate remaining runtime state and lifecycle feat: complete runtime isolation and cloning phases 10-16 Aug 12, 2026
@fglock
fglock merged commit 3886c09 into master Aug 12, 2026
2 checks passed
@fglock
fglock deleted the feature/perl-threads-phases-10-12 branch August 12, 2026 08:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant