@@ -6232,8 +6232,14 @@ static int zend_jit_assign_to_variable(zend_jit_ctx *jit,
6232
6232
ir_IF_TRUE_cold(if_typed);
6233
6233
jit_SET_EX_OPLINE(jit, opline);
6234
6234
if (Z_MODE(val_addr) == IS_REG) {
6235
- ZEND_ASSERT(opline->opcode == ZEND_ASSIGN);
6236
- zend_jit_addr real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->op2.var);
6235
+ zend_jit_addr real_addr;
6236
+
6237
+ if (opline->opcode == ZEND_ASSIGN_DIM) {
6238
+ real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, (opline+1)->op1.var);
6239
+ } else {
6240
+ ZEND_ASSERT(opline->opcode == ZEND_ASSIGN);
6241
+ real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->op2.var);
6242
+ }
6237
6243
if (!zend_jit_spill_store_inv(jit, val_addr, real_addr, val_info)) {
6238
6244
return 0;
6239
6245
}
@@ -12788,18 +12794,29 @@ static int zend_jit_isset_isempty_dim(zend_jit_ctx *jit,
12788
12794
return 1;
12789
12795
}
12790
12796
12791
- static int zend_jit_assign_dim(zend_jit_ctx *jit, const zend_op *opline, uint32_t op1_info, zend_jit_addr op1_addr, uint32_t op2_info, uint32_t val_info, uint8_t dim_type, int may_throw)
12797
+ static int zend_jit_assign_dim(zend_jit_ctx *jit,
12798
+ const zend_op *opline,
12799
+ uint32_t op1_info,
12800
+ zend_jit_addr op1_addr,
12801
+ uint32_t op2_info,
12802
+ zend_jit_addr op2_addr,
12803
+ uint32_t val_info,
12804
+ zend_jit_addr op3_addr,
12805
+ zend_jit_addr op3_def_addr,
12806
+ zend_jit_addr res_addr,
12807
+ uint8_t dim_type,
12808
+ int may_throw)
12792
12809
{
12793
- zend_jit_addr op2_addr, op3_addr, res_addr;
12794
12810
ir_ref if_type = IR_UNUSED;
12795
12811
ir_ref end_inputs = IR_UNUSED, ht_ref;
12796
12812
12797
- op2_addr = (opline->op2_type != IS_UNUSED) ? OP2_ADDR() : 0;
12798
- op3_addr = OP1_DATA_ADDR();
12799
- if (opline->result_type == IS_UNUSED) {
12800
- res_addr = 0;
12801
- } else {
12802
- res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->result.var);
12813
+ if (op3_addr != op3_def_addr && op3_def_addr) {
12814
+ if (!zend_jit_update_regs(jit, (opline+1)->op1.var, op3_addr, op3_def_addr, val_info)) {
12815
+ return 0;
12816
+ }
12817
+ if (Z_MODE(op3_def_addr) == IS_REG && Z_MODE(op3_addr) != IS_REG) {
12818
+ op3_addr = op3_def_addr;
12819
+ }
12803
12820
}
12804
12821
12805
12822
if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE && (val_info & MAY_BE_UNDEF)) {
@@ -12852,7 +12869,7 @@ static int zend_jit_assign_dim(zend_jit_ctx *jit, const zend_op *opline, uint32_
12852
12869
ir_refs_init(found_values, 8);
12853
12870
12854
12871
if (!zend_jit_fetch_dimension_address_inner(jit, opline, BP_VAR_W, op1_info,
12855
- op2_info, OP2_ADDR() , dim_type, NULL, NULL, NULL,
12872
+ op2_info, op2_addr , dim_type, NULL, NULL, NULL,
12856
12873
0, ht_ref, found_inputs, found_values, &end_inputs, NULL)) {
12857
12874
return 0;
12858
12875
}
@@ -12870,7 +12887,9 @@ static int zend_jit_assign_dim(zend_jit_ctx *jit, const zend_op *opline, uint32_
12870
12887
var_addr = ZEND_ADDR_REF_ZVAL(ref);
12871
12888
12872
12889
// JIT: value = zend_assign_to_variable(variable_ptr, value, OP_DATA_TYPE);
12873
- if (opline->op1_type == IS_VAR) {
12890
+ if (opline->op1_type == IS_VAR
12891
+ && Z_MODE(op3_addr) != IS_REG
12892
+ && (res_addr == 0 || Z_MODE(res_addr) != IS_REG)) {
12874
12893
ZEND_ASSERT(opline->result_type == IS_UNUSED);
12875
12894
if (!zend_jit_assign_to_variable_call(jit, opline, var_addr, var_addr, var_info, -1, (opline+1)->op1_type, op3_addr, val_info, res_addr, 0)) {
12876
12895
return 0;
@@ -16552,6 +16571,31 @@ static bool zend_jit_opline_supports_reg(const zend_op_array *op_array, zend_ssa
16552
16571
return ((op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) &&
16553
16572
(((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_LONG) ||
16554
16573
((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_STRING));
16574
+ case ZEND_ASSIGN_DIM:
16575
+ op1_info = OP1_INFO();
16576
+ op2_info = OP2_INFO();
16577
+ if (trace) {
16578
+ if (opline->op1_type == IS_CV) {
16579
+ if ((opline+1)->op1_type == IS_CV
16580
+ && (opline+1)->op1.var == opline->op1.var) {
16581
+ /* skip $a[x] = $a; */
16582
+ return 0;
16583
+ }
16584
+ } else if (opline->op1_type == IS_VAR) {
16585
+ if (trace->op1_type == IS_UNKNOWN
16586
+ || !(trace->op1_type & IS_TRACE_INDIRECT)
16587
+ || opline->result_type != IS_UNUSED) {
16588
+ return 0;
16589
+ }
16590
+ }
16591
+ if (trace->op1_type != IS_UNKNOWN
16592
+ && (trace->op1_type & ~(IS_TRACE_REFERENCE|IS_TRACE_INDIRECT|IS_TRACE_PACKED)) == IS_ARRAY) {
16593
+ op1_info &= ~((MAY_BE_ANY|MAY_BE_UNDEF) - MAY_BE_ARRAY);
16594
+ }
16595
+ }
16596
+ return ((op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) &&
16597
+ (((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_LONG) ||
16598
+ ((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_STRING));
16555
16599
}
16556
16600
return 0;
16557
16601
}
0 commit comments