Repository navigation
Fix concat into slot-less destination (#21886) + self-host bundle compile OOM + measured iteration costs - #21908
Merged
Merged
Conversation
…ust lints (#16508) bin/compile.php raises memory_limit to 6G for test/selfhost/ bundles because the 1536M default OOMs — but the bump sat INSIDE the `isset($options['-l'])` branch, so it only applied to lint. Compiling the same bundle: php bin/compile.php -o OUT test/selfhost/compiler_helloworld_smoke/main.php still ran at 1536M and died as: PHP Fatal error: Allowed memory size of 1610612736 bytes exhausted in vendor/ircmaxell/php-cfg/lib/PHPCfg/Traverser.php:117 with nothing indicating the cap was the cause — the traceback points at vendor parser internals, not at a memory setting. Hoisted the bump so lint and compile paths both get it. Verified: the exact command above, with no explicit PHP_COMPILER_MEMORY_LIMIT, previously OOMd and now runs past it (0 'Allowed memory size' lines). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The doc's only timing figure was 'north-star5-verify-fast ~1-2 min', which implies lowering work iterates in minutes. Measured, it does not: a THREE-LINE 'echo $s' script takes ~43 min to AOT-compile, because the path emits and links the whole runtime regardless of source size. Anyone planning a 'shrink the repro' inner loop will lose hours discovering this. Records the measured table and the three things that actually help: the helper-runtime cache (and why #21855's guard correctly makes lowering edits cold anyway), parallelising hypotheses instead of chasing a faster cycle, and using a single PHP_COMPILER_DUMP_IR=1 dump instead of repeated compiles — which is how #21886 was located in one run. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…inter' (#21886) Compiling test/selfhost/compiler_helloworld_smoke/main.php failed module verification: Module verification failed due to Store operand must be a pointer. store %__string__* %293, i64 258 The native concat path in compileBlockInternal promotes a KIND_VALUE destination to a real alloca slot before storing — but only when $result->type is TYPE_STRING. A destination whose inferred type never settled on string skipped the promotion and reached the raw store, writing a __string__* into an immediate (the i64 constant IS the value, there is no slot). The lowering already called helper->loadValue() on both INPUTS; nothing checked the OUTPUT had somewhere to go. Promote when the destination is KIND_VALUE, or when its LLVM type is not __string__*, or when ->value is null — covering the mis-inferred case rather than only the one known-good shape. Located by dumping IR once (PHP_COMPILER_DUMP_IR=1) and reading the single malformed store plus its enclosing function, rather than by repeated compiles — each attempt on this path costs ~26 min. Verified: - test/selfhost/compiler_helloworld_smoke/main.php now compiles and links (exit 0, 0 store errors, 841712-byte binary; previously hard-failed) - bin/compile.php still compiles clean (exit 0) — general path not regressed - phpunit --filter Concat and StringConcat|EchoConcat|FloatConcat|EnumConcat are BYTE-IDENTICAL to master baseline (83/148/3E/2F/1S and 6/7/3E), i.e. this change introduces no regressions; those failures pre-exist. NOT fixed by this: the linked binary still aborts at runtime with TypeError: SuperglobalRefreshJitHelper::buildGetTable(): must return HashTable, int returned which reproduces in phpunit on clean master and is unrelated to concat. Filed separately — this commit only unblocks the compile. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This was referenced Jul 21, 2026
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.
Three independent changes, each verified.
1.
#21886— concat into a slot-less destination (release blocker)test/selfhost/compiler_helloworld_smoke/main.phpcould not compile at all:The native concat path promotes a
KIND_VALUEdestination to a real alloca before storing — but only when$result->type === TYPE_STRING. A destination whose inferred type never settled on string skipped the promotion and hit the raw store, writing a__string__*into an immediate (thei64constant is the value; there is no slot). The lowering already calledhelper->loadValue()on both inputs; nothing checked the output had anywhere to go.Now promotes when the destination is
KIND_VALUE, when its LLVM type is not__string__*, or when->valueis null — covering the mis-inferred case rather than only the known-good shape.Verified
bin/compile.phpstill compiles clean (exit 0) — general path not regressedphpunit --filter Concatand--filter "StringConcat|EchoConcat|FloatConcat|EnumConcat"are byte-identical to master baseline (83/148/3E/2F/1Sand6/7/3E) — I stashed the fix and re-ran to confirm those failures pre-existExplicitly not fixed here: the linked binary still aborts at runtime with
SuperglobalRefreshJitHelper::buildGetTable(): must return HashTable, int returned. That reproduces in PHPUnit on clean master, is unrelated to concat, and is filed as #21907. This commit unblocks the compile only.2. Self-host bundle compiles OOM'd at 1536M
bin/compile.phpraisesmemory_limitto 6G fortest/selfhost/bundles, but the bump sat inside theisset($options['-l'])branch — lint only. Compiling the same bundle with-oran at 1536M and died as:with nothing pointing at the cap. Hoisted so both paths get it. Verified on the exact command that previously OOM'd (0
Allowed memory sizelines).3. Measured AOT iteration costs documented
bootstrap-dev-workflow.md's only timing figure implied lowering work iterates in minutes. Measured: a three-lineecho $sscript takes ~43 min to AOT-compile, because the path emits and links the whole runtime regardless of source size — so "shrink the repro" buys nothing. Records the table and what actually helps: the helper-runtime cache (and why #21855's guard correctly makes lowering edits cold anyway), parallelising hypotheses, and onePHP_COMPILER_DUMP_IR=1dump instead of repeated compiles — which is how #21886 was located in a single run.Related
#21886 · #21907 · #21855 · #21860 · #16508
🤖 Generated with Claude Code