diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index ecee7dc2afefd..9124b8400bcea 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -12726,7 +12726,7 @@ static int zend_jit_fetch_dim_read(zend_jit_ctx *jit, static zend_jit_addr zend_jit_prepare_array_update(zend_jit_ctx *jit, const zend_op *opline, - uint32_t op1_info, + uint32_t *op1_info_ptr, zend_jit_addr op1_addr, ir_ref *if_type, ir_ref *ht_ref, @@ -12735,6 +12735,7 @@ static zend_jit_addr zend_jit_prepare_array_update(zend_jit_ctx *jit, ir_ref ref = IR_UNUSED; ir_ref array_reference_end = IR_UNUSED, array_reference_ref = IR_UNUSED; ir_refs *array_inputs, *array_values; + uint32_t op1_info = *op1_info_ptr; ir_refs_init(array_inputs, 4); ir_refs_init(array_values, 4); @@ -12826,6 +12827,9 @@ static zend_jit_addr zend_jit_prepare_array_update(zend_jit_ctx *jit, ir_refs_add(array_inputs, ir_END()); ir_refs_add(array_values, ref); } + op1_info &= ~(MAY_BE_UNDEF | MAY_BE_NULL); + op1_info |= MAY_BE_ARRAY | MAY_BE_RC1; + *op1_info_ptr = op1_info; } if (array_inputs->count) { @@ -12855,9 +12859,9 @@ static int zend_jit_fetch_dim(zend_jit_ctx *jit, jit_SET_EX_OPLINE(jit, opline); } - op1_addr = zend_jit_prepare_array_update(jit, opline, op1_info, op1_addr, &if_type, &ht_ref, &may_throw); + op1_addr = zend_jit_prepare_array_update(jit, opline, &op1_info, op1_addr, &if_type, &ht_ref, &may_throw); - if (op1_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_ARRAY)) { + if (op1_info & MAY_BE_ARRAY) { ir_refs *found_inputs, *found_vals; ir_refs_init(found_inputs, 8); @@ -12937,7 +12941,7 @@ static int zend_jit_fetch_dim(zend_jit_ctx *jit, } } - if (op1_info & (MAY_BE_ANY-(MAY_BE_NULL|MAY_BE_ARRAY))) { + if (op1_info & (MAY_BE_ANY-MAY_BE_ARRAY)) { ir_ref arg2; may_throw = 1; @@ -13247,9 +13251,9 @@ static int zend_jit_assign_dim(zend_jit_ctx *jit, val_info &= ~MAY_BE_UNDEF; } - op1_addr = zend_jit_prepare_array_update(jit, opline, op1_info, op1_addr, &if_type, &ht_ref, &may_throw); + op1_addr = zend_jit_prepare_array_update(jit, opline, &op1_info, op1_addr, &if_type, &ht_ref, &may_throw); - if (op1_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_ARRAY)) { + if (op1_info & MAY_BE_ARRAY) { if (opline->op2_type == IS_UNUSED) { uint32_t var_info = MAY_BE_NULL; ir_ref if_ok, ref; @@ -13320,7 +13324,7 @@ static int zend_jit_assign_dim(zend_jit_ctx *jit, ir_END_list(end_inputs); } - if (op1_info & (MAY_BE_ANY-(MAY_BE_NULL|MAY_BE_ARRAY))) { + if (op1_info & (MAY_BE_ANY-MAY_BE_ARRAY)) { ir_ref arg2, arg4; if (if_type) { @@ -13411,9 +13415,9 @@ static int zend_jit_assign_dim_op(zend_jit_ctx *jit, jit_SET_EX_OPLINE(jit, opline); } - op1_addr = zend_jit_prepare_array_update(jit, opline, op1_info, op1_addr, &if_type, &ht_ref, &may_throw); + op1_addr = zend_jit_prepare_array_update(jit, opline, &op1_info, op1_addr, &if_type, &ht_ref, &may_throw); - if (op1_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_ARRAY)) { + if (op1_info & MAY_BE_ARRAY) { uint32_t var_def_info = zend_array_element_type(op1_def_info, opline->op1_type, 1, 0); if (opline->op2_type == IS_UNUSED) { @@ -13555,7 +13559,7 @@ static int zend_jit_assign_dim_op(zend_jit_ctx *jit, } } - if (op1_info & (MAY_BE_ANY-(MAY_BE_NULL|MAY_BE_ARRAY))) { + if (op1_info & (MAY_BE_ANY-MAY_BE_ARRAY)) { binary_op_type binary_op; ir_ref arg2; diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index a3abbc1217900..abe15a9ffa196 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -1860,11 +1860,6 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin ADD_OP2_TRACE_GUARD(); break; case ZEND_ASSIGN_DIM_OP: - if (opline->extended_value == ZEND_POW - || opline->extended_value == ZEND_DIV) { - // TODO: check for division by zero ??? - break; - } if (opline->result_type != IS_UNUSED) { break; } @@ -1875,23 +1870,18 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin } ZEND_FALLTHROUGH; case ZEND_ASSIGN_DIM: - if (opline->op1_type == IS_CV) { - if ((opline+1)->op1_type == IS_CV - && (opline+1)->op1.var == opline->op1.var) { - /* skip $a[x] = $a; */ - break; - } + if (opline->opcode == ZEND_ASSIGN_DIM + && opline->op1_type == IS_CV + && (opline+1)->op1_type == IS_CV + && (opline+1)->op1.var == opline->op1.var) { + /* skip $a[x] = $a; */ + break; + } + if (opline->op1_type == IS_CV || opline->opcode == ZEND_ASSIGN_DIM_OP) { ADD_OP1_DATA_TRACE_GUARD(); - ADD_OP2_TRACE_GUARD(); - ADD_OP1_TRACE_GUARD(); - } else if (orig_op1_type != IS_UNKNOWN - && (orig_op1_type & IS_TRACE_INDIRECT) - && opline->result_type == IS_UNUSED) { - if (opline->opcode == ZEND_ASSIGN_DIM_OP) { - ADD_OP1_DATA_TRACE_GUARD(); - } - ADD_OP2_TRACE_GUARD(); } + ADD_OP2_TRACE_GUARD(); + ADD_OP1_TRACE_GUARD(); if (op1_type == IS_ARRAY && ((opline->op2_type == IS_CONST && Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) == IS_LONG) @@ -4773,6 +4763,9 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par op1_info, op2_info, op1_data_info, val_type))) { goto jit_failure; } + if (opline->op1_type == IS_VAR && !(op1_info & (MAY_BE_ANY-MAY_BE_NULL))) { + SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->op1.var), IS_ARRAY, 1); + } goto done; case ZEND_PRE_INC_OBJ: case ZEND_PRE_DEC_OBJ: @@ -5097,6 +5090,9 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par && ssa->vars[(ssa_op+1)->op1_def].alias == NO_ALIAS) { ssa->var_info[(ssa_op+1)->op1_def].guarded_reference = ssa->var_info[(ssa_op+1)->op1_use].guarded_reference; } + if (opline->op1_type == IS_VAR && !(op1_info & (MAY_BE_ANY-MAY_BE_NULL))) { + SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->op1.var), IS_ARRAY, 1); + } goto done; case ZEND_ASSIGN: if (opline->op1_type != IS_CV) {