feat(opcache): relocate closures/arrow functions (dynamic_func_defs) in cache binaries - #258
Merged
Merged
Conversation
6 tasks
lisachenko
force-pushed
the
claude/opcache-115-relocate-closures
branch
from
August 19, 2026 21:59
083a6d3 to
51d407c
Compare
lisachenko
force-pushed
the
claude/opcache-115-relocate-closures
branch
from
August 19, 2026 22:40
51d407c to
97393cf
Compare
…fns)
Port the num_dynamic_func_defs branch of zend_file_cache_serialize_op_array /
zend_file_cache_unserialize_op_array (ext/opcache/zend_file_cache.c,
PHP-8.4.19): the zend_op_array* array is relocated, each def slot is
converted like the C SERIALIZE_PTR/UNSERIALIZE_PTR pair (offsets stored,
walking continues through the still-real address) and the walk recurses into
every nested op_array - so a closure defined inside another closure unfolds
through its own dynamic_func_defs. Both directions; the unsupportedPayload
refusal for closures is gone.
New fixture tests/OpCache/fixtures/closures.php holds an arrow function and an
anonymous function in a global function, a closure nested inside another
closure, and a scoped arrow function inside a static method.
Acceptance evidence:
- ClosureRelocationTest::testClosurePayloadRoundTripsByteIdentical -
byte-for-byte round trip of the compiled fixture
- testUnmodifiedResaveStillExecutes / testPatchedClosureFixtureExecutesFromCache
- the re-serialized (and patched) binary executes all closures from the
cache ('cl:42:42:...' proves arrow, anonymous, nested and method-scoped defs)
- full default suite, --group opcache --fail-on-skipped (host and
z-engine-php:debug84 container), phpstan level max and php-cs-fixer all green
Fixes #115
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BDcCQiYqbMkjRPyhWgLL6M
lisachenko
force-pushed
the
claude/opcache-115-relocate-closures
branch
from
August 19, 2026 23:08
97393cf to
a756aad
Compare
lisachenko
marked this pull request as ready for review
August 19, 2026 23:09
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this changes
Fixes #115 — third PR of the relocator-coverage chain (stacked on #257).
Ports the
num_dynamic_func_defsbranch ofzend_file_cache_(un)serialize_op_array: relocates thedynamic_func_defsarray, converts each slot, and recurses into each nested op_array — closures-inside-closures handled via their owndynamic_func_defs, both directions. Acceptance: fixture withfn()+function()in a global function, a nested closure, and a scopedfn()in a static method — byte-identical round trip and patched execution proving all defs execute from the cache (ClosureRelocationTest).docs/opcache-binary.mdscope updated.Environment it was verified on
php -v): PHP 8.4.19 (cli) (built: Mar 30 2026 19:28:35) (NTS)--enable-debug)? yes — debug 8.4 container opcache gate green at this chain point (40 tests)Per-issue verification before commit: full default suite baseline-identical, opcache gate green (release + debug84), PHPStan level max clean, cs-fixer clean.
Checklist
8.4)composer testpasses on the matching PHP minorcomposer phpstan(level max) andcomposer cs:checkare greendynamic_func_defsalready in the generated defstools/generator/symbols.phpunchanged — nothing generated touched🤖 Generated with Claude Code
https://claude.ai/code/session_01BDcCQiYqbMkjRPyhWgLL6M
Generated by Claude Code