From cfb21e8dc1a61497e1e6bc0d2499a9042605cfd4 Mon Sep 17 00:00:00 2001 From: Hao Sun Date: Mon, 13 Sep 2021 11:35:12 +0300 Subject: [PATCH] JIT: Fixed exit from CALL VM with GCC Global Register Variables PHP JIT supports three configurations: HYRBID, CALL with global register variables feature(CALL+GRV for short), and CALL+noGRV. CALL+GRV mode can be built with the following commands: ``` php Zend/zend_vm_gen.php --with-vm-kind=CALL ./buildconf -f; ./configure; make ``` About 230 test cases failed for tracing JIT under CALL+GRV mode on both x86 and arm64 machines. For CALL+GRV mode, the condition to determine whether the execution of an oparray is finished, is "opline == NULL". See function execute_ex() around line "if (UNEXPECTED(!OPLINE)) {". However, such cleanup operation is missing for the JIT wrapper zend_jit_trace_counter_helper(), and the trace_halt stub function. Tests: 1. test cases: all .phpt test cases under "Zend/tests/ tests/ ext/opcache/tests/jit/". 2. both JIT/x86 and JIT/arm64: function JIT, tracing JIT and tracing JIT with "--repeat 3" 3. execution modes: NTS/ZTS, HYBRID/CALL+GRV/CALL+noGRV In my local test, these test cases passed under all JIT configrations. --- ext/opcache/jit/zend_jit_vm_helpers.c | 5 ++++- ext/opcache/jit/zend_jit_x86.dasc | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ext/opcache/jit/zend_jit_vm_helpers.c b/ext/opcache/jit/zend_jit_vm_helpers.c index d919b59c9e8..0a8de03e481 100644 --- a/ext/opcache/jit/zend_jit_vm_helpers.c +++ b/ext/opcache/jit/zend_jit_vm_helpers.c @@ -308,7 +308,10 @@ static zend_always_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_trace_c if (UNEXPECTED(*(ZEND_OP_TRACE_INFO(opline, offset)->counter) <= 0)) { *(ZEND_OP_TRACE_INFO(opline, offset)->counter) = ZEND_JIT_COUNTER_INIT; if (UNEXPECTED(zend_jit_trace_hot_root(execute_data, opline) < 0)) { -#ifndef HAVE_GCC_GLOBAL_REGS +#ifdef HAVE_GCC_GLOBAL_REGS + opline = NULL; + return; +#else return -1; #endif } diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 88cf3a56790..d4c0a8e715b 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -2424,7 +2424,8 @@ static int zend_jit_trace_halt_stub(dasm_State **Dst) | EXT_JMP zend_jit_halt_op->handler, r0 } else if (GCC_GLOBAL_REGS) { | add r4, SPAD // stack alignment - | ret // PC must be zero + | xor IP, IP // PC must be zero + | ret } else { | mov FP, aword T2 // restore FP | mov RX, aword T3 // restore IP