Skip to content

Commit b3e2178

Browse files
shqkingdstogov
authored andcommitted
Support failed JIT test case: fetch_obj_001.phpt
This test case is a big one. Major changes are: 1. statement "foo($obj->a)" One new path is covered in function zend_jit_fetch_obj() for the involved FETCH_OBJ_W opcode. See the update around label 5. Opcode SEND_REF is used. The updates in function zend_jit_send_ref() are made to support it. Note that macro FREE_OP is executed for the first time. Temproray registers are passed since they are used inside. As a result, its use sites are updated accordingly. 2. statement "$a = array()" in $foo2 One new path in function zend_jit_assign_to_variable() is covered. 3. statements involving variable $d in $bar One new path in function zend_jit_fetch_obj() is covered. See the updates around label 7. Note that in macro EMALLOC, condition ZEND_DEBUG can be covered by DEBUG build, i.e. "./configure --enable-debug".
1 parent 178f274 commit b3e2178

File tree

1 file changed

+161
-19
lines changed

1 file changed

+161
-19
lines changed

ext/opcache/jit/zend_jit_arm64.dasc

Lines changed: 161 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,10 +1081,10 @@ static void* dasm_labels[zend_lb_MAX];
10811081
|| }
10821082
|.endmacro
10831083

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
10851085
|| 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
10881088
|| }
10891089
|.endmacro
10901090

@@ -1137,7 +1137,32 @@ static void* dasm_labels[zend_lb_MAX];
11371137
|.endmacro
11381138

11391139
|.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
11411166
|.endmacro
11421167

11431168
|.macro OBJ_RELEASE, reg, exit_label, tmp_reg1, tmp_reg2
@@ -3115,8 +3140,8 @@ static int zend_jit_math_helper(dasm_State **Dst,
31153140
} else {
31163141
ZEND_UNREACHABLE();
31173142
}
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
31203145
if (may_throw) {
31213146
zend_jit_check_exception(Dst);
31223147
}
@@ -3804,7 +3829,36 @@ static int zend_jit_assign_to_variable(dasm_State **Dst,
38043829
if (Z_REG(var_use_addr) == ZREG_FCARG1x || Z_REG(var_use_addr) == ZREG_REG0) {
38053830
bool keep_gc = 0;
38063831

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+
}
38083862
} else {
38093863
| GET_ZVAL_PTR FCARG1x, var_use_addr, TMP1
38103864
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
39694023
#endif
39704024

39714025
|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
39734027

39744028
if (may_throw) {
39754029
zend_jit_check_exception(Dst);
@@ -5792,7 +5846,75 @@ static int zend_jit_send_ref(dasm_State **Dst, const zend_op *opline, const zend
57925846
op1_addr = OP1_ADDR();
57935847
arg_addr = ZEND_ADDR_MEM_ZVAL(ZREG_RX, opline->result.var);
57945848

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:
57965918

57975919
return 1;
57985920
}
@@ -6543,9 +6665,9 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst,
65436665
}
65446666
#endif
65456667

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
65476669
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
65496671
}
65506672

65516673
if (may_throw) {
@@ -6670,7 +6792,7 @@ static int zend_jit_fetch_dim(dasm_State **Dst,
66706792
#endif
66716793

66726794
|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
66746796

66756797
if (may_throw) {
66766798
if (!zend_jit_check_exception(Dst)) {
@@ -7127,7 +7249,6 @@ static int zend_jit_fetch_obj(dasm_State **Dst,
71277249
|5:
71287250
| SET_EX_OPLINE opline, REG0
71297251
if (opline->opcode == ZEND_FETCH_OBJ_W) {
7130-
| brk #0 // TODO
71317252
| EXT_CALL zend_jit_fetch_obj_w_slow, REG0
71327253
} else if (opline->opcode != ZEND_FETCH_OBJ_IS) {
71337254
| EXT_CALL zend_jit_fetch_obj_r_slow, REG0
@@ -7140,7 +7261,28 @@ static int zend_jit_fetch_obj(dasm_State **Dst,
71407261

71417262
if ((op1_info & ((MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)- MAY_BE_OBJECT)) && JIT_G(trigger) != ZEND_JIT_ON_HOT_TRACE) {
71427263
|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+
}
71447286
}
71457287

71467288
if (!prop_info
@@ -7160,7 +7302,7 @@ static int zend_jit_fetch_obj(dasm_State **Dst,
71607302

71617303
| brk #0 // TODO
71627304
} 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
71647306
}
71657307
}
71667308

@@ -7352,14 +7494,14 @@ static int zend_jit_assign_obj_op(dasm_State **Dst,
73527494

73537495
|8:
73547496
| // 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
73567498
| b >9
73577499
|.code
73587500
}
73597501

73607502
|9:
73617503
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
73637505
}
73647506

73657507
if (may_throw) {
@@ -7550,14 +7692,14 @@ static int zend_jit_assign_obj(dasm_State **Dst,
75507692

75517693
|8:
75527694
| // 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
75547696
| b >9
75557697
|.code
75567698
}
75577699

75587700
|9:
75597701
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
75617703
}
75627704

75637705
if (may_throw) {

0 commit comments

Comments
 (0)