mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Merge branch 'PHP-8.1' into PHP-8.2
* PHP-8.1: Backport fix for GH-12512: JIT Assertion `info & (1 << type)' failed (#12660)
This commit is contained in:
commit
db26aee801
3 changed files with 154 additions and 3 deletions
|
@ -5033,6 +5033,21 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
|
||||||
zend_may_throw_ex(opline, ssa_op, op_array, ssa, op1_info, op2_info))) {
|
zend_may_throw_ex(opline, ssa_op, op_array, ssa, op1_info, op2_info))) {
|
||||||
goto jit_failure;
|
goto jit_failure;
|
||||||
}
|
}
|
||||||
|
if (ssa_op->op2_def > 0
|
||||||
|
&& Z_MODE(op2_addr) == IS_REG
|
||||||
|
&& ssa->vars[ssa_op->op2_def].no_val) {
|
||||||
|
uint8_t type = (op2_info & MAY_BE_LONG) ? IS_LONG : IS_DOUBLE;
|
||||||
|
uint32_t var_num = EX_VAR_TO_NUM(opline->op2.var);
|
||||||
|
|
||||||
|
if (STACK_MEM_TYPE(stack, var_num) != type
|
||||||
|
&& ssa->vars[ssa_op->op2_def].use_chain < 0
|
||||||
|
&& !ssa->vars[ssa_op->op2_def].phi_use_chain) {
|
||||||
|
if (!zend_jit_store_var_type(&dasm_state, var_num, type)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
SET_STACK_TYPE(stack, var_num, type, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (opline->op2_type == IS_CV
|
if (opline->op2_type == IS_CV
|
||||||
&& ssa_op->op2_def >= 0
|
&& ssa_op->op2_def >= 0
|
||||||
&& ssa->vars[ssa_op->op2_def].alias == NO_ALIAS) {
|
&& ssa->vars[ssa_op->op2_def].alias == NO_ALIAS) {
|
||||||
|
@ -5069,6 +5084,21 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
|
||||||
res_use_info, res_info, res_addr)) {
|
res_use_info, res_info, res_addr)) {
|
||||||
goto jit_failure;
|
goto jit_failure;
|
||||||
}
|
}
|
||||||
|
if (ssa_op->op1_def > 0
|
||||||
|
&& Z_MODE(op1_addr) == IS_REG
|
||||||
|
&& ssa->vars[ssa_op->op1_def].no_val) {
|
||||||
|
uint8_t type = (op1_info & MAY_BE_LONG) ? IS_LONG : IS_DOUBLE;
|
||||||
|
uint32_t var_num = EX_VAR_TO_NUM(opline->op1.var);
|
||||||
|
|
||||||
|
if (STACK_MEM_TYPE(stack, var_num) != type
|
||||||
|
&& ssa->vars[ssa_op->op1_def].use_chain < 0
|
||||||
|
&& !ssa->vars[ssa_op->op1_def].phi_use_chain) {
|
||||||
|
if (!zend_jit_store_var_type(&dasm_state, var_num, type)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
SET_STACK_TYPE(stack, var_num, type, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (opline->op1_type == IS_CV
|
if (opline->op1_type == IS_CV
|
||||||
&& ssa_op->op1_def >= 0
|
&& ssa_op->op1_def >= 0
|
||||||
&& ssa->vars[ssa_op->op1_def].alias == NO_ALIAS) {
|
&& ssa->vars[ssa_op->op1_def].alias == NO_ALIAS) {
|
||||||
|
@ -5151,6 +5181,21 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
|
||||||
op1_info, op1_addr, op1_def_addr)) {
|
op1_info, op1_addr, op1_def_addr)) {
|
||||||
goto jit_failure;
|
goto jit_failure;
|
||||||
}
|
}
|
||||||
|
if (ssa_op->op1_def > 0
|
||||||
|
&& Z_MODE(op1_addr) == IS_REG
|
||||||
|
&& ssa->vars[ssa_op->op1_def].no_val) {
|
||||||
|
uint8_t type = (op1_info & MAY_BE_LONG) ? IS_LONG : IS_DOUBLE;
|
||||||
|
uint32_t var_num = EX_VAR_TO_NUM(opline->op1.var);
|
||||||
|
|
||||||
|
if (STACK_MEM_TYPE(stack, var_num) != type
|
||||||
|
&& ssa->vars[ssa_op->op1_def].use_chain < 0
|
||||||
|
&& !ssa->vars[ssa_op->op1_def].phi_use_chain) {
|
||||||
|
if (!zend_jit_store_var_type(&dasm_state, var_num, type)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
SET_STACK_TYPE(stack, var_num, type, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (opline->op1_type == IS_CV
|
if (opline->op1_type == IS_CV
|
||||||
&& ssa_op->op1_def >= 0
|
&& ssa_op->op1_def >= 0
|
||||||
&& ssa->vars[ssa_op->op1_def].alias == NO_ALIAS) {
|
&& ssa->vars[ssa_op->op1_def].alias == NO_ALIAS) {
|
||||||
|
@ -6861,9 +6906,30 @@ done:
|
||||||
}
|
}
|
||||||
} else if (p->stop == ZEND_JIT_TRACE_STOP_LINK
|
} else if (p->stop == ZEND_JIT_TRACE_STOP_LINK
|
||||||
|| p->stop == ZEND_JIT_TRACE_STOP_INTERPRETER) {
|
|| p->stop == ZEND_JIT_TRACE_STOP_INTERPRETER) {
|
||||||
if (!zend_jit_trace_deoptimization(&dasm_state, 0, NULL,
|
if (ra
|
||||||
stack, op_array->last_var + op_array->T, NULL, NULL, NULL, 0)) {
|
&& (p-1)->op != ZEND_JIT_TRACE_ENTER
|
||||||
goto jit_failure;
|
&& (p-1)->op != ZEND_JIT_TRACE_BACK
|
||||||
|
&& opline->opcode != ZEND_DO_UCALL
|
||||||
|
&& opline->opcode != ZEND_DO_FCALL
|
||||||
|
&& opline->opcode != ZEND_DO_FCALL_BY_NAME
|
||||||
|
&& opline->opcode != ZEND_INCLUDE_OR_EVAL) {
|
||||||
|
if (!zend_jit_trace_deoptimization(&dasm_state, 0, NULL,
|
||||||
|
stack, op_array->last_var + op_array->T, NULL, NULL, NULL, 0)) {
|
||||||
|
goto jit_failure;
|
||||||
|
}
|
||||||
|
for (i = 0; i < op_array->last_var; i++) {
|
||||||
|
int8_t reg = STACK_REG(stack, i);
|
||||||
|
uint8_t type = STACK_TYPE(stack, i);
|
||||||
|
|
||||||
|
if (reg == ZREG_NONE
|
||||||
|
&& type != IS_UNKNOWN
|
||||||
|
&& type != STACK_MEM_TYPE(stack, i)) {
|
||||||
|
if (!zend_jit_store_var_type(&dasm_state, i, type)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
SET_STACK_TYPE(stack, i, type, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (p->stop == ZEND_JIT_TRACE_STOP_LINK) {
|
if (p->stop == ZEND_JIT_TRACE_STOP_LINK) {
|
||||||
const void *timeout_exit_addr = NULL;
|
const void *timeout_exit_addr = NULL;
|
||||||
|
|
41
ext/opcache/tests/jit/gh12512.phpt
Normal file
41
ext/opcache/tests/jit/gh12512.phpt
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
--TEST--
|
||||||
|
GH-12512: missing type store
|
||||||
|
--INI--
|
||||||
|
opcache.enable=1
|
||||||
|
opcache.enable_cli=1
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
function bar(array &$a): ?bool {
|
||||||
|
$ret = null;
|
||||||
|
foreach ($a as $key => $val) {
|
||||||
|
if ($val === 2) {
|
||||||
|
unset($a[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
function foo($a, bool $b): bool {
|
||||||
|
if ($b) return true;
|
||||||
|
$n2 = count($a);
|
||||||
|
do {
|
||||||
|
$n = $n2;
|
||||||
|
$res = bar($a);
|
||||||
|
$n2 = count($a);
|
||||||
|
} while ($res === null && $n !== $n2);
|
||||||
|
|
||||||
|
if ($res === null && $n === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$a = [1,'a'=>5];
|
||||||
|
bar($a);
|
||||||
|
foo([1,'a'=>5], true);
|
||||||
|
foo([1,'a'=>5], false);
|
||||||
|
foo([2,'a'=>5], false);
|
||||||
|
?>
|
||||||
|
DONE
|
||||||
|
--EXPECT--
|
||||||
|
DONE
|
44
ext/opcache/tests/jit/gh12512_2.phpt
Normal file
44
ext/opcache/tests/jit/gh12512_2.phpt
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
--TEST--
|
||||||
|
GH-12512: missing type store
|
||||||
|
--INI--
|
||||||
|
opcache.enable=1
|
||||||
|
opcache.enable_cli=1
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
function foo(array $a, $exit) {
|
||||||
|
$n = 0;
|
||||||
|
|
||||||
|
$count = count($a);
|
||||||
|
if ($count == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
$a2 = [];
|
||||||
|
foreach ($a as $v) {
|
||||||
|
$a2[] = $v;
|
||||||
|
}
|
||||||
|
|
||||||
|
$count = $a2[5];
|
||||||
|
|
||||||
|
for ($i = 0; $i < $count; $i++) {
|
||||||
|
$x = $a[$i];
|
||||||
|
for ($k = $i + 1; $k < $count; $k++) {
|
||||||
|
$y = $a[$k];
|
||||||
|
$n += $x > $y;
|
||||||
|
}
|
||||||
|
if ($exit) {
|
||||||
|
return $n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $n;
|
||||||
|
}
|
||||||
|
var_dump(foo([1,2,3,4,5,6,7,8], 1));
|
||||||
|
var_dump(foo([1,2,3,4,5,6,7,8], 1));
|
||||||
|
var_dump(foo([1,2,3,4,5,6,7,8], 0));
|
||||||
|
?>
|
||||||
|
DONE
|
||||||
|
--EXPECT--
|
||||||
|
int(0)
|
||||||
|
int(0)
|
||||||
|
int(0)
|
||||||
|
DONE
|
Loading…
Add table
Add a link
Reference in a new issue