diff --git a/lib/JIT/Builtin/StringXmlrpc.php b/lib/JIT/Builtin/StringXmlrpc.php index cf603b5f5e8..63f5935ec6d 100644 --- a/lib/JIT/Builtin/StringXmlrpc.php +++ b/lib/JIT/Builtin/StringXmlrpc.php @@ -14,8 +14,9 @@ use PHPLLVM\Builder; /** - * JIT/AOT link for __compiler_xmlrpc_* via Xmlrpc*JitHelper PHP (#19048). + * JIT/AOT link for __compiler_xmlrpc_* via Xmlrpc*JitHelper PHP (#19048, #32902). * + * Owns module-local ABI decls (getNamedFunction first) — Type always-on shells removed. * php-src: ext/xmlrpc/xmlrpc.c — PHP_FUNCTION(xmlrpc_encode), xmlrpc_decode */ final class StringXmlrpc diff --git a/lib/JIT/Builtin/Type.php b/lib/JIT/Builtin/Type.php index 77935e419e0..bba4ac4f817 100755 --- a/lib/JIT/Builtin/Type.php +++ b/lib/JIT/Builtin/Type.php @@ -937,23 +937,13 @@ public function register(): void { // (JitVmHelperLink::ensureBridge / Runtime implement); Type::initialize still // ensureLinked. Leftover Type empty decls vs Runtime ABI drift mint // json_encode.1 (#31894 / #32122). - $fntypeXmlrpcEncodeValue = $this->context->context->functionType( - $this->context->getTypeFromString('__string__*'), - false, - $valuePtr - ); - $fnXmlrpcEncodeValue = $this->context->module->addFunction( - '__compiler_xmlrpc_encode_value', - $fntypeXmlrpcEncodeValue - ); - $this->context->registerFunction('__compiler_xmlrpc_encode_value', $fnXmlrpcEncodeValue); - // __compiler_xmlrpc_encode_array always-on shell removed (#32250): leftover; - // StringXmlrpc ABI is __compiler_xmlrpc_encode_value + __compiler_xmlrpc_decode. - $fnXmlrpcDecode = $this->context->module->addFunction( - '__compiler_xmlrpc_decode', - $this->context->context->functionType($void, false, $strPtr, $valuePtr) - ); - $this->context->registerFunction('__compiler_xmlrpc_decode', $fnXmlrpcDecode); + // __compiler_xmlrpc_encode_value / __compiler_xmlrpc_decode always-on shells + // removed (#32902): __compiler_xmlrpc_encode_array already dropped (#32250). + // User-script xmlrpc_encode()/xmlrpc_decode() stay StringXmlrpc / + // ext/xmlrpc/JitXmlrpc. NestedJIT/AOT bridges getNamedFunction first + // (JitVmHelperLink::ensureBridge / decode emit addFunction if absent); + // Type::initialize still ensureLinked. Leftover Type empty decls vs Runtime + // ABI drift mint xmlrpc_encode.1 (#31894 / #32122). $fntypeSerializeHashtable = $this->context->context->functionType( $this->context->getTypeFromString('__string__*'), false, @@ -1113,6 +1103,7 @@ public function initialize(): void { StringHashAlgos::ensureLinked($this->context); StringJsonEncode::ensureLinked($this->context); StringJsonDecode::ensureLinked($this->context); + StringXmlrpc::ensureLinked($this->context); StringQuotPrint::ensureLinked($this->context); StringUtf8Latin1::ensureLinked($this->context); StringCslashes::ensureStandaloneBodies($this->context); diff --git a/test/unit/TypeDeadCompilerAbiRuntimeShrinkTest.php b/test/unit/TypeDeadCompilerAbiRuntimeShrinkTest.php index d13f1462180..92e3a017f8c 100644 --- a/test/unit/TypeDeadCompilerAbiRuntimeShrinkTest.php +++ b/test/unit/TypeDeadCompilerAbiRuntimeShrinkTest.php @@ -44,7 +44,7 @@ public function testTypeBuiltinDropsLeftoverAlwaysOnDeadCompilerAbis(): void } $this->assertStringContainsString("addFunction('exit'", $type); $this->assertStringContainsString("addFunction('abort'", $type); - $this->assertStringContainsString("registerFunction('__compiler_xmlrpc_encode_value'", $type); + // __compiler_xmlrpc_encode_value always-on shell removed (#32902); ownership in StringXmlrpc. $this->assertStringContainsString("registerFunction('__compiler_number_format'", $type); } diff --git a/test/unit/TypeDeadXmlrpcAbiRuntimeShrinkTest.php b/test/unit/TypeDeadXmlrpcAbiRuntimeShrinkTest.php new file mode 100644 index 00000000000..fde7bd15c4e --- /dev/null +++ b/test/unit/TypeDeadXmlrpcAbiRuntimeShrinkTest.php @@ -0,0 +1,75 @@ + */ + private function droppedAbis(): array + { + return [ + '__compiler_xmlrpc_encode_value', + '__compiler_xmlrpc_decode', + ]; + } + + public function testTypeBuiltinDropsLeftoverAlwaysOnXmlrpcAbis(): void + { + $type = (string) file_get_contents(__DIR__.'/../../lib/JIT/Builtin/Type.php'); + $this->assertStringContainsString('#32902', $type); + foreach ($this->droppedAbis() as $sym) { + $this->assertDoesNotMatchRegularExpression( + '/addFunction\(\s*[\'"]'.preg_quote($sym, '/').'[\'"]/', + $type, + "Builtin\\Type must not always-declare {$sym} (#32902)" + ); + $this->assertStringNotContainsString( + "registerFunction('{$sym}'", + $type, + "Builtin\\Type must not always-register {$sym} (#32902)" + ); + } + $this->assertStringContainsString("addFunction('exit'", $type); + $this->assertStringContainsString("addFunction('abort'", $type); + $this->assertStringContainsString("registerFunction('__compiler_convert_uuencode'", $type); + $this->assertStringContainsString('StringXmlrpc::ensureLinked', $type); + } + + public function testRuntimeOwnerDeclaresXmlrpcAbisModuleLocally(): void + { + $owner = (string) file_get_contents(__DIR__.'/../../lib/JIT/Builtin/StringXmlrpc.php'); + $this->assertStringContainsString('#32902', $owner); + $this->assertStringContainsString('getNamedFunction', $owner); + foreach ($this->droppedAbis() as $sym) { + $this->assertStringContainsString($sym, $owner, "{$sym} must remain owned by StringXmlrpc (#32902)"); + } + $jit = (string) file_get_contents(__DIR__.'/../../ext/xmlrpc/JitXmlrpc.php'); + $this->assertStringContainsString('StringXmlrpc::ensureEncodeLinked', $jit); + $this->assertStringContainsString('StringXmlrpc::ensureDecodeLinked', $jit); + } + + public function testTypeInitializeStillEnsureLinksXmlrpcRuntime(): void + { + $type = (string) file_get_contents(__DIR__.'/../../lib/JIT/Builtin/Type.php'); + $this->assertStringContainsString('StringXmlrpc::ensureLinked($this->context)', $type); + } + + public function testNoNewRuntimeCForXmlrpcAbis(): void + { + $this->assertFileDoesNotExist(dirname(__DIR__, 2).'/lib/AOT/runtime/xmlrpc.c'); + $this->assertFileDoesNotExist(dirname(__DIR__, 2).'/runtime/xmlrpc.c'); + $this->assertFileDoesNotExist(dirname(__DIR__, 2).'/lib/AOT/runtime/xmlrpc_encode.c'); + $this->assertFileDoesNotExist(dirname(__DIR__, 2).'/runtime/xmlrpc_encode.c'); + } +}