From 93d5c0e9461047f358af42a21750342222d00ea1 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 31 Oct 2023 17:55:37 +0300 Subject: [PATCH] Fixed missed type store --- ext/opcache/jit/zend_jit_trace.c | 45 ++++++++++++++++++++++++++++++ ext/opcache/tests/jit/gh12512.phpt | 41 +++++++++++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 ext/opcache/tests/jit/gh12512.phpt diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index d7d01141d05..4e97c452e2b 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -4893,6 +4893,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))) { 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_type(&ctx, var_num, type)) { + return 0; + } + SET_STACK_TYPE(stack, var_num, type, 1); + } + } if (opline->op2_type == IS_CV && ssa_op->op2_def >= 0 && ssa->vars[ssa_op->op2_def].alias == NO_ALIAS) { @@ -4931,6 +4946,21 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par res_use_info, res_info, res_addr)) { 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_type(&ctx, var_num, type)) { + return 0; + } + SET_STACK_TYPE(stack, var_num, type, 1); + } + } if (opline->op1_type == IS_CV && ssa_op->op1_def >= 0 && ssa->vars[ssa_op->op1_def].alias == NO_ALIAS) { @@ -5013,6 +5043,21 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par op1_info, op1_addr, op1_def_addr)) { 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_type(&ctx, var_num, type)) { + return 0; + } + SET_STACK_TYPE(stack, var_num, type, 1); + } + } if (opline->op1_type == IS_CV && ssa_op->op1_def >= 0 && ssa->vars[ssa_op->op1_def].alias == NO_ALIAS) { diff --git a/ext/opcache/tests/jit/gh12512.phpt b/ext/opcache/tests/jit/gh12512.phpt new file mode 100644 index 00000000000..35307d18cc6 --- /dev/null +++ b/ext/opcache/tests/jit/gh12512.phpt @@ -0,0 +1,41 @@ +--TEST-- +GH-12512: missing type store +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +--FILE-- + $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