Commit a135ac77366 for php.net
commit a135ac77366623e4320a40feda609b9908657f44
Author: Arnaud Le Blanc <arnaud.lb@gmail.com>
Date: Fri Mar 20 13:46:29 2026 +0100
TAILLCALL VM: Do not return in ZEND_VM_ENTER_EX, ZEND_VM_LEAVE
The TAILLCALL VM returns in ZEND_VM_ENTER_EX and ZEND_VM_LEAVE, but that's
not necessary.
Redefine ZEND_VM_ENTER_EX, ZEND_VM_LEAVE so that they tailcall instead.
This makes the Symfony and bench.php benchmarks about 1% and 3.5% faster.
Closes GH-21475
diff --git a/UPGRADING b/UPGRADING
index b7b160820bb..e55b9730f71 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -246,6 +246,7 @@ PHP 8.6 UPGRADE NOTES
creation of intermediate Closures, the overhead of calling userland
callbacks from internal functions and providing for better insight for the
JIT.
+ . The performance of the TAILCALL VM has been improved.
- DOM:
. Made splitText() faster and consume less memory.
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index cbfae90802c..7dfedca98d3 100644
Binary files a/Zend/zend_vm_execute.h and b/Zend/zend_vm_execute.h differ
diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php
index f8989b2336f..ed0256832d5 100755
--- a/Zend/zend_vm_gen.php
+++ b/Zend/zend_vm_gen.php
@@ -2126,6 +2126,8 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
out($f,"# undef ZEND_VM_RETURN\n");
out($f,"# undef ZEND_VM_DISPATCH_TO_HELPER\n");
out($f,"# undef ZEND_VM_INTERRUPT\n");
+ out($f,"# undef ZEND_VM_ENTER_EX\n");
+ out($f,"# undef ZEND_VM_LEAVE\n");
out($f,"\n");
out($f,"# define ZEND_VM_TAIL_CALL(call) ZEND_MUSTTAIL return call\n");
out($f,"# define ZEND_VM_CONTINUE() ZEND_VM_TAIL_CALL(opline->handler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU))\n");
@@ -2137,6 +2139,8 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
out($f," } while (0)\n");
out($f,"# define ZEND_VM_DISPATCH_TO_LEAVE_HELPER(helper) opline = &call_leave_op; SAVE_OPLINE(); ZEND_VM_CONTINUE()\n");
out($f,"# define ZEND_VM_INTERRUPT() ZEND_VM_TAIL_CALL(zend_interrupt_helper".($spec?"_SPEC":"")."_TAILCALL(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU))\n");
+ out($f,"# define ZEND_VM_ENTER_EX() ZEND_VM_INTERRUPT_CHECK(); ZEND_VM_CONTINUE()\n");
+ out($f,"# define ZEND_VM_LEAVE() ZEND_VM_CONTINUE()\n");
out($f,"\n");
out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV zend_interrupt_helper".($spec?"_SPEC":"")."_TAILCALL(ZEND_OPCODE_HANDLER_ARGS);\n");
out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_NULL_TAILCALL_HANDLER(ZEND_OPCODE_HANDLER_ARGS);\n");