@@ -6254,7 +6254,7 @@ static int zend_jit_assign_to_variable(zend_jit_ctx *jit,
6254
6254
if (Z_MODE(val_addr) == IS_REG) {
6255
6255
zend_jit_addr real_addr;
6256
6256
6257
- if (opline->opcode == ZEND_ASSIGN_DIM) {
6257
+ if (opline->opcode == ZEND_ASSIGN_DIM || opline->opcode == ZEND_ASSIGN_OBJ ) {
6258
6258
real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, (opline+1)->op1.var);
6259
6259
} else {
6260
6260
ZEND_ASSERT(opline->opcode == ZEND_ASSIGN);
@@ -14143,6 +14143,9 @@ static int zend_jit_assign_obj(zend_jit_ctx *jit,
14143
14143
uint32_t op1_info,
14144
14144
zend_jit_addr op1_addr,
14145
14145
uint32_t val_info,
14146
+ zend_jit_addr val_addr,
14147
+ zend_jit_addr val_def_addr,
14148
+ zend_jit_addr res_addr,
14146
14149
bool op1_indirect,
14147
14150
zend_class_entry *ce,
14148
14151
bool ce_is_instanceof,
@@ -14155,17 +14158,21 @@ static int zend_jit_assign_obj(zend_jit_ctx *jit,
14155
14158
zval *member;
14156
14159
zend_string *name;
14157
14160
zend_property_info *prop_info;
14158
- zend_jit_addr val_addr = OP1_DATA_ADDR();
14159
- zend_jit_addr res_addr = 0;
14160
14161
zend_jit_addr prop_addr;
14161
14162
ir_ref obj_ref = IR_UNUSED;
14162
14163
ir_ref prop_ref = IR_UNUSED;
14163
14164
ir_ref delayed_end_input = IR_UNUSED;
14164
14165
ir_ref end_inputs = IR_UNUSED;
14165
14166
ir_ref slow_inputs = IR_UNUSED;
14167
+ uint32_t res_info = RES_INFO();
14166
14168
14167
- if (RETURN_VALUE_USED(opline)) {
14168
- res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->result.var);
14169
+ if (val_addr != val_def_addr && val_def_addr) {
14170
+ if (!zend_jit_update_regs(jit, (opline+1)->op1.var, val_addr, val_def_addr, val_info)) {
14171
+ return 0;
14172
+ }
14173
+ if (Z_MODE(val_def_addr) == IS_REG && Z_MODE(val_addr) != IS_REG) {
14174
+ val_addr = val_def_addr;
14175
+ }
14169
14176
}
14170
14177
14171
14178
ZEND_ASSERT(opline->op2_type == IS_CONST);
@@ -14206,7 +14213,7 @@ static int zend_jit_assign_obj(zend_jit_ctx *jit,
14206
14213
jit_ZVAL_ADDR(jit, op1_addr),
14207
14214
ir_CONST_ADDR(ZSTR_VAL(name)));
14208
14215
14209
- if (RETURN_VALUE_USED(opline)) {
14216
+ if (RETURN_VALUE_USED(opline) && Z_MODE(res_addr) != IS_REG ) {
14210
14217
jit_set_Z_TYPE_INFO(jit, res_addr, IS_NULL);
14211
14218
}
14212
14219
@@ -14276,25 +14283,51 @@ static int zend_jit_assign_obj(zend_jit_ctx *jit,
14276
14283
prop_addr = ZEND_ADDR_REF_ZVAL(prop_ref);
14277
14284
14278
14285
if (!ce || ce_is_instanceof || (ce->ce_flags & (ZEND_ACC_HAS_TYPE_HINTS|ZEND_ACC_TRAIT))) {
14286
+ ir_ref arg3, arg4;
14279
14287
ir_ref prop_info_ref = ir_LOAD_A(
14280
14288
ir_ADD_OFFSET(run_time_cache, (opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) + sizeof(void*) * 2));
14281
14289
ir_ref if_has_prop_info = ir_IF(prop_info_ref);
14282
14290
ir_IF_TRUE_cold(if_has_prop_info);
14283
14291
14292
+ if (Z_MODE(val_addr) == IS_REG) {
14293
+ zend_jit_addr real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, (opline+1)->op1.var);
14294
+ if (!zend_jit_spill_store_inv(jit, val_addr, real_addr, val_info)) {
14295
+ return 0;
14296
+ }
14297
+ arg3 = jit_ZVAL_ADDR(jit, real_addr);
14298
+ } else {
14299
+ arg3 = jit_ZVAL_ADDR(jit, val_addr);
14300
+ }
14301
+
14302
+ if (!RETURN_VALUE_USED(opline)) {
14303
+ arg4 = IR_NULL;
14304
+ } else if (Z_MODE(res_addr) == IS_REG) {
14305
+ zend_jit_addr real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->result.var);
14306
+ arg4 = jit_ZVAL_ADDR(jit, real_addr);
14307
+ } else {
14308
+ arg4 = jit_ZVAL_ADDR(jit, res_addr);
14309
+ }
14284
14310
// JIT: value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC);
14285
14311
jit_SET_EX_OPLINE(jit, opline);
14286
14312
ir_CALL_4(IR_VOID, ir_CONST_FC_FUNC(zend_jit_assign_to_typed_prop),
14287
14313
prop_ref,
14288
14314
prop_info_ref,
14289
- jit_ZVAL_ADDR(jit, val_addr) ,
14290
- RETURN_VALUE_USED(opline) ? jit_ZVAL_ADDR(jit, res_addr) : IR_NULL );
14315
+ arg3 ,
14316
+ arg4 );
14291
14317
14292
14318
if ((opline+1)->op1_type == IS_CONST) {
14293
14319
// TODO: ???
14294
14320
// if (Z_TYPE_P(value) == orig_type) {
14295
14321
// CACHE_PTR_EX(cache_slot + 2, NULL);
14296
14322
}
14297
14323
14324
+ if (RETURN_VALUE_USED(opline) && Z_MODE(res_addr) == IS_REG) {
14325
+ zend_jit_addr real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->result.var);
14326
+ if (!zend_jit_load_reg(jit, real_addr, res_addr, res_info)) {
14327
+ return 0;
14328
+ }
14329
+ }
14330
+
14298
14331
ir_END_list(end_inputs);
14299
14332
ir_IF_FALSE(if_has_prop_info);
14300
14333
}
@@ -14319,7 +14352,7 @@ static int zend_jit_assign_obj(zend_jit_ctx *jit,
14319
14352
}
14320
14353
}
14321
14354
if (ZEND_TYPE_IS_SET(prop_info->type)) {
14322
- ir_ref ref;
14355
+ ir_ref ref, arg3, arg4 ;
14323
14356
14324
14357
// JIT: value = zend_assign_to_typed_prop(prop_info, property_val, value EXECUTE_DATA_CC);
14325
14358
jit_SET_EX_OPLINE(jit, opline);
@@ -14333,18 +14366,43 @@ static int zend_jit_assign_obj(zend_jit_ctx *jit,
14333
14366
ref = ir_LOAD_A(ir_ADD_OFFSET(ref, offsetof(zend_class_entry, properties_info_table)));
14334
14367
ref = ir_LOAD_A(ir_ADD_OFFSET(ref, prop_info_offset));
14335
14368
}
14369
+ if (Z_MODE(val_addr) == IS_REG) {
14370
+ zend_jit_addr real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, (opline+1)->op1.var);
14371
+ if (!zend_jit_spill_store_inv(jit, val_addr, real_addr, val_info)) {
14372
+ return 0;
14373
+ }
14374
+ arg3 = jit_ZVAL_ADDR(jit, real_addr);
14375
+ } else {
14376
+ arg3 = jit_ZVAL_ADDR(jit, val_addr);
14377
+ }
14378
+ if (!RETURN_VALUE_USED(opline)) {
14379
+ arg4 = IR_NULL;
14380
+ } else if (Z_MODE(res_addr) == IS_REG) {
14381
+ zend_jit_addr real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->result.var);
14382
+ arg4 = jit_ZVAL_ADDR(jit, real_addr);
14383
+ } else {
14384
+ arg4 = jit_ZVAL_ADDR(jit, res_addr);
14385
+ }
14336
14386
ir_CALL_4(IR_VOID, ir_CONST_FC_FUNC(zend_jit_assign_to_typed_prop),
14337
14387
prop_ref,
14338
14388
ref,
14339
- jit_ZVAL_ADDR(jit, val_addr) ,
14340
- RETURN_VALUE_USED(opline) ? jit_ZVAL_ADDR(jit, res_addr) : IR_NULL );
14389
+ arg3 ,
14390
+ arg4 );
14341
14391
14392
+ if (RETURN_VALUE_USED(opline) && Z_MODE(res_addr) == IS_REG) {
14393
+ zend_jit_addr real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->result.var);
14394
+ if (!zend_jit_load_reg(jit, real_addr, res_addr, res_info)) {
14395
+ return 0;
14396
+ }
14397
+ }
14342
14398
ir_END_list(end_inputs);
14343
14399
}
14344
14400
}
14345
14401
14346
14402
if (!prop_info || !ZEND_TYPE_IS_SET(prop_info->type)) {
14347
- if (opline->result_type == IS_UNUSED) {
14403
+ if (Z_MODE(val_addr) != IS_REG
14404
+ && (res_addr == 0 || Z_MODE(res_addr) != IS_REG)
14405
+ && opline->result_type == IS_UNUSED) {
14348
14406
if (!zend_jit_assign_to_variable_call(jit, opline, prop_addr, prop_addr, -1, -1, (opline+1)->op1_type, val_addr, val_info, res_addr, 0)) {
14349
14407
return 0;
14350
14408
}
@@ -14365,18 +14423,44 @@ static int zend_jit_assign_obj(zend_jit_ctx *jit,
14365
14423
}
14366
14424
14367
14425
if (slow_inputs) {
14426
+ ir_ref arg3, arg5;
14427
+
14368
14428
ir_MERGE_list(slow_inputs);
14369
14429
jit_SET_EX_OPLINE(jit, opline);
14370
14430
14431
+ if (Z_MODE(val_addr) == IS_REG) {
14432
+ zend_jit_addr real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, (opline+1)->op1.var);
14433
+ if (!zend_jit_spill_store_inv(jit, val_addr, real_addr, val_info)) {
14434
+ return 0;
14435
+ }
14436
+ arg3 = jit_ZVAL_ADDR(jit, real_addr);
14437
+ } else {
14438
+ arg3 = jit_ZVAL_ADDR(jit, val_addr);
14439
+ }
14440
+ if (!RETURN_VALUE_USED(opline)) {
14441
+ arg5 = IR_NULL;
14442
+ } else if (Z_MODE(res_addr) == IS_REG) {
14443
+ zend_jit_addr real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->result.var);
14444
+ arg5 = jit_ZVAL_ADDR(jit, real_addr);
14445
+ } else {
14446
+ arg5 = jit_ZVAL_ADDR(jit, res_addr);
14447
+ }
14448
+
14371
14449
// JIT: value = zobj->handlers->write_property(zobj, name, value, CACHE_ADDR(opline->extended_value));
14372
14450
ir_ref run_time_cache = ir_LOAD_A(jit_EX(run_time_cache));
14373
14451
ir_CALL_5(IR_VOID, ir_CONST_FC_FUNC(zend_jit_assign_obj_helper),
14374
14452
obj_ref,
14375
14453
ir_CONST_ADDR(name),
14376
- jit_ZVAL_ADDR(jit, val_addr) ,
14454
+ arg3 ,
14377
14455
ir_ADD_OFFSET(run_time_cache, opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS),
14378
- RETURN_VALUE_USED(opline) ? jit_ZVAL_ADDR(jit, res_addr) : IR_NULL );
14456
+ arg5 );
14379
14457
14458
+ if (RETURN_VALUE_USED(opline) && Z_MODE(res_addr) == IS_REG) {
14459
+ zend_jit_addr real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->result.var);
14460
+ if (!zend_jit_load_reg(jit, real_addr, res_addr, res_info)) {
14461
+ return 0;
14462
+ }
14463
+ }
14380
14464
ir_END_list(end_inputs);
14381
14465
}
14382
14466
@@ -14412,6 +14496,7 @@ static int zend_jit_assign_obj_op(zend_jit_ctx *jit,
14412
14496
uint32_t op1_info,
14413
14497
zend_jit_addr op1_addr,
14414
14498
uint32_t val_info,
14499
+ zend_jit_addr val_addr,
14415
14500
zend_ssa_range *val_range,
14416
14501
bool op1_indirect,
14417
14502
zend_class_entry *ce,
@@ -14424,7 +14509,6 @@ static int zend_jit_assign_obj_op(zend_jit_ctx *jit,
14424
14509
zval *member;
14425
14510
zend_string *name;
14426
14511
zend_property_info *prop_info;
14427
- zend_jit_addr val_addr = OP1_DATA_ADDR();
14428
14512
zend_jit_addr prop_addr;
14429
14513
bool use_prop_guard = 0;
14430
14514
bool may_throw = 0;
@@ -14579,12 +14663,22 @@ static int zend_jit_assign_obj_op(zend_jit_ctx *jit,
14579
14663
}
14580
14664
}
14581
14665
if (ZEND_TYPE_IS_SET(prop_info->type)) {
14582
- ir_ref if_ref, if_typed, noref_path, ref_path, reference, ref;
14666
+ ir_ref if_ref, if_typed, noref_path, ref_path, reference, ref, arg2 ;
14583
14667
14584
14668
may_throw = 1;
14585
14669
14586
14670
jit_SET_EX_OPLINE(jit, opline);
14587
14671
14672
+ if (Z_MODE(val_addr) == IS_REG) {
14673
+ zend_jit_addr real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, (opline+1)->op1.var);
14674
+ if (!zend_jit_spill_store_inv(jit, val_addr, real_addr, val_info)) {
14675
+ return 0;
14676
+ }
14677
+ arg2 = jit_ZVAL_ADDR(jit, real_addr);
14678
+ } else {
14679
+ arg2 = jit_ZVAL_ADDR(jit, val_addr);
14680
+ }
14681
+
14588
14682
if_ref = jit_if_Z_TYPE(jit, prop_addr, IS_REFERENCE);
14589
14683
ir_IF_FALSE(if_ref);
14590
14684
noref_path = ir_END();
@@ -14599,7 +14693,7 @@ static int zend_jit_assign_obj_op(zend_jit_ctx *jit,
14599
14693
14600
14694
ir_CALL_3(IR_VOID, ir_CONST_FC_FUNC(zend_jit_assign_op_to_typed_ref),
14601
14695
reference,
14602
- jit_ZVAL_ADDR(jit, val_addr) ,
14696
+ arg2 ,
14603
14697
ir_CONST_FC_FUNC(binary_op));
14604
14698
14605
14699
ir_END_list(end_inputs);
@@ -14623,7 +14717,7 @@ static int zend_jit_assign_obj_op(zend_jit_ctx *jit,
14623
14717
ir_CALL_4(IR_VOID, ir_CONST_FC_FUNC(zend_jit_assign_op_to_typed_prop),
14624
14718
prop_ref,
14625
14719
ref,
14626
- jit_ZVAL_ADDR(jit, val_addr) ,
14720
+ arg2 ,
14627
14721
ir_CONST_FC_FUNC(binary_op));
14628
14722
14629
14723
ir_END_list(end_inputs);
@@ -14647,7 +14741,7 @@ static int zend_jit_assign_obj_op(zend_jit_ctx *jit,
14647
14741
}
14648
14742
14649
14743
if (var_info & MAY_BE_REF) {
14650
- ir_ref if_ref, if_typed, noref_path, ref_path, reference, ref;
14744
+ ir_ref if_ref, if_typed, noref_path, ref_path, reference, ref, arg2 ;
14651
14745
14652
14746
may_throw = 1;
14653
14747
@@ -14665,9 +14759,18 @@ static int zend_jit_assign_obj_op(zend_jit_ctx *jit,
14665
14759
14666
14760
jit_SET_EX_OPLINE(jit, opline);
14667
14761
14762
+ if (Z_MODE(val_addr) == IS_REG) {
14763
+ zend_jit_addr real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, (opline+1)->op1.var);
14764
+ if (!zend_jit_spill_store_inv(jit, val_addr, real_addr, val_info)) {
14765
+ return 0;
14766
+ }
14767
+ arg2 = jit_ZVAL_ADDR(jit, real_addr);
14768
+ } else {
14769
+ arg2 = jit_ZVAL_ADDR(jit, val_addr);
14770
+ }
14668
14771
ir_CALL_3(IR_VOID, ir_CONST_FC_FUNC(zend_jit_assign_op_to_typed_ref),
14669
14772
reference,
14670
- jit_ZVAL_ADDR(jit, val_addr) ,
14773
+ arg2 ,
14671
14774
ir_CONST_FC_FUNC(binary_op));
14672
14775
14673
14776
ir_END_list(end_inputs);
@@ -14760,16 +14863,27 @@ static int zend_jit_assign_obj_op(zend_jit_ctx *jit,
14760
14863
}
14761
14864
14762
14865
if (slow_inputs) {
14866
+ ir_ref arg3;
14867
+
14763
14868
ir_MERGE_list(slow_inputs);
14764
14869
14765
14870
may_throw = 1;
14766
14871
14872
+ if (Z_MODE(val_addr) == IS_REG) {
14873
+ zend_jit_addr real_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, (opline+1)->op1.var);
14874
+ if (!zend_jit_spill_store_inv(jit, val_addr, real_addr, val_info)) {
14875
+ return 0;
14876
+ }
14877
+ arg3 = jit_ZVAL_ADDR(jit, real_addr);
14878
+ } else {
14879
+ arg3 = jit_ZVAL_ADDR(jit, val_addr);
14880
+ }
14767
14881
jit_SET_EX_OPLINE(jit, opline);
14768
14882
ir_ref run_time_cache = ir_LOAD_A(jit_EX(run_time_cache));
14769
14883
ir_CALL_5(IR_VOID, ir_CONST_FC_FUNC(zend_jit_assign_obj_op_helper),
14770
14884
obj_ref,
14771
14885
ir_CONST_ADDR(name),
14772
- jit_ZVAL_ADDR(jit, val_addr) ,
14886
+ arg3 ,
14773
14887
ir_ADD_OFFSET(run_time_cache, (opline+1)->extended_value & ~ZEND_FETCH_OBJ_FLAGS),
14774
14888
ir_CONST_FC_FUNC(binary_op));
14775
14889
@@ -16692,7 +16806,16 @@ static bool zend_jit_opline_supports_reg(const zend_op_array *op_array, zend_ssa
16692
16806
return ((op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) &&
16693
16807
(((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_LONG) ||
16694
16808
((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_STRING));
16809
+ case ZEND_ASSIGN_OBJ_OP:
16810
+ if (opline->result_type != IS_UNUSED) {
16811
+ return 0;
16812
+ }
16813
+ if (!zend_jit_supported_binary_op(opline->extended_value, MAY_BE_ANY, OP1_DATA_INFO())) {
16814
+ return 0;
16815
+ }
16816
+ ZEND_FALLTHROUGH;
16695
16817
case ZEND_FETCH_OBJ_R:
16818
+ case ZEND_ASSIGN_OBJ:
16696
16819
if (opline->op2_type != IS_CONST
16697
16820
|| Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) != IS_STRING
16698
16821
|| Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))[0] == '\0') {
0 commit comments