diff --git a/ext/opcache/jit/zend_jit_arm64.dasc b/ext/opcache/jit/zend_jit_arm64.dasc index 40e7a5263db..3f895edf72d 100644 --- a/ext/opcache/jit/zend_jit_arm64.dasc +++ b/ext/opcache/jit/zend_jit_arm64.dasc @@ -1778,6 +1778,10 @@ static int zend_jit_interrupt_handler_stub(dasm_State **Dst) | //zend_interrupt_function(execute_data); | mov CARG1, FP | EXT_CALL zend_interrupt_function, TMP1 + | MEM_LOAD_64_ZTS ldr, REG0, executor_globals, exception, TMP1 + | cbz REG0, >1 + | EXT_CALL zend_jit_exception_in_interrupt_handler_helper, TMP1 + |1: | //ZEND_VM_ENTER(); | //execute_data = EG(current_execute_data); | MEM_LOAD_64_ZTS ldr, FP, executor_globals, current_execute_data, TMP1 diff --git a/ext/opcache/jit/zend_jit_disasm.c b/ext/opcache/jit/zend_jit_disasm.c index 621bf1991b8..9adc058ec8d 100644 --- a/ext/opcache/jit/zend_jit_disasm.c +++ b/ext/opcache/jit/zend_jit_disasm.c @@ -700,6 +700,7 @@ static int zend_jit_disasm_init(void) REGISTER_HELPER(zval_jit_update_constant_ex); #endif REGISTER_HELPER(zend_jit_free_trampoline_helper); + REGISTER_HELPER(zend_jit_exception_in_interrupt_handler_helper); #undef REGISTER_HELPER #ifndef _WIN32 diff --git a/ext/opcache/jit/zend_jit_helpers.c b/ext/opcache/jit/zend_jit_helpers.c index 8fa258008af..f07e5918f82 100644 --- a/ext/opcache/jit/zend_jit_helpers.c +++ b/ext/opcache/jit/zend_jit_helpers.c @@ -2545,6 +2545,23 @@ static void ZEND_FASTCALL zend_jit_free_trampoline_helper(zend_function *func) zend_free_trampoline(func); } +static void ZEND_FASTCALL zend_jit_exception_in_interrupt_handler_helper(void) +{ + if (EG(exception)) { + /* We have to UNDEF result, because ZEND_HANDLE_EXCEPTION is going to free it */ + const zend_op *throw_op = EG(opline_before_exception); + + if (throw_op + && throw_op->result_type & (IS_TMP_VAR|IS_VAR) + && throw_op->opcode != ZEND_ADD_ARRAY_ELEMENT + && throw_op->opcode != ZEND_ADD_ARRAY_UNPACK + && throw_op->opcode != ZEND_ROPE_INIT + && throw_op->opcode != ZEND_ROPE_ADD) { + ZVAL_UNDEF(ZEND_CALL_VAR(EG(current_execute_data), throw_op->result.var)); + } + } +} + static zend_string* ZEND_FASTCALL zend_jit_rope_end(zend_string **rope, uint32_t count) { zend_string *ret; diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 3768325825e..99ce096035e 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -1715,6 +1715,10 @@ static int zend_jit_interrupt_handler_stub(dasm_State **Dst) | mov aword A1, FP | EXT_CALL zend_interrupt_function, r0 |.endif + | MEM_CMP_ZTS aword, executor_globals, exception, 0, r0 + | je >1 + | EXT_CALL zend_jit_exception_in_interrupt_handler_helper, r0 + |1: | //ZEND_VM_ENTER(); | //execute_data = EG(current_execute_data); | MEM_LOAD_ZTS FP, aword, executor_globals, current_execute_data, r0