diff --git a/NEWS b/NEWS index 5c6f6e8db9e3..b30aa975d158 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,8 @@ PHP NEWS when $allow_string is false is now deprecated. (Daniel Scherzer) . Fixed bug GH-23232 (lone namespace separator asks the autoloader for an empty class name). (spawnia) + . Enabled the TAILCALL VM (--disable-gcc-global-regs) when building with GCC >= 16. + (henderkes) - CLI: . Fixed bug GH-23242 (PHP development server does not support Expect diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index e00aff17a924..674d1ed5b673 100755 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -2522,7 +2522,7 @@ function gen_vm_opcodes_header( $str .= "# define ZEND_VM_KIND\t\tZEND_VM_KIND_HYBRID\n"; } if ($GLOBALS["vm_kind_name"][ZEND_VM_GEN_KIND] === "ZEND_VM_KIND_HYBRID" || $GLOBALS["vm_kind_name"][ZEND_VM_GEN_KIND] === "ZEND_VM_KIND_CALL") { - $str .= "#elif defined(HAVE_MUSTTAIL) && defined(HAVE_PRESERVE_NONE) && (defined(__x86_64__) || defined(_M_X64) || defined(__aarch64__)) && defined(__clang__)\n"; + $str .= "#elif defined(HAVE_MUSTTAIL) && defined(HAVE_PRESERVE_NONE) && (defined(__x86_64__) || defined(__aarch64__))\n"; $str .= "# define ZEND_VM_KIND\t\tZEND_VM_KIND_TAILCALL\n"; $str .= "#else\n"; $str .= "# define ZEND_VM_KIND\t\tZEND_VM_KIND_CALL\n"; diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h index 4e0d3ec43d9c..1d204b9281f5 100644 --- a/Zend/zend_vm_opcodes.h +++ b/Zend/zend_vm_opcodes.h @@ -41,7 +41,7 @@ static const char *const zend_vm_kind_name[] = { /* HYBRID requires support for computed GOTO and global register variables*/ #elif (defined(__GNUC__) && defined(HAVE_GCC_GLOBAL_REGS)) # define ZEND_VM_KIND ZEND_VM_KIND_HYBRID -#elif defined(HAVE_MUSTTAIL) && defined(HAVE_PRESERVE_NONE) && (defined(__x86_64__) || defined(_M_X64) || defined(__aarch64__)) && defined(__clang__) +#elif defined(HAVE_MUSTTAIL) && defined(HAVE_PRESERVE_NONE) && (defined(__x86_64__) || defined(__aarch64__)) # define ZEND_VM_KIND ZEND_VM_KIND_TAILCALL #else # define ZEND_VM_KIND ZEND_VM_KIND_CALL diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index e91da6aeb8d3..85109c7d0e03 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -3100,23 +3100,10 @@ static int zend_real_jit_func(zend_op_array *op_array, zend_script *script, cons return FAILURE; } -/* Run-time JIT handler */ -#if ZEND_VM_KIND == ZEND_VM_KIND_CALL || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL -static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_runtime_jit(ZEND_OPCODE_HANDLER_ARGS) -#else -static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_runtime_jit(ZEND_OPCODE_HANDLER_ARGS) -#endif +/* GCC cannot tail-call from a function that uses setjmp. */ +static zend_never_inline void zend_runtime_jit_compile(zend_op_array *op_array) { -#if GCC_GLOBAL_REGS - zend_execute_data *execute_data; - zend_op *opline; -#else - const zend_op *orig_opline = opline; -#endif - - execute_data = EG(current_execute_data); - zend_op_array *op_array = &EX(func)->op_array; - opline = op_array->opcodes; + const zend_op *opline = op_array->opcodes; zend_jit_op_array_extension *jit_extension; bool do_bailout = 0; @@ -3154,6 +3141,23 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_runtime_jit(Z if (do_bailout) { zend_bailout(); } +} + +/* Run-time JIT handler */ +#if ZEND_VM_KIND == ZEND_VM_KIND_CALL || ZEND_VM_KIND == ZEND_VM_KIND_TAILCALL +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_runtime_jit(ZEND_OPCODE_HANDLER_ARGS) +#else +static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV zend_runtime_jit(ZEND_OPCODE_HANDLER_ARGS) +#endif +{ +#if GCC_GLOBAL_REGS + zend_execute_data *execute_data; +#else + const zend_op *orig_opline = opline; +#endif + + execute_data = EG(current_execute_data); + zend_runtime_jit_compile(&EX(func)->op_array); /* JIT-ed code is going to be called by VM */ #if GCC_GLOBAL_REGS