diff --git a/lib/JIT/Builtin/GetHeadersRuntime.php b/lib/JIT/Builtin/GetHeadersRuntime.php index 6a00c408561..d49ac6d278d 100644 --- a/lib/JIT/Builtin/GetHeadersRuntime.php +++ b/lib/JIT/Builtin/GetHeadersRuntime.php @@ -4,6 +4,7 @@ namespace PHPCompiler\JIT\Builtin; +use PHPCompiler\JIT\BasicBlockHelper; use PHPCompiler\JIT\Context; use PHPCompiler\JIT\JitNestedHelperCoerce; use PHPCompiler\JIT\JitVmHelperLink; @@ -13,6 +14,8 @@ * JIT/AOT link for __compiler_get_headers via GetHeadersJitHelper PHP (#9212, #24633). * * Helper compile: {@see JitVmHelperLink::ensureCompiled} (peer StreamFstat #24586 / StringQuotPrint #24620). + * Call-site {@see ensureLinked} restores the caller insert block after bridge emit + * (thin AOT: "Current basic block has no parent function", #27317 / peer #27088). * SSOT {@see \PHPCompiler\ext\standard\VmHttpFetchNative} / {@see \PHPCompiler\ext\standard\VmHttpHeaders}. * php-src: ext/standard/head.c — PHP_FUNCTION(get_headers) */ @@ -43,10 +46,16 @@ public static function implement(Context $context): void return; } + // Preserve caller insert block — clearInsertionPosition alone orphans mid-emit (#27317 / #27088). + $savedInsert = BasicBlockHelper::tryGetInsertBlock($context); self::ensureJitHelperCompiled($context); self::implementGetHeadersBridge($context); self::registerLinkedRuntime($context); - $context->builder->clearInsertionPosition(); + if (null !== $savedInsert) { + BasicBlockHelper::restoreInsertBlock($context, $savedInsert); + } else { + $context->builder->clearInsertionPosition(); + } } private static function implementGetHeadersBridge(Context $context): void diff --git a/test/fixtures/aot/cases/get_headers_refused_connection.phpt b/test/fixtures/aot/cases/get_headers_refused_connection.phpt new file mode 100644 index 00000000000..f34641b4e27 --- /dev/null +++ b/test/fixtures/aot/cases/get_headers_refused_connection.phpt @@ -0,0 +1,7 @@ +--TEST-- +AOT get_headers() refused connection returns false (#27317, ext/standard/head.c) +--FILE-- +assertStringContainsString('GetHeadersJitHelper', $source); $this->assertStringContainsString('JitVmHelperLink::ensureCompiled', $source); $this->assertStringContainsString('JitVmHelperLink::lookupCompiled', $source); + $this->assertStringContainsString('BasicBlockHelper::restoreInsertBlock', $source); $this->assertStringNotContainsString('VmHttpFetchPure::request', $source); $this->assertStringNotContainsString('NestedJitCompileScope::run', $source); $this->assertStringNotContainsString('parseAndCompile', $source); @@ -29,7 +30,7 @@ public function testGetHeadersRuntimeRoutesThroughGetHeadersJitHelper(): void $this->assertStringNotContainsString('use PHPCompiler\\JIT;', $source); $lineCount = \substr_count($source, "\n"); - $this->assertLessThan(120, $lineCount, 'GetHeadersRuntime must be a thin bridge'); + $this->assertLessThan(130, $lineCount, 'GetHeadersRuntime must be a thin bridge'); } public function testJitGetHeadersUsesCompilerGetHeadersAbi(): void