Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions lib/JIT/Builtin/SuperglobalRefreshRuntime.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
* Former NestedJIT {@see \PHPCompiler\Web\SuperglobalRefreshJitHelper} bridge removed (#21888):
* `: HashTable` returns TypeError under self-host stubs (`HashTable, int returned` — peer #20652 /
* #13571). Zend/VM SSOT remains {@see \PHPCompiler\Web\Superglobals} + the JitHelper unit tests.
*
* Context ensureFullStandaloneBodies must not eagerly link this during init (#35137) —
* {@see Context::compileToFile} (every LOAD_TYPE_STANDALONE) + JIT.php ensureLinked before
* resolve already ensure before `__superglobals__refresh` lookup. bootstrap-aot still
* ensureStandaloneBodies in ensureBootstrapAotStandaloneBodies. Leftover Context NestedJIT
* vs Runtime ABI drift mints superglobals_refresh.1 (#31894 / #32122).
* php-src: main/php_variables.c
*/
final class SuperglobalRefreshRuntime
Expand Down
24 changes: 15 additions & 9 deletions lib/JIT/Context.php
Original file line number Diff line number Diff line change
Expand Up @@ -2517,7 +2517,12 @@ private function ensureFullStandaloneBodies(): void
// standalone must not NestedJIT those ABIs during init — leftover Context
// NestedJIT vs Runtime ABI drift mints utf8_*.1 / define.1 /
// file_get_contents.1 / readfile.1 / strspn.1 (#31894 / #32122).
Builtin\SuperglobalRefreshRuntime::ensureStandaloneBodies($this);
// SuperglobalRefresh always-on removed (#35137 / peer CliArgv #35133): compileToFile
// ensures SuperglobalRefreshRuntime for every LOAD_TYPE_STANDALONE before main
// emits __superglobals__refresh; thin already used ensureUserScriptRefreshEmit /
// ensureStandaloneBodies; JIT.php ensureLinked before resolve. Full standalone
// must not NestedJIT __superglobals__refresh during init — leftover Context
// NestedJIT vs Runtime ABI drift mints superglobals_refresh.1 (#31894 / #32122).
// 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 —
Expand Down Expand Up @@ -2574,14 +2579,15 @@ public function compileToFile(string $file) {
// Every standalone main emits __phpc_cli_store_argv — link before that call.
// Was ensureFull-only for non-thin (#35133); thin already linked here (#34822).
Builtin\CliArgvRuntime::ensureStandaloneBodies($this);
if ($this->isThinStandaloneAotMain()) {
// IniRuntime always-on removed (#34848): JitIni / IniGet / IniSet / ErrorReporting /
// ZendDoubleStringRuntime / ExceptionThrowToStringSeed already ensureLinked before
// lookup (peer #34578 / #34822). Thin hello-world must not NestedJIT ini ABI during
// compileToFile pre-main — leftover Context NestedJIT vs Runtime ABI drift mints
// ini_get.1 / phpc_ini_*.1 (#31894 / #32122).
Builtin\SuperglobalRefreshRuntime::ensureUserScriptRefreshEmit($this);
}
// Every standalone main emits __superglobals__refresh — link before that call.
// Was ensureFull-only for non-thin (#35137); thin used ensureUserScriptRefreshEmit
// (#34822). Unify via ensureStandaloneBodies (→ JitSuperglobalRefreshKernel).
Builtin\SuperglobalRefreshRuntime::ensureStandaloneBodies($this);
// IniRuntime always-on removed from thin compileToFile (#34848): JitIni / IniGet /
// IniSet / ErrorReporting / ZendDoubleStringRuntime / ExceptionThrowToStringSeed
// already ensureLinked before lookup (peer #34578 / #34822). Thin hello-world must
// not NestedJIT ini ABI during compileToFile pre-main — leftover Context NestedJIT
// vs Runtime ABI drift mints ini_get.1 / phpc_ini_*.1 (#31894 / #32122).
}

// add main function
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,13 @@ public function testEnsureFullDropsEagerAssertGcProgressTriggerNestedJit(): void
);
}

// Still links echo / refresh used by standalone main (#35133: CliArgv at compileToFile).
// Still links echo; CliArgv + SuperglobalRefresh deferred (#35133 / #35137).
$this->assertStringContainsString('ValueEchoRuntime::ensureLinked($this)', $fullBody);
$this->assertStringContainsString('SuperglobalRefreshRuntime::ensureStandaloneBodies($this)', $fullBody);
$this->assertStringNotContainsString(
'SuperglobalRefreshRuntime::ensureStandaloneBodies($this)',
$fullBody,
'SuperglobalRefresh deferred to compileToFile (#35137)'
);
// compileToFile ensureLinked fills return-pending before clear.
$this->assertStringContainsString('JitReturnPending::ensureLinked($this)', $context);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,13 @@ public function testEnsureFullDropsEagerCliArgvNestedJit(): void
);
}

// Still links echo / refresh; StringFormat left ensureFull in #35130.
// Still links echo; SuperglobalRefresh deferred to compileToFile (#35137).
$this->assertStringContainsString('ValueEchoRuntime::ensureLinked($this)', $fullBody);
$this->assertStringContainsString('SuperglobalRefreshRuntime::ensureStandaloneBodies($this)', $fullBody);
$this->assertStringNotContainsString(
'SuperglobalRefreshRuntime::ensureStandaloneBodies($this)',
$fullBody,
'SuperglobalRefresh deferred to compileToFile (#35137)'
);
$this->assertStringNotContainsString(
'StringFormat::ensureStandaloneBodies($this)',
$fullBody,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,13 @@ public function testEnsureFullDropsEagerExceptionAndErrorBridge(): void
);
}

// Still links echo / refresh (#35130 StringFormat + #35133 CliArgv deferred).
// Still links echo; CliArgv + SuperglobalRefresh deferred (#35133 / #35137).
$this->assertStringContainsString('ValueEchoRuntime::ensureLinked($this)', $fullBody);
$this->assertStringContainsString('SuperglobalRefreshRuntime::ensureStandaloneBodies($this)', $fullBody);
$this->assertStringNotContainsString(
'SuperglobalRefreshRuntime::ensureStandaloneBodies($this)',
$fullBody,
'SuperglobalRefresh deferred to compileToFile (#35137)'
);
}

public function testStandaloneMainStillEnsuresBeforeClearAbort(): void
Expand Down
8 changes: 6 additions & 2 deletions test/unit/ContextFullStandaloneLazyGetenvShrinkTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,13 @@ public function testEnsureFullDropsEagerGetenvNestedJit(): void
);
}

// Still links echo / refresh (#35130 StringFormat + #35133 CliArgv deferred).
// Still links echo; CliArgv + SuperglobalRefresh deferred (#35133 / #35137).
$this->assertStringContainsString('ValueEchoRuntime::ensureLinked($this)', $fullBody);
$this->assertStringContainsString('SuperglobalRefreshRuntime::ensureStandaloneBodies($this)', $fullBody);
$this->assertStringNotContainsString(
'SuperglobalRefreshRuntime::ensureStandaloneBodies($this)',
$fullBody,
'SuperglobalRefresh deferred to compileToFile (#35137)'
);
}

public function testCallSitesStillEnsureBeforeLookup(): void
Expand Down
12 changes: 8 additions & 4 deletions test/unit/ContextFullStandaloneLazyJsonOffsetShrinkTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,14 @@ public function testEnsureFullDropsEagerJsonAndOffsetNestedJit(): void
);
}

// Still links refresh used by inventory / standalone main.
// StringStrspn left ensureFull in #35089 — do not re-assert eager strspn here.
// StringFormat left ensureFull in #35130 — do not re-assert eager format here.
$this->assertStringContainsString('SuperglobalRefreshRuntime::ensureStandaloneBodies($this)', $fullBody);
// Still links echo; SuperglobalRefresh deferred to compileToFile (#35137).
// StringStrspn / StringFormat already lazy — do not re-assert eager here.
$this->assertStringContainsString('ValueEchoRuntime::ensureLinked($this)', $fullBody);
$this->assertStringNotContainsString(
'SuperglobalRefreshRuntime::ensureStandaloneBodies($this)',
$fullBody,
'SuperglobalRefresh deferred to compileToFile (#35137)'
);
}

public function testCallSitesStillEnsureBeforeLookup(): void
Expand Down
8 changes: 6 additions & 2 deletions test/unit/ContextFullStandaloneLazyRandomBytesShrinkTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,13 @@ public function testEnsureFullDropsEagerRandomBytesNestedJit(): void
);
}

// Still links echo / refresh (#35130 StringFormat + #35133 CliArgv deferred).
// Still links echo; CliArgv + SuperglobalRefresh deferred (#35133 / #35137).
$this->assertStringContainsString('ValueEchoRuntime::ensureLinked($this)', $fullBody);
$this->assertStringContainsString('SuperglobalRefreshRuntime::ensureStandaloneBodies($this)', $fullBody);
$this->assertStringNotContainsString(
'SuperglobalRefreshRuntime::ensureStandaloneBodies($this)',
$fullBody,
'SuperglobalRefresh deferred to compileToFile (#35137)'
);
}

public function testCallSitesStillEnsureBeforeLookup(): void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,13 @@ public function testEnsureFullDropsEagerStdlibNestedJit(): void
);
}

// Still links echo / refresh used by standalone main (#35133: CliArgv at compileToFile).
// Still links echo; CliArgv + SuperglobalRefresh deferred (#35133 / #35137).
$this->assertStringContainsString('ValueEchoRuntime::ensureLinked($this)', $fullBody);
$this->assertStringContainsString('SuperglobalRefreshRuntime::ensureStandaloneBodies($this)', $fullBody);
$this->assertStringNotContainsString(
'SuperglobalRefreshRuntime::ensureStandaloneBodies($this)',
$fullBody,
'SuperglobalRefresh deferred to compileToFile (#35137)'
);
}

public function testCallSitesStillEnsureBeforeLookup(): void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,13 @@ public function testEnsureFullDropsEagerStreamAndFunctionStaticNestedJit(): void
);
}

// Still links echo / refresh used by standalone main (#35133: CliArgv at compileToFile).
// Still links echo; CliArgv + SuperglobalRefresh deferred (#35133 / #35137).
$this->assertStringContainsString('ValueEchoRuntime::ensureLinked($this)', $fullBody);
$this->assertStringContainsString('SuperglobalRefreshRuntime::ensureStandaloneBodies($this)', $fullBody);
$this->assertStringNotContainsString(
'SuperglobalRefreshRuntime::ensureStandaloneBodies($this)',
$fullBody,
'SuperglobalRefresh deferred to compileToFile (#35137)'
);
}

public function testCallSitesStillEnsureBeforeLookup(): void
Expand Down
8 changes: 6 additions & 2 deletions test/unit/ContextFullStandaloneLazyStringFormatShrinkTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,13 @@ public function testEnsureFullDropsEagerStringFormatNestedJit(): void
);
}

// Still links echo / refresh; CliArgv deferred to compileToFile in #35133.
// Still links echo; CliArgv + SuperglobalRefresh deferred (#35133 / #35137).
$this->assertStringContainsString('ValueEchoRuntime::ensureLinked($this)', $fullBody);
$this->assertStringContainsString('SuperglobalRefreshRuntime::ensureStandaloneBodies($this)', $fullBody);
$this->assertStringNotContainsString(
'SuperglobalRefreshRuntime::ensureStandaloneBodies($this)',
$fullBody,
'SuperglobalRefresh deferred to compileToFile (#35137)'
);
$this->assertStringNotContainsString(
'CliArgvRuntime::ensureStandaloneBodies($this)',
$fullBody,
Expand Down
124 changes: 124 additions & 0 deletions test/unit/ContextFullStandaloneLazySuperglobalRefreshShrinkTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
<?php

declare(strict_types=1);

namespace PHPCompiler\Test\Unit;

use PHPUnit\Framework\TestCase;

/**
* Drop Context::ensureFullStandaloneBodies always-on NestedJIT of SuperglobalRefreshRuntime
* (#35137 / peer CliArgv #35133 / ensureMinimal thin refresh).
*
* Full standalone must not NestedJIT __superglobals__refresh during init (#32122 .1 mint class).
* compileToFile ensures before main emits __superglobals__refresh for every standalone.
* php-src: main/php_variables.c
*/
final class ContextFullStandaloneLazySuperglobalRefreshShrinkTest extends TestCase
{
public function testEnsureFullDropsEagerSuperglobalRefreshNestedJit(): void
{
$context = (string) file_get_contents(__DIR__.'/../../lib/JIT/Context.php');
$this->assertStringContainsString('#35137', $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 ([
'SuperglobalRefreshRuntime::ensureStandaloneBodies($this)',
'SuperglobalRefreshRuntime::ensureLinked($this)',
'SuperglobalRefreshRuntime::ensureUserScriptRefreshEmit($this)',
'SuperglobalRefreshRuntime::implement($this)',
] as $forbidden) {
$this->assertStringNotContainsString(
$forbidden,
$fullBody,
'ensureFullStandaloneBodies must not eagerly '.$forbidden.' (#35137)'
);
}

// Still links echo; CliArgv + SuperglobalRefresh deferred to compileToFile.
$this->assertStringContainsString('ValueEchoRuntime::ensureLinked($this)', $fullBody);
$this->assertStringNotContainsString(
'CliArgvRuntime::ensureStandaloneBodies($this)',
$fullBody,
'CliArgv deferred to compileToFile (#35133)'
);
}

public function testCompileToFileEnsuresSuperglobalRefreshForAllStandalone(): void
{
$context = (string) file_get_contents(__DIR__.'/../../lib/JIT/Context.php');
$compilePos = strpos($context, 'public function compileToFile(string $file)');
$this->assertNotFalse($compilePos);
$compileSlice = substr($context, $compilePos, 2800);
$this->assertStringContainsString(
'LOAD_TYPE_STANDALONE === $this->loadType',
$compileSlice
);
$this->assertStringContainsString(
'SuperglobalRefreshRuntime::ensureStandaloneBodies($this)',
$compileSlice,
'compileToFile must ensure SuperglobalRefresh for every standalone (#35137)'
);
$this->assertStringContainsString('#35137', $compileSlice);
// Thin-only gate must not wrap SuperglobalRefresh ensure.
$this->assertDoesNotMatchRegularExpression(
'/isThinStandaloneAotMain\(\)\s*\{\s*Builtin\\\\SuperglobalRefreshRuntime::ensure/',
$compileSlice,
'SuperglobalRefresh ensure must not be thin-only (#35137)'
);
$this->assertStringNotContainsString(
'SuperglobalRefreshRuntime::ensureUserScriptRefreshEmit($this)',
$compileSlice,
'unified on ensureStandaloneBodies for all standalone (#35137)'
);
}

public function testBootstrapAotStillEnsuresSuperglobalRefresh(): void
{
$context = (string) file_get_contents(__DIR__.'/../../lib/JIT/Context.php');
$bootPos = strpos($context, 'private function ensureBootstrapAotStandaloneBodies');
$this->assertNotFalse($bootPos);
$bootEnd = strpos($context, 'private function ensureFullStandaloneBodies', $bootPos);
$this->assertNotFalse($bootEnd);
$bootBody = substr($context, $bootPos, $bootEnd - $bootPos);
$this->assertStringContainsString(
'SuperglobalRefreshRuntime::ensureStandaloneBodies($this)',
$bootBody,
'bootstrap-aot fixtures still ensure SuperglobalRefresh (#14459 / #35137)'
);
}

public function testJitEnsureLinkedBeforeResolve(): void
{
$jit = (string) file_get_contents(__DIR__.'/../../lib/JIT.php');
$this->assertStringContainsString(
'SuperglobalRefreshRuntime::ensureLinked($this->context)',
$jit,
'JIT.php must ensure lazily before resolve (#35137)'
);
}

public function testSuperglobalRefreshRuntimeDocumentsLazyFull(): void
{
$source = (string) file_get_contents(__DIR__.'/../../lib/JIT/Builtin/SuperglobalRefreshRuntime.php');
$this->assertStringContainsString('#35137', $source);
$this->assertStringContainsString('ensureFullStandaloneBodies', $source);
}

public function testNoNewRuntimeCForFullSuperglobalRefreshLazy(): void
{
$runtimeDir = dirname(__DIR__, 2).'/lib/AOT/runtime';
$this->assertFileDoesNotExist(
$runtimeDir.'/superglobals_refresh.c',
'must not re-add superglobals_refresh.c for #35137 — PHP JIT bridges only'
);
$this->assertFileDoesNotExist(
$runtimeDir.'/phpc_superglobals_refresh.c',
'must not add phpc_superglobals_refresh.c for #35137'
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,14 @@ public function testEnsureFullDropsEagerTokenHighlightHebrevAndSuperglobalName()
);
}

// Still links refresh used by inventory / standalone main.
// StringStrspn left ensureFull in #35089 — do not re-assert eager strspn here.
$this->assertStringContainsString('SuperglobalRefreshRuntime::ensureStandaloneBodies($this)', $fullBody);
// Still links echo; SuperglobalRefresh deferred to compileToFile (#35137).
// StringStrspn already lazy — do not re-assert eager here.
$this->assertStringContainsString('ValueEchoRuntime::ensureLinked($this)', $fullBody);
$this->assertStringNotContainsString(
'SuperglobalRefreshRuntime::ensureStandaloneBodies($this)',
$fullBody,
'SuperglobalRefresh deferred to compileToFile (#35137)'
);
}

public function testCallSitesStillEnsureBeforeLookup(): void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ public function testCompileToFileThinDropsEagerIniRuntime(): void
'compileToFile still ensures CliArgv for thin standalone (#34822)'
);
$this->assertStringContainsString(
'SuperglobalRefreshRuntime::ensureUserScriptRefreshEmit($this)',
'SuperglobalRefreshRuntime::ensureStandaloneBodies($this)',
$body,
'compileToFile still emits superglobal refresh for thin standalone'
'compileToFile ensures SuperglobalRefresh for every standalone (#35137)'
);
}

Expand Down
4 changes: 3 additions & 1 deletion test/unit/ExamplesHelloWorldAotRegressionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ public function testContextMinimalUserStandaloneBodiesDefersNestedJit(): void
{
$source = (string) file_get_contents(dirname(__DIR__, 2).'/lib/JIT/Context.php');
$this->assertStringContainsString('ensureMinimalUserStandaloneBodies', $source);
$this->assertStringContainsString('ensureUserScriptRefreshEmit', $source);
// compileToFile links refresh via ensureStandaloneBodies for every standalone (#35137).
$this->assertStringContainsString('SuperglobalRefreshRuntime::ensureStandaloneBodies', $source);
$refresh = (string) file_get_contents(dirname(__DIR__, 2).'/lib/JIT/Builtin/SuperglobalRefreshRuntime.php');
$this->assertStringContainsString('ensureUserScriptRefreshPrerequisites', $refresh);
$this->assertStringContainsString('ensureUserScriptRefreshEmit', $refresh);
$this->assertStringContainsString('JitSuperglobalRefreshKernel::implement', $refresh);
$this->assertStringContainsString('#35137', $refresh);
// StringHtmlspecialchars lazy (#34642); HtmlspecialcharsDecode / HtmlEntities /
// ErrorHandler / ExceptionHandler lazy (#34612).
$this->assertStringContainsString('#34642', $source);
Expand Down