From 430b46f3ab9642c24537951b6eff3e39ac98cec5 Mon Sep 17 00:00:00 2001 From: PurHur Date: Mon, 27 Jul 2026 14:06:16 +0000 Subject: [PATCH] php-in-php: route StringCaseCompare through JitVmHelperLink (#23862) Replace hand-rolled NestedJitCompileScope::run in strcasecmp/strncasecmp lowering with JitVmHelperLink::ensureCompiled + lookupCompiled so helper compile matches peer migrations (StringStrtotime #23862) and gains helper- runtime cache hits. Co-authored-by: Cursor --- lib/JIT/Builtin/StringCaseCompare.php | 45 +++++------------------ test/unit/StrcasecmpRuntimeShrinkTest.php | 15 +++++++- 2 files changed, 24 insertions(+), 36 deletions(-) diff --git a/lib/JIT/Builtin/StringCaseCompare.php b/lib/JIT/Builtin/StringCaseCompare.php index bb0f9c6687d..c4e2ded0f0b 100644 --- a/lib/JIT/Builtin/StringCaseCompare.php +++ b/lib/JIT/Builtin/StringCaseCompare.php @@ -4,17 +4,17 @@ namespace PHPCompiler\JIT\Builtin; -use PHPCompiler\JIT; use PHPCompiler\JIT\BasicBlockHelper; use PHPCompiler\JIT\Context; -use PHPCompiler\JIT\NestedJitCompileScope; +use PHPCompiler\JIT\JitVmHelperLink; use PHPLLVM\Builder; use PHPLLVM\Value; use PHPLLVM\Value\Function_ as LlvmFunction; /** - * JIT/AOT link for strcasecmp/strncasecmp via CaseCompareJitHelper PHP (#15225). + * JIT/AOT link for strcasecmp/strncasecmp via CaseCompareJitHelper PHP (#15225, #23862). * + * Helper compile: {@see JitVmHelperLink::ensureCompiled} (peer StringStrtotime #23832). * Replaces libc `strcasecmp`/`strncasecmp` LLVM lookups in ext/standard. Keeps i8* ABI. * SSOT: {@see \PHPCompiler\ext\standard\VmString} */ @@ -171,42 +171,17 @@ private static function stringFromCstr(Context $context, Value $cstr): Value private static function helperFunction(Context $context, string $logical): LlvmFunction { self::ensureJitHelperCompiled($context); - $lc = \strtolower($logical); - $fn = $context->functions[$lc] ?? null; - if (null === $fn) { - throw new \LogicException($logical.' missing after CaseCompareJitHelper compile (#15225)'); - } - return $fn; + return JitVmHelperLink::lookupCompiled($context, $logical, '#23862'); } private static function ensureJitHelperCompiled(Context $context): void { - $missing = false; - foreach (self::COMPILED_HELPERS as $logical) { - if (!isset($context->functions[\strtolower($logical)])) { - $missing = true; - break; - } - } - if (!$missing) { - return; - } - - $runtime = $context->runtime; - $path = \dirname(__DIR__, 3).self::HELPER_PATH; - NestedJitCompileScope::run($context, static function () use ($context, $runtime, $path): void { - $block = $runtime->parseAndCompile((string) \file_get_contents($path), 'CaseCompareJitHelper.php'); - if (null === $block) { - throw new \LogicException('CaseCompareJitHelper.php parseAndCompile failed (#15225)'); - } - $jit = new JIT($context); - $jit->compile($block); - }); - foreach (self::COMPILED_HELPERS as $logical) { - if (!isset($context->functions[\strtolower($logical)])) { - throw new \LogicException($logical.' was not compiled for JIT (#15225)'); - } - } + JitVmHelperLink::ensureCompiled( + $context, + self::HELPER_PATH, + self::COMPILED_HELPERS, + '#23862' + ); } } diff --git a/test/unit/StrcasecmpRuntimeShrinkTest.php b/test/unit/StrcasecmpRuntimeShrinkTest.php index 2683cc20046..1a76ff19892 100644 --- a/test/unit/StrcasecmpRuntimeShrinkTest.php +++ b/test/unit/StrcasecmpRuntimeShrinkTest.php @@ -8,9 +8,22 @@ use PHPCompiler\ext\standard\VmString; use PHPUnit\Framework\TestCase; -/** strcasecmp()/strncasecmp() JIT routes through CaseCompareJitHelper PHP not libc LLVM (#15225). */ +/** strcasecmp()/strncasecmp() JIT routes through CaseCompareJitHelper PHP not libc LLVM (#15225, #23862). */ final class StrcasecmpRuntimeShrinkTest extends TestCase { + public function testStringCaseCompareUsesJitVmHelperLinkNotHandRolledNestedJit(): void + { + $source = (string) file_get_contents(__DIR__.'/../../lib/JIT/Builtin/StringCaseCompare.php'); + $this->assertStringContainsString('CaseCompareJitHelper', $source); + $this->assertStringContainsString('JitVmHelperLink::ensureCompiled', $source); + $this->assertStringContainsString('JitVmHelperLink::lookupCompiled', $source); + $this->assertStringNotContainsString('NestedJitCompileScope::run', $source); + $this->assertStringNotContainsString('parseAndCompile', $source); + $this->assertStringNotContainsString('new JIT(', $source); + $this->assertStringNotContainsString('use PHPCompiler\\JIT;', $source); + $this->assertStringNotContainsString('UserScriptAotDeferNestedJit', $source); + } + public function testStrcasecmpUsesPhpBridgeNotLibcOnly(): void { $builtin = (string) file_get_contents(__DIR__.'/../../ext/standard/strcasecmp.php');