Repository navigation
Language: list destructuring JIT/MCJIT execute — phase 2 of #4308 / #4325 (zend_execute.c) #4531
Description
Activity
- addedphase-2:languagePhase 2 – language featuresPhase 2 – language featuresarea:compilerCompiler / CFG / JITCompiler / CFG / JITarea:vmVirtual machineVirtual machineimplementation-readySpec complete: repro, php-src ref, done-when — safe for workers to claimSpec complete: repro, php-src ref, done-when — safe for workers to claim
on Jun 2, 2026 claim: worker-lane-b — starting this run
Worker lane B — WIP (PR opened, not merged)
Done this run
- Identified MCJIT segfault root cause: guarded-list merge CFG block was inserted into
blockStoragebeforeTYPE_JUMPcompiled it → empty merge LLVM BB. - Fix: defer
blockStorageregistration; compile merge on jump vialistUnpackMergeLlvmBlocks+allowRecompile. - Compile-time skip path: null-init list targets at merge entry (
listUnpackMergeNullInitTargets). - JIT
var_export()2-arg (return true) for compliance phpts. vendor/bin/phpunit --filter ListDestruct— OK (compile + VM).
Still failing
php bin/jit.php test/repro/list_destruct_null_4325.php # exit 139Smaller JIT snippets (
[$a]=null;,[$a,$b]=null;without echo) execute OK.Next step
Debug merge-block teardown (
valueDelref/freeDeadVariables) when echo +var_exportfollow skipped list destruct in the same function.- Identified MCJIT segfault root cause: guarded-list merge CFG block was inserted into
- added a commit that references this issue
on Jun 3, 2026 claim: agent-worker-lane-b — continuing MCJIT execute (#4531); bin/jit.php was VM-fallback via embed bootstrap, fixing Runtime->jit() path + tests
WIP handoff (agent-worker-lane-b) — PR opened, not merged (MCJIT execute blocked)
Done this run
- Root cause: catch
$e->getMessage()in list-destruct TypeError tests failed JIT compile (Call to undefined method ::getmessage()) because catch variables have empty/unregistereduserTypeand Exception methods had no JIT proxy. - Fix:
lib/JIT/Call/ExceptionGetMessage.php+exception::getmessageregistration;initJitMethodCall()normalizes empty userType and routesgetMessage()through Exception proxy. - VM compliance green:
vendor/bin/phpunit test/compliance/VMTest.php --filter list_destructure→ OK (7 tests). - JIT compile for string list-destruct + catch now succeeds (past getMessage).
Blocker
Runtime->jit()MCJIT execute fails module verify (AddrSpaceCast source must be a pointer, etc.) for all scripts in harness — not list-destruct-specific.ListDestruct*JitExecuteTeststill ERROR. Also:bin/jit.phpclassless repros VM-fallback via embed bootstrap (requiresVmLowering: yes), so they don't validate MCJIT.PR
https://github.com/PurHur/php-compiler/pull/new/agent/issue-4531-list-destruct-jit-v2 (branch
agent/issue-4531-list-destruct-jit-v2)Next step
Fix MCJIT module verify on linked runtime bundle (#98), then re-run
vendor/bin/phpunit --filter ListDestructand remove JITTest skips forlist_destructure_null/list_destructure_string.- Root cause: catch
- added a commit that references this issue
on Jun 7, 2026 Worker lane B — continued (#4531), not merged
This run
- Continued PR JIT: list destruct MCJIT — getMessage catch lowering (#4531) #7513 (
agent/issue-4531-list-destruct-jit-v2). - Fixed
ExceptionGetMessageto useJitValueBox::valuePtrFromVariable. - Fixed glob/scandir libc signature drift:
StringFsGlobVecJit+StringDirJitnow usei8*params consistent withLibcExtern(eliminates scandirselect void*/i8*verify errors).
Verification
# VM parity — green ./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && vendor/bin/phpunit test/compliance/VMTest.php --filter list_destructure' # OK (7 tests) # MCJIT compile+verify — still fails (shared harness #98, not list-destruct-specific) ./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && vendor/bin/phpunit test/unit/ListDestructStringJitCompileTest.php' # ERROR: Module verification failed (~60 remaining IR issues: AddrSpaceCast, icmp type mix, parse_str/setcookie, …) ./script/docker-exec.sh -- bash -lc 'source script/php-env.sh && vendor/bin/phpunit test/unit/ListDestructStringJitExecuteTest.php' # ERROR: same module verify gate
Blocker / next step
Runtime->jit()MCJIT path requires full module verify on eagerType::initialize()runtime bundle IR. Post-#7405 PHP-in-PHP emit still has ~60 verify errors across dns/parse_str/setcookie/escaping helpers. Need follow-up aligned with #98 /162b31b85libc-alignment sweep beforeListDestruct*JitExecuteTestcan pass and JITTest list_destruct skips can drop.PR: #7513
- Continued PR JIT: list destruct MCJIT — getMessage catch lowering (#4531) #7513 (
claim: agent-worker-lane-b — continuing PR #7513; un-skip JITTest list_destruct + align unit probes with bin/jit.php subprocess path
- added a commit that references this issue
on Jun 7, 2026 - added a commit that references this issue
on Jun 7, 2026 Merged via PR #7513.
Verification (Docker harness)
- VM:
vendor/bin/phpunit test/compliance/VMTest.php --filter list_destructure→ OK (7) - JIT compliance:
vendor/bin/phpunit test/compliance/JITTest.php --filter list_destructure→ OK (5) - Unit probes:
vendor/bin/phpunit --filter ListDestructNullJitCompileTest|ListDestructStringJitCompileTest|ListDestructNullJitExecuteTest|ListDestructStringJitExecuteTest→ OK (4) - Repro:
php bin/jit.php test/repro/list_destruct_null_4325.phpandlist_destruct_string_typeerror.php→ Zend-matching output, no segfault
Notes
ExceptionGetMessageJIT proxy enables$e->getMessage()in catch arms for string list-destruct TypeError tests.- ListDestruct JIT probes use
bin/jit.phpsubprocess (CI: Run JIT compliance tests in CI (fix LLVM skip in PHPUnit) #98 pattern); JITTest list_destruct skips removed. - In-process
Runtime::jit()module verify on eager runtime bundle remains tracked under CI: Run JIT compliance tests in CI (fix LLVM skip in PHPUnit) #98 for non-list-destruct MCJIT paths.
- VM:
Category
language
Problem
VM parity for guarded
list()/[]destructuring from non-array RHS is tracked in closed #4308 (string) and #4325 (null/false).JITTeststill skips MCJIT execute for these cases because LLVM lowering can segfault when compiling unreachable dim-fetch paths on guarded destructuring.Workers need a follow-up issue for JIT/AOT execute stability, not VM semantics.
php-src reference
Zend/zend_execute.c—ZEND_HANDLE_EXCEPTION/ list unpack on invalid typesZend/zend_vm_def.h—ZEND_FETCH_LIST/ array unpackRepro
Existing tests (should pass VM, fail or skip MCJIT):
test/compliance/cases/language/list_destructure_string.phpt(Language: list destructuring from string — must not treat string as packed list (zend_execute.c parity) #4308)test/repro/list_destruct_null_4325.php(Language: list destructuring from null — target variables must remain unset (zend_execute.c parity) #4325)test/unit/ListDestructStringJitCompileTest.phptest/unit/ListDestructNullJitCompileTest.phpScope
lib/JIT/ListUnpackHelper.phplib/JIT.php(guarded list destruct branch)lib/Compiler.php(listDestructGuardGroupEnd,compileListDestructGuard)test/compliance/JITTest.phpforlist_destructDone when
bin/jit.phpruns repro scripts without segfault; output matches ZendListDestruct*JitCompileTestand MCJIT execute probes passlist_destructcases for MCJIT instability