Skip to content

feat(opcache): relocate closures/arrow functions (dynamic_func_defs) in cache binaries - #258

Merged
lisachenko merged 1 commit into
8.4from
claude/opcache-115-relocate-closures
Aug 19, 2026
Merged

feat(opcache): relocate closures/arrow functions (dynamic_func_defs) in cache binaries#258
lisachenko merged 1 commit into
8.4from
claude/opcache-115-relocate-closures

Conversation

@lisachenko

Copy link
Copy Markdown
Owner

What this changes

Fixes #115 — third PR of the relocator-coverage chain (stacked on #257).

Ports the num_dynamic_func_defs branch of zend_file_cache_(un)serialize_op_array: relocates the dynamic_func_defs array, converts each slot, and recurses into each nested op_array — closures-inside-closures handled via their own dynamic_func_defs, both directions. Acceptance: fixture with fn() + function() in a global function, a nested closure, and a scoped fn() in a static method — byte-identical round trip and patched execution proving all defs execute from the cache (ClosureRelocationTest). docs/opcache-binary.md scope updated.

Environment it was verified on

  • PHP version (full first line of php -v): PHP 8.4.19 (cli) (built: Mar 30 2026 19:28:35) (NTS)
  • Thread safety: NTS
  • OS / architecture: Linux x86-64 (Ubuntu)
  • Debug build (--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

  • Targets the minimum affected version branch (chain → 8.4)
  • composer test passes on the matching PHP minor
  • composer phpstan (level max) and composer cs:check are green
  • Tests added or updated; dynamic_func_defs already in the generated defs
  • tools/generator/symbols.php unchanged — nothing generated touched
  • Conventional Commits used for the commit messages

🤖 Generated with Claude Code

https://claude.ai/code/session_01BDcCQiYqbMkjRPyhWgLL6M


Generated by Claude Code

@lisachenko
lisachenko force-pushed the claude/opcache-115-relocate-closures branch from 083a6d3 to 51d407c Compare August 19, 2026 21:59
@lisachenko
lisachenko force-pushed the claude/opcache-115-relocate-closures branch from 51d407c to 97393cf Compare August 19, 2026 22:40
Base automatically changed from claude/opcache-114-relocate-traits to 8.4 August 19, 2026 23:08
…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
lisachenko force-pushed the claude/opcache-115-relocate-closures branch from 97393cf to a756aad Compare August 19, 2026 23:08
@lisachenko
lisachenko marked this pull request as ready for review August 19, 2026 23:09
@lisachenko
lisachenko merged commit 40975ff into 8.4 Aug 19, 2026
21 checks passed
@lisachenko
lisachenko deleted the claude/opcache-115-relocate-closures branch August 19, 2026 23:17
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.

feat(opcache): relocate closures/arrow functions (dynamic_func_defs) in cache binaries

2 participants