From 64cb8639c70eab83629428deee50f91396f3b45f Mon Sep 17 00:00:00 2001 From: PurHur Date: Wed, 26 Aug 2026 08:41:40 +0000 Subject: [PATCH] php-in-php: lazy TokenGetAll/Highlight/Hebrev + SuperglobalName from ensureFull (#35035) Drop dead no-op ensureStandaloneBodies calls and SuperglobalNameRuntime NestedJIT from ensureFullStandaloneBodies; call sites already ensureLinked (peer #34812). Co-authored-by: Cursor --- lib/JIT/Builtin/SuperglobalNameRuntime.php | 2 +- lib/JIT/Context.php | 14 +-- ...neLazyTokenHebrevSuperglobalShrinkTest.php | 85 +++++++++++++++++++ 3 files changed, 95 insertions(+), 6 deletions(-) create mode 100644 test/unit/ContextFullStandaloneLazyTokenHebrevSuperglobalShrinkTest.php diff --git a/lib/JIT/Builtin/SuperglobalNameRuntime.php b/lib/JIT/Builtin/SuperglobalNameRuntime.php index 0585047a4a5..352b035091e 100644 --- a/lib/JIT/Builtin/SuperglobalNameRuntime.php +++ b/lib/JIT/Builtin/SuperglobalNameRuntime.php @@ -17,7 +17,7 @@ * Owns `__compiler_is_superglobal_name` ABI module-locally: {@see getNamedFunction} first, then * {@see implementBridge}. Do not re-add empty always-on shells in {@see Type} — leftover decls * mint is_superglobal_name.1 (#31894 / #32122 / #33235). Context ensureMinimalUserStandaloneBodies - * must not NestedJIT this during thin hello-world init (#34812) — call sites + * and ensureFullStandaloneBodies must not NestedJIT this during init (#34812 / #35035) — call sites * {@see StringSuperglobalName::ensureLinked} / {@see \PHPCompiler\ext\standard\JitSuperglobalName} * already ensureLinked before lookup. Call-site ensureLinked restores the caller insert block * after bridge emit (thin AOT: parentless call / module verify — peer MetaTagsRuntime #27317). diff --git a/lib/JIT/Context.php b/lib/JIT/Context.php index 4b61359124b..8014ce559d9 100644 --- a/lib/JIT/Context.php +++ b/lib/JIT/Context.php @@ -2485,15 +2485,19 @@ private function ensureFullStandaloneBodies(): void Builtin\RewriteVarsRuntime::ensureStandaloneBodies($this); Builtin\DefineRuntime::ensureStandaloneBodies($this); Builtin\SuperglobalRefreshRuntime::ensureStandaloneBodies($this); - Builtin\SuperglobalNameRuntime::ensureLinked($this); + // SuperglobalName always-on removed (#35035): JitSuperglobalName / JIT.php + // StringSuperglobalName::ensureLinked before lookup (peer ensureMinimal #34812 / + // #33235). Full standalone must not NestedJIT is_superglobal_name during init — + // leftover Context NestedJIT vs Runtime ABI drift mints is_superglobal_name.1 + // (#31894 / #32122). Builtin\StringStrspn::ensureStandaloneBodies($this); // BootstrapCompileSmokeM3Emit / inventory argv {main} calls __compiler_file_get_contents (#15604). Builtin\StringFileGetContents::ensureStandaloneBodies($this); Builtin\StringReadfile::ensureStandaloneBodies($this); - Builtin\TokenGetAll::ensureStandaloneBodies($this); - Builtin\Highlight::ensureStandaloneBodies($this); - Builtin\Hebrev::ensureStandaloneBodies($this); - Builtin\Hebrevc::ensureStandaloneBodies($this); + // TokenGetAll / Highlight / Hebrev / Hebrevc always-on removed (#35035): each + // ensureStandaloneBodies is a no-op — helper LLVM compiles on first lowering + // (TokenGetAll::helperFunction / JitHighlight / JitHebrev). Do not re-add eager + // NestedJIT here (#31894 / #32122 .1 mint class). \PHPCompiler\ext\standard\JitStreamBucketKernel::ensureStandaloneBodies($this); } finally { Builtin\StreamIoRuntime::endStandaloneInitPhase(); diff --git a/test/unit/ContextFullStandaloneLazyTokenHebrevSuperglobalShrinkTest.php b/test/unit/ContextFullStandaloneLazyTokenHebrevSuperglobalShrinkTest.php new file mode 100644 index 00000000000..bd6b9b0528b --- /dev/null +++ b/test/unit/ContextFullStandaloneLazyTokenHebrevSuperglobalShrinkTest.php @@ -0,0 +1,85 @@ +assertStringContainsString('#35035', $context); + $fullPos = strpos($context, 'private function ensureFullStandaloneBodies'); + $this->assertNotFalse($fullPos); + $fullEnd = strpos($context, 'public function compileToFile', $fullPos); + $this->assertNotFalse($fullEnd); + $fullBody = substr($context, $fullPos, $fullEnd - $fullPos); + + foreach ([ + 'TokenGetAll::ensureStandaloneBodies($this)', + 'Highlight::ensureStandaloneBodies($this)', + 'Hebrev::ensureStandaloneBodies($this)', + 'Hebrevc::ensureStandaloneBodies($this)', + 'SuperglobalNameRuntime::ensureLinked($this)', + ] as $forbidden) { + $this->assertStringNotContainsString( + $forbidden, + $fullBody, + 'ensureFullStandaloneBodies must not eagerly '.$forbidden.' (#35035)' + ); + } + + // Still links refresh + strspn / file helpers used by inventory / standalone main. + $this->assertStringContainsString('SuperglobalRefreshRuntime::ensureStandaloneBodies($this)', $fullBody); + $this->assertStringContainsString('StringStrspn::ensureStandaloneBodies($this)', $fullBody); + } + + public function testCallSitesStillEnsureBeforeLookup(): void + { + $jit = (string) file_get_contents(__DIR__.'/../../ext/standard/JitSuperglobalName.php'); + $this->assertStringContainsString('StringSuperglobalName::ensureLinked($context)', $jit); + + $hebrev = (string) file_get_contents(__DIR__.'/../../ext/standard/JitHebrev.php'); + $this->assertStringContainsString('Hebrev::ensureLinked($context)', $hebrev); + + $hebrevc = (string) file_get_contents(__DIR__.'/../../ext/standard/JitHebrevc.php'); + $this->assertStringContainsString('HebrevcBuiltin::ensureLinked($context)', $hebrevc); + + $highlight = (string) file_get_contents(__DIR__.'/../../ext/standard/JitHighlight.php'); + $this->assertStringContainsString('Highlight::ensureLinked($context)', $highlight); + + $token = (string) file_get_contents(__DIR__.'/../../ext/tokenizer/JitTokenGetAll.php'); + $this->assertStringContainsString('TokenGetAll::helperFunction($context)', $token); + } + + public function testSuperglobalNameRuntimeDocumentsLazyFull(): void + { + $source = (string) file_get_contents(__DIR__.'/../../lib/JIT/Builtin/SuperglobalNameRuntime.php'); + $this->assertStringContainsString('#35035', $source); + $this->assertStringContainsString('ensureFullStandaloneBodies', $source); + } + + public function testNoNewRuntimeCForFullStandaloneLazy(): void + { + $runtimeDir = dirname(__DIR__, 2).'/lib/AOT/runtime'; + $this->assertFileDoesNotExist( + $runtimeDir.'/token_get_all.c', + 'must not add token_get_all.c for #35035 — PHP JIT bridges only' + ); + $this->assertFileDoesNotExist( + $runtimeDir.'/is_superglobal_name.c', + 'must not re-add is_superglobal_name.c for #35035' + ); + } +}