diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index b424934e4927..0656ef252740 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -3266,6 +3266,15 @@ static zend_jit_reg_var* zend_jit_trace_allocate_registers(zend_jit_trace_rec *t } if (count) { + for (i = 0; i < ssa->vars_count; i++) { + if (RA_HAS_REG(i) && + vars_op_array[i] && + vars_op_array[i]->last_try_catch && + ssa->vars[i].var < vars_op_array[i]->last_var && + !(RA_REG_FLAGS(i) & ZREG_LOAD)) { + RA_REG_FLAGS(i) |= ZREG_STORE; + } + } /* SSA resolution */ if (trace_buffer->stop == ZEND_JIT_TRACE_STOP_LOOP || trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL diff --git a/ext/opcache/tests/jit/gh24445.phpt b/ext/opcache/tests/jit/gh24445.phpt new file mode 100644 index 000000000000..e858855ec2c1 --- /dev/null +++ b/ext/opcache/tests/jit/gh24445.phpt @@ -0,0 +1,36 @@ +--TEST-- +GH-24445 (Tracing JIT: a catch reads an int local as undefined after an internal call throws) +--CREDITS-- +EJ-Research +--EXTENSIONS-- +opcache +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=64M +opcache.jit=tracing +opcache.jit_hot_loop=1 +opcache.jit_hot_func=1 +--FILE-- + +--EXPECT-- +int(1) diff --git a/ext/opcache/tests/jit/gh24798.phpt b/ext/opcache/tests/jit/gh24798.phpt new file mode 100644 index 000000000000..b0fd253de038 --- /dev/null +++ b/ext/opcache/tests/jit/gh24798.phpt @@ -0,0 +1,33 @@ +--TEST-- +GH-24798 (Tracing JIT loses register-allocated CVs when an exception is caught in the same function) +--EXTENSIONS-- +opcache +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=64M +opcache.jit=tracing +opcache.jit_hot_loop=1 +opcache.jit_hot_func=1 +opcache.jit_hot_return=1 +opcache.jit_hot_side_exit=1 +--FILE-- +getMessage(), ' at $i = ', $i, PHP_EOL; + $s += 100; + } + } + return $s; +} +var_dump(f(5)); +?> +--EXPECT-- +DivisionByZeroError: Division by zero at $i = 2 +float(100)