diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index 689c994a7170c..59092c05d71ea 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -5559,29 +5559,35 @@ static int zend_jit_long_math_helper(zend_jit_ctx *jit, } if (op1_info & MAY_BE_UNDEF) { - ir_ref if_def; + ir_ref if_def, ref, ref2; + ref = jit_ZVAL_ADDR(jit, op1_addr); if_def = jit_if_not_Z_TYPE(jit, op1_addr, IS_UNDEF); ir_IF_FALSE_cold(if_def); // zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(CV_DEF_OF(EX_VAR_TO_NUM(opline->op1.var)))); ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_undefined_op_helper), ir_CONST_U32(opline->op1.var)); - jit_set_Z_TYPE_INFO(jit, op1_addr, IS_NULL); + ref2 = jit_EG(uninitialized_zval); ir_MERGE_WITH_EMPTY_TRUE(if_def); + ref = ir_PHI_2(IR_ADDR, ref2, ref); + op1_addr = ZEND_ADDR_REF_ZVAL(ref); } if (op2_info & MAY_BE_UNDEF) { - ir_ref if_def; + ir_ref if_def, ref, ref2; + ref = jit_ZVAL_ADDR(jit, op2_addr); if_def = jit_if_not_Z_TYPE(jit, op2_addr, IS_UNDEF); ir_IF_FALSE_cold(if_def); // zend_error(E_WARNING, "Undefined variable $%s", ZSTR_VAL(CV_DEF_OF(EX_VAR_TO_NUM(opline->op2.var)))); ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_undefined_op_helper), ir_CONST_U32(opline->op2.var)); - jit_set_Z_TYPE_INFO(jit, op2_addr, IS_NULL); + ref2 = jit_EG(uninitialized_zval); ir_MERGE_WITH_EMPTY_TRUE(if_def); + ref = ir_PHI_2(IR_ADDR, ref2, ref); + op2_addr = ZEND_ADDR_REF_ZVAL(ref); } if (Z_MODE(op1_addr) == IS_REG) { @@ -16327,6 +16333,15 @@ static bool zend_jit_opline_supports_reg(const zend_op_array *op_array, zend_ssa case ZEND_MUL: op1_info = OP1_INFO(); op2_info = OP2_INFO(); + if ((op1_info & MAY_BE_UNDEF) || (op2_info & MAY_BE_UNDEF)) { + return 0; + } + if (trace && trace->op1_type != IS_UNKNOWN) { + op1_info &= 1U << (trace->op1_type & ~(IS_TRACE_REFERENCE|IS_TRACE_INDIRECT|IS_TRACE_PACKED)); + } + if (trace && trace->op2_type != IS_UNKNOWN) { + op2_info &= 1U << (trace->op2_type & ~(IS_TRACE_REFERENCE|IS_TRACE_INDIRECT|IS_TRACE_PACKED)); + } return !(op1_info & MAY_BE_UNDEF) && !(op2_info & MAY_BE_UNDEF) && (op1_info & (MAY_BE_LONG|MAY_BE_DOUBLE)) @@ -16339,6 +16354,12 @@ static bool zend_jit_opline_supports_reg(const zend_op_array *op_array, zend_ssa case ZEND_MOD: op1_info = OP1_INFO(); op2_info = OP2_INFO(); + if (trace && trace->op1_type != IS_UNKNOWN) { + op1_info &= 1U << (trace->op1_type & ~(IS_TRACE_REFERENCE|IS_TRACE_INDIRECT|IS_TRACE_PACKED)); + } + if (trace && trace->op2_type != IS_UNKNOWN) { + op2_info &= 1U << (trace->op2_type & ~(IS_TRACE_REFERENCE|IS_TRACE_INDIRECT|IS_TRACE_PACKED)); + } return (op1_info & MAY_BE_LONG) && (op2_info & MAY_BE_LONG); case ZEND_PRE_INC: @@ -16384,6 +16405,13 @@ static bool zend_jit_opline_supports_reg(const zend_op_array *op_array, zend_ssa && (trace->op1_type & ~(IS_TRACE_REFERENCE|IS_TRACE_INDIRECT|IS_TRACE_PACKED)) == IS_ARRAY) { op1_info &= ~((MAY_BE_ANY|MAY_BE_UNDEF) - MAY_BE_ARRAY); } + if (trace && trace->op2_type != IS_UNKNOWN) { + if ((trace->op2_type & ~(IS_TRACE_REFERENCE|IS_TRACE_INDIRECT|IS_TRACE_PACKED)) == IS_LONG) { + op2_info &= ~((MAY_BE_ANY|MAY_BE_UNDEF) - MAY_BE_LONG); + } else if ((trace->op2_type & ~(IS_TRACE_REFERENCE|IS_TRACE_INDIRECT|IS_TRACE_PACKED)) == IS_STRING) { + op2_info &= ~((MAY_BE_ANY|MAY_BE_UNDEF) - MAY_BE_STRING); + } + } return ((op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) && (!(opline->op1_type & (IS_TMP_VAR|IS_VAR)) || !(op1_info & MAY_BE_RC1)) && (((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_LONG) || diff --git a/ext/opcache/tests/jit/reg_alloc_018.phpt b/ext/opcache/tests/jit/reg_alloc_018.phpt new file mode 100644 index 0000000000000..d6516cb506c05 --- /dev/null +++ b/ext/opcache/tests/jit/reg_alloc_018.phpt @@ -0,0 +1,17 @@ +--TEST-- +Register Alloction 018: Incorrect allocation +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +--FILE-- + +DONE +--EXPECTF-- +Warning: Undefined variable $y in %sreg_alloc_018.php on line 2 + +Warning: Undefined variable $y in %sreg_alloc_018.php on line 2 +DONE