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");