mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Fix deoptimization after exit during inc/dec
When the assumption that (PRE|POST)_(INC|DEC) overflows turns out to be false and we exit, effects are lost if op1 or result were in regs. Fix by updating the stack map before creating the exit point. Fixes GH-19669 Closes GH-19680
This commit is contained in:
4
NEWS
4
NEWS
@@ -7,6 +7,10 @@ PHP NEWS
|
||||
checks). (timwolla)
|
||||
. The __sleep() and __wakeup() magic methods have been deprecated. (Girgias)
|
||||
|
||||
- Opcache:
|
||||
. Fixed bug GH-19669 (assertion failure in zend_jit_trace_type_to_info_ex).
|
||||
(Arnaud)
|
||||
|
||||
- URI:
|
||||
. Fixed bug GH-19780 (InvalidUrlException should check $errors argument).
|
||||
(nielsdos)
|
||||
|
||||
@@ -4808,33 +4808,30 @@ static int zend_jit_inc_dec(zend_jit_ctx *jit, const zend_op *opline, uint32_t o
|
||||
int32_t exit_point;
|
||||
const void *exit_addr;
|
||||
zend_jit_trace_stack *stack;
|
||||
uint32_t old_res_info = 0;
|
||||
uint32_t old_res_info = 0, old_op1_info = 0;
|
||||
|
||||
stack = JIT_G(current_frame)->stack;
|
||||
if (opline->result_type != IS_UNUSED) {
|
||||
old_res_info = STACK_INFO(stack, EX_VAR_TO_NUM(opline->result.var));
|
||||
SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->result.var), IS_LONG, 0);
|
||||
if (opline->opcode == ZEND_PRE_INC || opline->opcode == ZEND_PRE_DEC) {
|
||||
SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->result.var), IS_LONG, 0);
|
||||
SET_STACK_REF(stack, EX_VAR_TO_NUM(opline->result.var), ref);
|
||||
} else {
|
||||
SET_STACK_REF(stack, EX_VAR_TO_NUM(opline->result.var), op1_lval_ref);
|
||||
}
|
||||
}
|
||||
old_op1_info = STACK_INFO(stack, EX_VAR_TO_NUM(opline->op1.var));
|
||||
SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->op1.var), IS_LONG, 0);
|
||||
SET_STACK_REF(stack, EX_VAR_TO_NUM(opline->op1.var), ref);
|
||||
|
||||
exit_point = zend_jit_trace_get_exit_point(opline + 1, 0);
|
||||
exit_addr = zend_jit_trace_get_exit_addr(exit_point);
|
||||
if ((opline->opcode == ZEND_PRE_INC || opline->opcode == ZEND_PRE_DEC) &&
|
||||
opline->result_type != IS_UNUSED) {
|
||||
if_overflow = ir_IF(ir_OVERFLOW(ref));
|
||||
ir_IF_FALSE_cold(if_overflow);
|
||||
jit_set_Z_LVAL(jit, res_addr, ref);
|
||||
if (Z_MODE(res_addr) != IS_REG) {
|
||||
jit_set_Z_TYPE_INFO(jit, res_addr, IS_LONG);
|
||||
}
|
||||
jit_SIDE_EXIT(jit, ir_CONST_ADDR(exit_addr));
|
||||
ir_IF_TRUE(if_overflow);
|
||||
} else {
|
||||
ir_GUARD(ir_OVERFLOW(ref), ir_CONST_ADDR(exit_addr));
|
||||
}
|
||||
ir_GUARD(ir_OVERFLOW(ref), ir_CONST_ADDR(exit_addr));
|
||||
|
||||
if (opline->result_type != IS_UNUSED) {
|
||||
SET_STACK_INFO(stack, EX_VAR_TO_NUM(opline->result.var), old_res_info);
|
||||
}
|
||||
SET_STACK_INFO(stack, EX_VAR_TO_NUM(opline->op1.var), old_op1_info);
|
||||
} else {
|
||||
if_overflow = ir_IF(ir_OVERFLOW(ref));
|
||||
ir_IF_FALSE(if_overflow);
|
||||
|
||||
24
ext/opcache/tests/jit/gh19669-001.phpt
Normal file
24
ext/opcache/tests/jit/gh19669-001.phpt
Normal file
@@ -0,0 +1,24 @@
|
||||
--TEST--
|
||||
GH-19669: assertion failure zend_jit_trace_type_to_info_ex
|
||||
--CREDITS--
|
||||
YuanchengJiang
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (PHP_INT_SIZE !== 8) {
|
||||
die('skip output depends PHP_INT_SIZE=8');
|
||||
}
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
function test() {
|
||||
$a = PHP_INT_MIN;
|
||||
$b = 0;
|
||||
while ($b++ < 2) {
|
||||
$a = (int) ($a-- + $a - $b);
|
||||
}
|
||||
return $a;
|
||||
}
|
||||
var_dump(test());
|
||||
?>
|
||||
--EXPECT--
|
||||
int(-3)
|
||||
24
ext/opcache/tests/jit/gh19669-002.phpt
Normal file
24
ext/opcache/tests/jit/gh19669-002.phpt
Normal file
@@ -0,0 +1,24 @@
|
||||
--TEST--
|
||||
GH-19669 002: assertion failure zend_jit_trace_type_to_info_ex
|
||||
--CREDITS--
|
||||
YuanchengJiang
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (PHP_INT_SIZE !== 8) {
|
||||
die('skip output depends PHP_INT_SIZE=8');
|
||||
}
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
function test() {
|
||||
$a = PHP_INT_MIN;
|
||||
$b = -1;
|
||||
while ($b++ < 2) {
|
||||
$a = (int) (--$a + $a - $b);
|
||||
}
|
||||
return $a;
|
||||
}
|
||||
var_dump(test());
|
||||
?>
|
||||
--EXPECT--
|
||||
int(-10)
|
||||
Reference in New Issue
Block a user