From 3079a7230c4fbf9c279703441b6218b60baf710a Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Wed, 13 May 2026 12:29:31 -0400 Subject: [PATCH] JIT: Resolve escape_if_undef orig_handler via jit->current_op_array zend_jit_escape_if_undef received an op_array pointer captured at parent-trace compile time. That pointer can go stale by the time a side trace compiles for the exit. Drop the parameter and read jit->current_op_array instead; zend_jit_trace_start sets it for trace compilation, and zend_jit_trace_exit_to_vm now seeds it from exit_info->op_array so the deoptimizer path has it too. Closes GH-21710 --- ext/opcache/jit/zend_jit_ir.c | 4 ++-- ext/opcache/jit/zend_jit_trace.c | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index f99605ee4208..08b065404e08 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -8068,7 +8068,7 @@ static int zend_jit_defined(zend_jit_ctx *jit, const zend_op *opline, uint8_t sm return 1; } -static int zend_jit_escape_if_undef(zend_jit_ctx *jit, int var, uint32_t flags, const zend_op *opline, const zend_op_array *op_array, int8_t reg) +static int zend_jit_escape_if_undef(zend_jit_ctx *jit, int var, uint32_t flags, const zend_op *opline, int8_t reg) { zend_jit_addr reg_addr = ZEND_ADDR_REF_ZVAL(zend_jit_deopt_rload(jit, IR_ADDR, reg)); ir_ref if_def = ir_IF(jit_Z_TYPE(jit, reg_addr)); @@ -8094,7 +8094,7 @@ static int zend_jit_escape_if_undef(zend_jit_ctx *jit, int var, uint32_t flags, /* We can't use trace_escape() because opcode handler may be overridden by JIT */ zend_jit_op_array_trace_extension *jit_extension = - (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(op_array); + (zend_jit_op_array_trace_extension*)ZEND_FUNC_INFO(jit->current_op_array); size_t offset = jit_extension->offset; ir_ref ref = ir_CONST_FC_FUNC(ZEND_OP_TRACE_INFO((opline - 1), offset)->orig_handler); if (GCC_GLOBAL_REGS) { diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index da97d102f202..d22f67ba3a7e 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -3606,7 +3606,7 @@ static int zend_jit_trace_deoptimization( ZEND_ASSERT(STACK_FLAGS(parent_stack, check2) == ZREG_ZVAL_COPY); ZEND_ASSERT(reg != ZREG_NONE); - if (!zend_jit_escape_if_undef(jit, check2, flags, opline, exit_info->op_array, reg)) { + if (!zend_jit_escape_if_undef(jit, check2, flags, opline, reg)) { return 0; } if (!zend_jit_restore_zval(jit, EX_NUM_TO_VAR(check2), reg)) { @@ -7377,6 +7377,8 @@ static const void *zend_jit_trace_exit_to_vm(uint32_t trace_num, uint32_t exit_n zend_jit_traces[trace_num].stack_map + zend_jit_traces[trace_num].exit_info[exit_num].stack_offset : NULL; + ctx.current_op_array = zend_jit_traces[trace_num].exit_info[exit_num].op_array; + if (!zend_jit_trace_deoptimization(&ctx, &zend_jit_traces[trace_num].exit_info[exit_num], stack, stack_size, NULL, NULL,