Skip to content
Merged
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
39 changes: 26 additions & 13 deletions lib/JIT/Context.php
Original file line number Diff line number Diff line change
Expand Up @@ -2349,7 +2349,7 @@ private function ensureMinimalUserStandaloneBodies(): void
// #20966 / #20982 / #20998). ensureMinimal is reached for user-script AOT and via
// bootstrap-aot ensureBootstrapAotStandaloneBodies; the old `!$isUserScriptAot`
// guard only NestedJIT Stream* on the bootstrap path and still risked feof.1 /
// stream_bucket_*.1 (#31894 / #32122). Full standalone still ensureLinked below.
// stream_bucket_*.1 (#31894 / #32122). Full standalone drop is #35086 (peer #35073).
// StringTriggerError always-on removed (#34641): trigger_error_.php / JitBuiltinWarning /
// JitIncDec / HashTableResourceKeyLlvm / JitTriggerErrorKernel already ensureLinked before
// lookup (peer #34631 / #33234). JitTriggerErrorKernel restores builder insert mid-{main}.
Expand Down Expand Up @@ -2417,9 +2417,12 @@ private function ensureFullStandaloneBodies(): void
try {
ExceptionBridge::ensureStandaloneBodies($this);
ErrorBridge::ensureStandaloneBodies($this);
// NestedJIT StreamLifecycle/StreamRead helpers during full standalone init (#20966 / #20982).
Builtin\StreamLifecycleRuntime::ensureLinked($this);
Builtin\StreamReadRuntime::ensureLinked($this);
// StreamLifecycle / StreamRead always-on removed (#35086): JitFclose / JitFeof /
// JitFflush / JitFgetc / JitFgets / StringVarDump / StringPrintR / SilenceRuntime /
// StreamReadJit / StringFgetcsvJit already ensureLinked(ForUserScriptLowering)
// before lookup (peer ensureMinimal #34836 / #20966 / #20982). Full standalone
// must not NestedJIT feof/fclose/fflush/fgets during init — leftover Context
// NestedJIT vs Runtime ABI drift mints feof.1 / fflush.1 (#31894 / #32122).
// StringTriggerError / AssertFail / AssertOptions / JitReturnPending always-on
// removed (#35073): JitAssert / JitAssertOptions / TryCatchHelper /
// AssertFail::ensureLinked (→ StringTriggerError) already ensure before lookup
Expand Down Expand Up @@ -2479,14 +2482,22 @@ private function ensureFullStandaloneBodies(): void
// (peer #35035). Do not NestedJIT offset / scalar-dim helpers during full init.
// UndefinedVariableRuntime: ensureLinked only — emitWarningForName uses __compiler_trigger_error
// (call sites / AssertFail ensure StringTriggerError; avoid duplicate bodies — #10524 / #35073).
// NestedJIT StreamFilterJitHelper during full standalone init (#21041 / peer #20998).
Builtin\StreamFilter::ensureLinked($this);
// GcToggle / FunctionStatic / GcCollect / ProgressNote / LastError always-on
// removed (#35073): JitGcToggle / JitGcCollectCycles / ProgressNoteRuntime /
// JitErrorGetLast / JitTriggerErrorKernel / Object_ delref already ensureLinked
// before lookup (peer ensureMinimal #34605 / #34631). Full standalone must not
// NestedJIT gc_* / progress_note / last_error during init (#31894 / #32122).
Builtin\FunctionStaticRuntime::ensureStandaloneBodies($this);
// StreamFilter / StreamBucket always-on removed (#35086): StreamIoJit /
// StreamReadJit / StreamReadRuntime / JitStreamBucket / JitIsResource already
// StreamFilter::ensureLinked / StreamBucket::ensureLinked before lookup
// (peer ensureMinimal #34836 / #21041 / #20998). Full standalone must not
// NestedJIT stream_filter_* / stream_bucket_* during init — leftover Context
// NestedJIT vs Runtime ABI drift mints stream_bucket_*.1 (#31894 / #32122).
// GcToggle / GcCollect / ProgressNote / LastError always-on removed (#35073):
// JitGcToggle / JitGcCollectCycles / ProgressNoteRuntime / JitErrorGetLast /
// JitTriggerErrorKernel / Object_ delref already ensureLinked before lookup
// (peer ensureMinimal #34605 / #34631). Full standalone must not NestedJIT
// gc_* / progress_note / last_error during init (#31894 / #32122).
// FunctionStatic always-on removed (#35086): FunctionStaticHelper::ensureRuntime
// already FunctionStaticRuntime::ensureLinked before phpc_fn_static_* lookup
// (#10173). Full standalone must not emit fn-static table ABI during init —
// leftover Context NestedJIT vs Runtime ABI drift mints phpc_fn_static_*.1
// (#31894 / #32122).
Builtin\StringUtf8Latin1::ensureStandaloneBodies($this);
Builtin\RewriteVarsRuntime::ensureStandaloneBodies($this);
Builtin\DefineRuntime::ensureStandaloneBodies($this);
Expand All @@ -2504,7 +2515,9 @@ private function ensureFullStandaloneBodies(): void
// 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);
// JitStreamBucketKernel always-on removed (#35086): StreamBucket::ensureLinked →
// JitStreamBucketKernel::ensureLinked (JitStreamBucket / JitIsResource) already
// implement before lookup (peer #34836). Do not NestedJIT stream_bucket_* here.
} finally {
Builtin\StreamIoRuntime::endStandaloneInitPhase();
}
Expand Down
88 changes: 88 additions & 0 deletions test/unit/ContextFullStandaloneLazyStreamRuntimeShrinkTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php

declare(strict_types=1);

namespace PHPCompiler\Test\Unit;

use PHPUnit\Framework\TestCase;

/**
* Drop Context::ensureFullStandaloneBodies always-on NestedJIT of StreamLifecycle /
* StreamRead / StreamFilter / StreamBucket / FunctionStatic (#35086 / peers #34836 / #35073).
*
* Full standalone must not NestedJIT feof/fclose/stream_bucket_/phpc_fn_static_ during
* init (#32122 .1 mint class). Call sites already ensureLinked before lookup.
*/
final class ContextFullStandaloneLazyStreamRuntimeShrinkTest extends TestCase
{
public function testEnsureFullDropsEagerStreamAndFunctionStaticNestedJit(): void
{
$context = (string) file_get_contents(__DIR__.'/../../lib/JIT/Context.php');
$this->assertStringContainsString('#35086', $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 ([
'StreamLifecycleRuntime::ensureLinked($this)',
'StreamReadRuntime::ensureLinked($this)',
'StreamFilter::ensureLinked($this)',
'JitStreamBucketKernel::ensureStandaloneBodies($this)',
'FunctionStaticRuntime::ensureStandaloneBodies($this)',
] as $forbidden) {
$this->assertStringNotContainsString(
$forbidden,
$fullBody,
'ensureFullStandaloneBodies must not eagerly '.$forbidden.' (#35086)'
);
}

// Still links echo / argv / refresh used by standalone main.
$this->assertStringContainsString('ValueEchoRuntime::ensureLinked($this)', $fullBody);
$this->assertStringContainsString('CliArgvRuntime::ensureStandaloneBodies($this)', $fullBody);
$this->assertStringContainsString('SuperglobalRefreshRuntime::ensureStandaloneBodies($this)', $fullBody);
}

public function testCallSitesStillEnsureBeforeLookup(): void
{
$checks = [
'ext/standard/JitFclose.php' => 'StreamLifecycleRuntime::ensureLinkedForUserScriptLowering',
'ext/standard/JitFeof.php' => 'StreamLifecycleRuntime::ensureLinkedForUserScriptLowering',
'ext/standard/JitFgetc.php' => 'StreamReadRuntime::ensureLinked',
'ext/standard/JitFgets.php' => 'StreamReadRuntime::ensureLinked',
'ext/standard/JitStreamBucket.php' => 'StreamBucket::ensureLinked',
'ext/standard/JitIsResource.php' => 'StreamBucket::ensureLinked',
'lib/JIT/Builtin/StringVarDump.php' => 'StreamLifecycleRuntime::ensureLinked',
'lib/JIT/Builtin/StringPrintR.php' => 'StreamLifecycleRuntime::ensureLinked',
'lib/JIT/Builtin/SilenceRuntime.php' => 'StreamLifecycleRuntime::ensureLinked',
'lib/JIT/Builtin/StreamReadJit.php' => 'StreamFilter::ensureLinked',
'lib/JIT/Builtin/StreamIoJit.php' => 'StreamFilter::ensureLinked',
'lib/JIT/FunctionStaticHelper.php' => 'FunctionStaticRuntime::ensureLinked',
];
foreach ($checks as $rel => $needle) {
$path = __DIR__.'/../../'.$rel;
$this->assertFileExists($path, $rel);
$source = (string) file_get_contents($path);
$this->assertStringContainsString($needle, $source, $rel.' must ensure lazily (#35086)');
}
}

public function testNoNewRuntimeCForFullStreamLazy(): void
{
$runtimeDir = dirname(__DIR__, 2).'/lib/AOT/runtime';
$this->assertFileDoesNotExist(
$runtimeDir.'/stream_lifecycle.c',
'must not add stream_lifecycle.c for #35086 — PHP JIT bridges only'
);
$this->assertFileDoesNotExist(
$runtimeDir.'/stream_bucket.c',
'must not add stream_bucket.c for #35086'
);
$this->assertFileDoesNotExist(
$runtimeDir.'/function_static.c',
'must not add function_static.c for #35086'
);
}
}
19 changes: 6 additions & 13 deletions test/unit/ContextMinimalStandaloneLazyStreamRuntimeShrinkTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,20 +47,8 @@ public function testEnsureMinimalDropsEagerStreamRuntime(): void
);
}

public function testCallSitesAndFullStandaloneStillEnsure(): void
public function testCallSitesStillEnsureLazily(): void
{
$context = (string) file_get_contents(__DIR__.'/../../lib/JIT/Context.php');
$this->assertStringContainsString(
'StreamLifecycleRuntime::ensureLinked($this)',
$context,
'ensureFullStandaloneBodies still ensureLinked StreamLifecycle (#34836)'
);
$this->assertStringContainsString(
'StreamReadRuntime::ensureLinked($this)',
$context,
'ensureFullStandaloneBodies still ensureLinked StreamRead (#34836)'
);

$checks = [
'ext/standard/JitFclose.php' => 'StreamLifecycleRuntime::ensureLinkedForUserScriptLowering',
'ext/standard/JitFeof.php' => 'StreamLifecycleRuntime::ensureLinkedForUserScriptLowering',
Expand All @@ -78,6 +66,11 @@ public function testCallSitesAndFullStandaloneStillEnsure(): void
$source = (string) file_get_contents($path);
$this->assertStringContainsString($needle, $source, $rel.' must ensure lazily (#34836)');
}

// Full standalone also dropped Stream* (#35086) — guard lives in
// ContextFullStandaloneLazyStreamRuntimeShrinkTest.
$context = (string) file_get_contents(__DIR__.'/../../lib/JIT/Context.php');
$this->assertStringContainsString('#35086', $context);
}

public function testNoNewRuntimeCForMinimalStreamLazy(): void
Expand Down
Loading