Skip to content

Commit 495d7cb

Browse files
committed
Fix GH-24445: Tracing JIT loses register-allocated CVs in catch blocks.
Should also fix GH-24798
1 parent 98b580b commit 495d7cb

3 files changed

Lines changed: 78 additions & 0 deletions

File tree

‎ext/opcache/jit/zend_jit_trace.c‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3266,6 +3266,15 @@ static zend_jit_reg_var* zend_jit_trace_allocate_registers(zend_jit_trace_rec *t
32663266
}
32673267

32683268
if (count) {
3269+
for (i = 0; i < ssa->vars_count; i++) {
3270+
if (RA_HAS_REG(i) &&
3271+
vars_op_array[i] &&
3272+
vars_op_array[i]->last_try_catch &&
3273+
ssa->vars[i].var < vars_op_array[i]->last_var &&
3274+
!(RA_REG_FLAGS(i) & ZREG_LOAD)) {
3275+
RA_REG_FLAGS(i) |= ZREG_STORE;
3276+
}
3277+
}
32693278
/* SSA resolution */
32703279
if (trace_buffer->stop == ZEND_JIT_TRACE_STOP_LOOP
32713280
|| trace_buffer->stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL

‎ext/opcache/tests/jit/gh24445.phpt‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--TEST--
2+
GH-24445 (Tracing JIT: a catch reads an int local as undefined after an internal call throws)
3+
--CREDITS--
4+
EJ-Research
5+
--EXTENSIONS--
6+
opcache
7+
--INI--
8+
opcache.enable=1
9+
opcache.enable_cli=1
10+
opcache.file_update_protection=0
11+
opcache.jit_buffer_size=64M
12+
opcache.jit=tracing
13+
opcache.jit_hot_loop=1
14+
opcache.jit_hot_func=1
15+
--FILE--
16+
<?php
17+
function loop(array $p): void { foreach ($p as $v) {} }
18+
function id(int $n): int { return $n; }
19+
function run(array $p, int $d): int {
20+
loop($p);
21+
$n = count($p);
22+
try {
23+
intdiv(1, $d);
24+
} catch (DivisionByZeroError $e) {
25+
var_dump($n);
26+
return -1;
27+
}
28+
return id($n);
29+
}
30+
for ($i = 0; $i < 10; $i++) {
31+
run([1], 1);
32+
}
33+
run([1], 0);
34+
?>
35+
--EXPECT--
36+
int(1)

‎ext/opcache/tests/jit/gh24798.phpt‎

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
--TEST--
2+
GH-24798 (Tracing JIT loses register-allocated CVs when an exception is caught in the same function)
3+
--EXTENSIONS--
4+
opcache
5+
--INI--
6+
opcache.enable=1
7+
opcache.enable_cli=1
8+
opcache.file_update_protection=0
9+
opcache.jit_buffer_size=64M
10+
opcache.jit=tracing
11+
opcache.jit_hot_loop=1
12+
opcache.jit_hot_func=1
13+
opcache.jit_hot_return=1
14+
opcache.jit_hot_side_exit=1
15+
--FILE--
16+
<?php
17+
function f($n) {
18+
$s = 0.0;
19+
for ($i = 0; $i < $n; $i++) {
20+
try {
21+
$s += 1.0 / ($i - 2);
22+
} catch (DivisionByZeroError $e) {
23+
echo $e::class, ': ', $e->getMessage(), ' at $i = ', $i, PHP_EOL;
24+
$s += 100;
25+
}
26+
}
27+
return $s;
28+
}
29+
var_dump(f(5));
30+
?>
31+
--EXPECT--
32+
DivisionByZeroError: Division by zero at $i = 2
33+
float(100)

0 commit comments

Comments
 (0)