Skip to content

feat(opcache): relocate PHP 8.4 property hooks in cache binaries - #260

Merged
lisachenko merged 1 commit into
8.4from
claude/opcache-113-relocate-property-hooks
Aug 19, 2026
Merged

feat(opcache): relocate PHP 8.4 property hooks in cache binaries#260
lisachenko merged 1 commit into
8.4from
claude/opcache-113-relocate-property-hooks

Conversation

@lisachenko

Copy link
Copy Markdown
Owner

What this changes

Fixes #113 — final PR of the relocator-coverage chain (stacked on #259). With this, the last payload-shape refusal is gone: PayloadRelocator handles every compile-producible 8.4 payload; only the platform refusals remain (Windows/32-bit by policy, ZTS pending #118).

Ports the prop->hooks branch of zend_file_cache_(un)serialize_prop_info: relocates the zend_function*[ZEND_PROPERTY_HOOK_COUNT] array (count 2, private const following the file's precedent — constants.php doesn't export it), converts each non-NULL slot, and recurses into each hook op_array (shared bodies early-return via the opcodes guard, as in C). Acceptance: fixture with get+set hooks, a get-only virtual property, and a set-only backed property — byte-identical round trip and patched execution proving both hooks, the virtual getter and the set clamp run from the cache (PropertyHookRelocationTest). 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 --group opcache --fail-on-skipped OK (47 tests, 318 assertions) on this chain head

Chain-final verification on this head: full default suite Tests: 519, Assertions: 5250 (baseline skips/incompletes only); opcache-runner mode Tests: 517, Skipped: 6 (all pre-existing/issue-linked); 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; prop->hooks field 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-113-relocate-property-hooks branch from 8f9bb30 to cc37a01 Compare August 19, 2026 21:59
@lisachenko
lisachenko force-pushed the claude/opcache-113-relocate-property-hooks branch from cc37a01 to a661d63 Compare August 19, 2026 22:40
@lisachenko
lisachenko force-pushed the claude/opcache-113-relocate-property-hooks branch from a661d63 to c6a4d31 Compare August 19, 2026 23:08
@lisachenko
lisachenko force-pushed the claude/opcache-113-relocate-property-hooks branch from c6a4d31 to f057e9d Compare August 19, 2026 23:17
Base automatically changed from claude/opcache-116-relocate-iterators to 8.4 August 19, 2026 23:28
…load

Port the prop->hooks branch of zend_file_cache_serialize_prop_info /
zend_file_cache_unserialize_prop_info (ext/opcache/zend_file_cache.c,
PHP-8.4.19): the zend_function*[ZEND_PROPERTY_HOOK_COUNT] array is relocated,
and each non-NULL hook slot is converted and its op_array walked in both
directions (hook bodies shared with the class function_table return early
through the existing opcodes guard, as in C). NULL get/set slots stay NULL.
The last payload-shape refusal is gone; only the platform refusals
(Windows/32-bit, ZTS - issues #119/#118) remain.

The hooked-class get_iterator field holds HOOKED_ITERATOR_PLACEHOLDER in the
file; it is execution-only and preserved verbatim (see the #116 notes on
unserializeIteratorFuncs), so the placeholder round-trips untouched.

New fixture tests/OpCache/fixtures/property-hooks.php compiles a property with
both get and set hooks, a get-only virtual property and a set-only backed
property.

Acceptance evidence:
- PropertyHookRelocationTest::testPropertyHookPayloadRoundTripsByteIdentical -
  byte-for-byte round trip of the compiled fixture
- testUnmodifiedResaveStillExecutes / testPatchedPropertyHookFixtureExecutesFromCache
  - the re-serialized (and patched) binary executes get/set hooks from the
  cache ('0:40:gauge-40:0:...' proves both hooks, the virtual getter and the
  set-only clamp ran)
- full default suite, --group opcache --fail-on-skipped (host and
  z-engine-php:debug84 container), opcache-runner mode
  (opcache.enable_cli=1, --exclude-group performance/internal/opcache-incompatible),
  phpstan level max and php-cs-fixer all green

Fixes #113

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BDcCQiYqbMkjRPyhWgLL6M
@lisachenko
lisachenko force-pushed the claude/opcache-113-relocate-property-hooks branch from f057e9d to 040e736 Compare August 19, 2026 23:28
@lisachenko
lisachenko marked this pull request as ready for review August 19, 2026 23:32
@lisachenko
lisachenko merged commit 12f4829 into 8.4 Aug 19, 2026
21 checks passed
@lisachenko
lisachenko deleted the claude/opcache-113-relocate-property-hooks branch August 19, 2026 23:40
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 PHP 8.4 property hooks in cache binaries

2 participants