@@ -1081,10 +1081,10 @@ static void* dasm_labels[zend_lb_MAX];
1081
1081
|| }
1082
1082
|.endmacro
1083
1083
1084
- |.macro FREE_OP, op_type, op, op_info, cold, opline
1084
+ |.macro FREE_OP, op_type, op, op_info, cold, opline, tmp_reg1, tmp_reg2
1085
1085
|| if (op_type & (IS_VAR|IS_TMP_VAR)) {
1086
- | brk #0 // TODO: test
1087
- | // ZVAL_PTR_DTOR ZEND_ADDR_MEM_ZVAL(ZREG_FP, op.var), op_info, 0, cold, opline
1086
+ || zend_jit_addr addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, op.var);
1087
+ | ZVAL_PTR_DTOR addr, op_info, 0, cold, opline, tmp_reg1, tmp_reg2
1088
1088
|| }
1089
1089
|.endmacro
1090
1090
@@ -1137,7 +1137,32 @@ static void* dasm_labels[zend_lb_MAX];
1137
1137
|.endmacro
1138
1138
1139
1139
|.macro EMALLOC, size, op_array, opline
1140
- | brk #0 // TODO
1140
+ ||#if ZEND_DEBUG
1141
+ || const char *filename = op_array->filename ? op_array->filename->val : NULL;
1142
+ | mov FCARG1x, #size
1143
+ | LOAD_ADDR FCARG2x, filename
1144
+ | LOAD_32BIT_VAL CARG3w, opline->lineno
1145
+ | mov CARG4, xzr
1146
+ | mov CARG5, xzr
1147
+ | EXT_CALL _emalloc, REG0
1148
+ | mov REG0, RETVALx
1149
+ ||#else
1150
+ ||#ifdef HAVE_BUILTIN_CONSTANT_P
1151
+ || if (size > 24 && size <= 32) {
1152
+ | EXT_CALL _emalloc_32, REG0
1153
+ | mov REG0, RETVALx
1154
+ || } else {
1155
+ | mov FCARG1x, #size
1156
+ | EXT_CALL _emalloc, REG0
1157
+ | mov REG0, RETVALx
1158
+ || }
1159
+ ||#else
1160
+ | brk #0 // TODO
1161
+ | mov FCARG1x, #size
1162
+ | EXT_CALL _emalloc, REG0
1163
+ | mov REG0, RETVALx
1164
+ ||#endif
1165
+ ||#endif
1141
1166
|.endmacro
1142
1167
1143
1168
|.macro OBJ_RELEASE, reg, exit_label, tmp_reg1, tmp_reg2
@@ -3115,8 +3140,8 @@ static int zend_jit_math_helper(dasm_State **Dst,
3115
3140
} else {
3116
3141
ZEND_UNREACHABLE();
3117
3142
}
3118
- | FREE_OP op1_type, op1, op1_info, 0, opline
3119
- | FREE_OP op2_type, op2, op2_info, 0, opline
3143
+ | FREE_OP op1_type, op1, op1_info, 0, opline, ZREG_TMP1, ZREG_TMP2
3144
+ | FREE_OP op2_type, op2, op2_info, 0, opline, ZREG_TMP1, ZREG_TMP2
3120
3145
if (may_throw) {
3121
3146
zend_jit_check_exception(Dst);
3122
3147
}
@@ -3804,7 +3829,36 @@ static int zend_jit_assign_to_variable(dasm_State **Dst,
3804
3829
if (Z_REG(var_use_addr) == ZREG_FCARG1x || Z_REG(var_use_addr) == ZREG_REG0) {
3805
3830
bool keep_gc = 0;
3806
3831
3807
- | brk #0 // TODO
3832
+ | GET_ZVAL_PTR Rx(tmp_reg), var_use_addr, TMP1
3833
+ if (tmp_reg == ZREG_FCARG1x) {
3834
+ if (Z_MODE(val_addr) == IS_REG) {
3835
+ keep_gc = 1;
3836
+ } else if ((val_info & ((MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_GUARD)-(MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_TRUE))) == 0) {
3837
+ keep_gc = 1;
3838
+ } else if (Z_MODE(val_addr) == IS_CONST_ZVAL) {
3839
+ zval *zv = Z_ZV(val_addr);
3840
+ if (Z_TYPE_P(zv) == IS_DOUBLE) {
3841
+ if (Z_DVAL_P(zv) == 0) {
3842
+ keep_gc = 1;
3843
+ }
3844
+ } else if (IS_SIGNED_32BIT(Z_LVAL_P(zv))) {
3845
+ keep_gc = 1;
3846
+ }
3847
+ } else if (Z_MODE(val_addr) == IS_MEM_ZVAL) {
3848
+ if ((val_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_GUARD)) == MAY_BE_DOUBLE) {
3849
+ keep_gc = 1;
3850
+ }
3851
+ }
3852
+ }
3853
+ if (!keep_gc) {
3854
+ | str Rx(tmp_reg), T1 // save
3855
+ }
3856
+ if (!zend_jit_simple_assign(Dst, opline, var_addr, var_info, var_def_info, val_type, val_addr, val_info, res_addr, in_cold, 0)) {
3857
+ return 0;
3858
+ }
3859
+ if (!keep_gc) {
3860
+ | ldr FCARG1x, T1 // restore
3861
+ }
3808
3862
} else {
3809
3863
| GET_ZVAL_PTR FCARG1x, var_use_addr, TMP1
3810
3864
if (!zend_jit_simple_assign(Dst, opline, var_addr, var_info, var_def_info, val_type, val_addr, val_info, res_addr, in_cold, 1)) {
@@ -3969,7 +4023,7 @@ static int zend_jit_assign_dim(dasm_State **Dst, const zend_op *opline, uint32_t
3969
4023
#endif
3970
4024
3971
4025
|9:
3972
- | FREE_OP opline->op2_type, opline->op2, op2_info, 0, opline
4026
+ | FREE_OP opline->op2_type, opline->op2, op2_info, 0, opline, ZREG_TMP1, ZREG_TMP2
3973
4027
3974
4028
if (may_throw) {
3975
4029
zend_jit_check_exception(Dst);
@@ -5792,7 +5846,75 @@ static int zend_jit_send_ref(dasm_State **Dst, const zend_op *opline, const zend
5792
5846
op1_addr = OP1_ADDR();
5793
5847
arg_addr = ZEND_ADDR_MEM_ZVAL(ZREG_RX, opline->result.var);
5794
5848
5795
- | brk #0 // TODO
5849
+ if (!zend_jit_reuse_ip(Dst)) {
5850
+ return 0;
5851
+ }
5852
+
5853
+ if (opline->op1_type == IS_VAR) {
5854
+ if (op1_info & MAY_BE_INDIRECT) {
5855
+ | LOAD_ZVAL_ADDR REG0, op1_addr
5856
+ | // if (EXPECTED(Z_TYPE_P(ret) == IS_INDIRECT)) {
5857
+ | IF_NOT_Z_TYPE REG0, IS_INDIRECT, >1, TMP1w
5858
+ | // ret = Z_INDIRECT_P(ret);
5859
+ | GET_Z_PTR REG0, REG0
5860
+ |1:
5861
+ op1_addr = ZEND_ADDR_MEM_ZVAL(ZREG_REG0, 0);
5862
+ }
5863
+ } else if (opline->op1_type == IS_CV) {
5864
+ if (op1_info & MAY_BE_UNDEF) {
5865
+ if (op1_info & (MAY_BE_ANY|MAY_BE_REF)) {
5866
+ | brk #0 // TODO
5867
+ }
5868
+ op1_info &= ~MAY_BE_UNDEF;
5869
+ op1_info |= MAY_BE_NULL;
5870
+ }
5871
+ } else {
5872
+ ZEND_UNREACHABLE();
5873
+ }
5874
+
5875
+ if (op1_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) {
5876
+ if (op1_info & MAY_BE_REF) {
5877
+ | IF_NOT_ZVAL_TYPE op1_addr, IS_REFERENCE, >2, TMP1w, TMP2
5878
+ | GET_ZVAL_PTR REG1, op1_addr, TMP1
5879
+ | GC_ADDREF REG1, TMP1w
5880
+ | SET_ZVAL_PTR arg_addr, REG1, TMP1
5881
+ | SET_ZVAL_TYPE_INFO arg_addr, IS_REFERENCE_EX, TMP1w, TMP2
5882
+ | b >6
5883
+ }
5884
+ |2:
5885
+ | // ZVAL_NEW_REF(arg, varptr);
5886
+ if (opline->op1_type == IS_VAR) {
5887
+ if (Z_REG(op1_addr) != ZREG_REG0 || Z_OFFSET(op1_addr) != 0) {
5888
+ | brk #0 // TODO
5889
+ | LOAD_ZVAL_ADDR REG0, op1_addr
5890
+ }
5891
+ | str REG0, T1 // save
5892
+ }
5893
+ | EMALLOC sizeof(zend_reference), op_array, opline // Allocate space in REG0
5894
+ | mov TMP1w, #2
5895
+ | str TMP1w, [REG0]
5896
+ || ZEND_ASSERT(GC_REFERENCE <= MAX_IMM12);
5897
+ | mov TMP1w, #GC_REFERENCE
5898
+ | str TMP1w, [REG0, #offsetof(zend_reference, gc.u.type_info)]
5899
+ | str xzr, [REG0, #offsetof(zend_reference, sources.ptr)]
5900
+ ref_addr = ZEND_ADDR_MEM_ZVAL(ZREG_REG0, offsetof(zend_reference, val));
5901
+ if (opline->op1_type == IS_VAR) {
5902
+ zend_jit_addr val_addr = ZEND_ADDR_MEM_ZVAL(ZREG_REG1, 0);
5903
+
5904
+ | ldr REG1, T1 // restore
5905
+ | ZVAL_COPY_VALUE ref_addr, MAY_BE_ANY, val_addr, op1_info, ZREG_REG2, ZREG_REG2, ZREG_TMP1, ZREG_TMP2, ZREG_FPR0
5906
+ | SET_ZVAL_PTR val_addr, REG0, TMP1
5907
+ | SET_ZVAL_TYPE_INFO val_addr, IS_REFERENCE_EX, TMP1w, TMP2
5908
+ } else {
5909
+ | brk #0 // TODO
5910
+ }
5911
+ | SET_ZVAL_PTR arg_addr, REG0, TMP1
5912
+ | SET_ZVAL_TYPE_INFO arg_addr, IS_REFERENCE_EX, TMP1w, TMP2
5913
+ }
5914
+
5915
+ |6:
5916
+ | FREE_OP opline->op1_type, opline->op1, op1_info, !cold, opline, ZREG_TMP1, ZREG_TMP2
5917
+ |7:
5796
5918
5797
5919
return 1;
5798
5920
}
@@ -6543,9 +6665,9 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst,
6543
6665
}
6544
6666
#endif
6545
6667
6546
- | FREE_OP opline->op2_type, opline->op2, op2_info, 0, opline
6668
+ | FREE_OP opline->op2_type, opline->op2, op2_info, 0, opline, ZREG_TMP1, ZREG_TMP2
6547
6669
if (opline->opcode != ZEND_FETCH_LIST_R && !op1_avoid_refcounting) {
6548
- | FREE_OP opline->op1_type, opline->op1, op1_info, 0, opline
6670
+ | FREE_OP opline->op1_type, opline->op1, op1_info, 0, opline, ZREG_TMP1, ZREG_TMP2
6549
6671
}
6550
6672
6551
6673
if (may_throw) {
@@ -6670,7 +6792,7 @@ static int zend_jit_fetch_dim(dasm_State **Dst,
6670
6792
#endif
6671
6793
6672
6794
|8:
6673
- | FREE_OP opline->op2_type, opline->op2, op2_info, 0, opline
6795
+ | FREE_OP opline->op2_type, opline->op2, op2_info, 0, opline, ZREG_TMP1, ZREG_TMP2
6674
6796
6675
6797
if (may_throw) {
6676
6798
if (!zend_jit_check_exception(Dst)) {
@@ -7127,7 +7249,6 @@ static int zend_jit_fetch_obj(dasm_State **Dst,
7127
7249
|5:
7128
7250
| SET_EX_OPLINE opline, REG0
7129
7251
if (opline->opcode == ZEND_FETCH_OBJ_W) {
7130
- | brk #0 // TODO
7131
7252
| EXT_CALL zend_jit_fetch_obj_w_slow, REG0
7132
7253
} else if (opline->opcode != ZEND_FETCH_OBJ_IS) {
7133
7254
| EXT_CALL zend_jit_fetch_obj_r_slow, REG0
@@ -7140,7 +7261,28 @@ static int zend_jit_fetch_obj(dasm_State **Dst,
7140
7261
7141
7262
if ((op1_info & ((MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)- MAY_BE_OBJECT)) && JIT_G(trigger) != ZEND_JIT_ON_HOT_TRACE) {
7142
7263
|7:
7143
- | brk #0 // TODO
7264
+ if (opline->opcode != ZEND_FETCH_OBJ_IS) {
7265
+ | SET_EX_OPLINE opline, REG0
7266
+ if (opline->opcode != ZEND_FETCH_OBJ_W
7267
+ && (op1_info & MAY_BE_UNDEF)) {
7268
+ zend_jit_addr orig_op1_addr = OP1_ADDR();
7269
+
7270
+ | brk #0 // TODO
7271
+ } else if (Z_REG(op1_addr) != ZREG_FCARG1x || Z_OFFSET(op1_addr) != 0) {
7272
+ | brk #0 // TODO
7273
+ | LOAD_ZVAL_ADDR FCARG1x, op1_addr
7274
+ }
7275
+ | LOAD_ADDR FCARG2x, Z_STRVAL_P(member)
7276
+ if (opline->opcode == ZEND_FETCH_OBJ_W) {
7277
+ | EXT_CALL zend_jit_invalid_property_write, REG0
7278
+ | SET_ZVAL_TYPE_INFO res_addr, _IS_ERROR, TMP1w, TMP2
7279
+ } else {
7280
+ | brk #0 // TODO
7281
+ }
7282
+ | b >9
7283
+ } else {
7284
+ | brk #0 // TODO
7285
+ }
7144
7286
}
7145
7287
7146
7288
if (!prop_info
@@ -7160,7 +7302,7 @@ static int zend_jit_fetch_obj(dasm_State **Dst,
7160
7302
7161
7303
| brk #0 // TODO
7162
7304
} else if (!op1_avoid_refcounting) {
7163
- | FREE_OP opline->op1_type, opline->op1, op1_info, 1, opline
7305
+ | FREE_OP opline->op1_type, opline->op1, op1_info, 1, opline, ZREG_TMP1, ZREG_TMP2
7164
7306
}
7165
7307
}
7166
7308
@@ -7352,14 +7494,14 @@ static int zend_jit_assign_obj_op(dasm_State **Dst,
7352
7494
7353
7495
|8:
7354
7496
| // FREE_OP_DATA();
7355
- | FREE_OP (opline+1)->op1_type, (opline+1)->op1, val_info, 0, opline
7497
+ | FREE_OP (opline+1)->op1_type, (opline+1)->op1, val_info, 0, opline, ZREG_TMP1, ZREG_TMP2
7356
7498
| b >9
7357
7499
|.code
7358
7500
}
7359
7501
7360
7502
|9:
7361
7503
if (opline->op1_type != IS_UNUSED && !use_this && !op1_indirect) {
7362
- | FREE_OP opline->op1_type, opline->op1, op1_info, 1, opline
7504
+ | FREE_OP opline->op1_type, opline->op1, op1_info, 1, opline, ZREG_TMP1, ZREG_TMP2
7363
7505
}
7364
7506
7365
7507
if (may_throw) {
@@ -7550,14 +7692,14 @@ static int zend_jit_assign_obj(dasm_State **Dst,
7550
7692
7551
7693
|8:
7552
7694
| // FREE_OP_DATA();
7553
- | FREE_OP (opline+1)->op1_type, (opline+1)->op1, val_info, 0, opline
7695
+ | FREE_OP (opline+1)->op1_type, (opline+1)->op1, val_info, 0, opline, ZREG_TMP1, ZREG_TMP2
7554
7696
| b >9
7555
7697
|.code
7556
7698
}
7557
7699
7558
7700
|9:
7559
7701
if (opline->op1_type != IS_UNUSED && !use_this && !op1_indirect) {
7560
- | FREE_OP opline->op1_type, opline->op1, op1_info, 1, opline
7702
+ | FREE_OP opline->op1_type, opline->op1, op1_info, 1, opline, ZREG_TMP1, ZREG_TMP2
7561
7703
}
7562
7704
7563
7705
if (may_throw) {
0 commit comments