Skip to content

Commit c5d6fc0

Browse files
shqkingdstogov
authored andcommitted
Support failed JIT test case: fetch_dim_r_002.phpt
The opcodes for function $foo are: 0001 INIT_FCALL 1 96 string("var_dump") 0002 #2.T1 [null, long] = FETCH_DIM_R array(...) #1.CV0($n) [...] 0003 SEND_VAL #2.T1 [null, long] 1 0004 DO_ICALL 0005 RETURN null Opcode FETCH_DIM_R is not touched before, and the updates in function zend_jit_fetch_dim_read() are made to support it. As different types of arguments are used for $foo, several cases in function zend_jit_fetch_dimension_address_inner() are covered as well. Besides, opcode DO_ICALL can reach one site of cold code in function zend_jit_do_fcall().
1 parent 99118a6 commit c5d6fc0

File tree

1 file changed

+229
-9
lines changed

1 file changed

+229
-9
lines changed

ext/opcache/jit/zend_jit_arm64.dasc

+229-9
Original file line numberDiff line numberDiff line change
@@ -3212,7 +3212,6 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
32123212

32133213
if (op2_info & ((MAY_BE_ANY|MAY_BE_UNDEF) - MAY_BE_LONG)) {
32143214
| // if (EXPECTED(Z_TYPE_P(dim) == IS_LONG))
3215-
| brk #0 // TODO
32163215
| IF_NOT_ZVAL_TYPE op2_addr, IS_LONG, >3, TMP1w, TMP2
32173216
}
32183217
if (op1_info & MAY_BE_PACKED_GUARD) {
@@ -3240,7 +3239,6 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
32403239
} else {
32413240
if (!op2_loaded) {
32423241
| // hval = Z_LVAL_P(dim);
3243-
| brk #0 // TODO
32443242
| GET_ZVAL_LVAL ZREG_FCARG2x, op2_addr, TMP1
32453243
op2_loaded = 1;
32463244
}
@@ -3303,7 +3301,34 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
33033301
case BP_VAR_R:
33043302
case BP_VAR_IS:
33053303
case BP_VAR_UNSET:
3304+
if (packed_loaded) {
3305+
| brk #0 // TODO
3306+
}
3307+
if (!(op1_info & MAY_BE_ARRAY_KEY_LONG) || (packed_loaded && (op1_info & MAY_BE_ARRAY_HASH))) {
3308+
| brk #0 // TODO
3309+
}
3310+
if (op1_info & MAY_BE_ARRAY_HASH) {
3311+
|4:
3312+
if (!op2_loaded) {
3313+
| brk #0 // TODO
3314+
}
3315+
| EXT_CALL _zend_hash_index_find, REG0
3316+
| mov REG0, RETVALx
3317+
| tst REG0, REG0
3318+
if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE && type == BP_VAR_R) {
3319+
| brk #0 // TODO
3320+
} else if (type == BP_VAR_IS && not_found_exit_addr) {
3321+
| brk #0 // TODO
3322+
} else if (type == BP_VAR_IS && found_exit_addr) {
3323+
| brk #0 // TODO
3324+
} else {
3325+
| beq >2 // NOT_FOUND
3326+
}
3327+
}
3328+
|.cold_code
3329+
|2:
33063330
| brk #0 // TODO
3331+
|.code
33073332
break;
33083333
case BP_VAR_RW:
33093334
| brk #0 // TODO
@@ -3336,7 +3361,6 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
33363361
}
33373362

33383363
if (type != BP_JIT_IS && (op2_info & MAY_BE_STRING)) {
3339-
| brk #0 // TODO
33403364
| b >8
33413365
}
33423366
}
@@ -3345,7 +3369,6 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
33453369
|3:
33463370
if (op2_info & ((MAY_BE_ANY|MAY_BE_UNDEF) - (MAY_BE_LONG|MAY_BE_STRING))) {
33473371
| // if (EXPECTED(Z_TYPE_P(dim) == IS_STRING))
3348-
| brk #0 // TODO
33493372
| IF_NOT_ZVAL_TYPE op2_addr, IS_STRING, >3, TMP1w, TMP2
33503373
}
33513374
| // offset_key = Z_STR_P(dim);
@@ -3358,7 +3381,36 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
33583381
case BP_VAR_R:
33593382
case BP_VAR_IS:
33603383
case BP_VAR_UNSET:
3361-
| brk #0 // TODO
3384+
if (opline->op2_type != IS_CONST) {
3385+
| ldrb TMP1w, [FCARG2x, #offsetof(zend_string, val)]
3386+
| cmp TMP1w, #((uint8_t) ('9'))
3387+
| ble >1
3388+
|.cold_code
3389+
|1:
3390+
| EXT_CALL zend_jit_symtable_find, REG0
3391+
| b >1
3392+
|.code
3393+
| EXT_CALL zend_hash_find, REG0
3394+
|1:
3395+
} else {
3396+
| brk #0 // TODO
3397+
| EXT_CALL _zend_hash_find_known_hash, REG0
3398+
}
3399+
| mov REG0, RETVALx
3400+
| tst REG0, REG0
3401+
if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE && type == BP_VAR_R) {
3402+
| brk #0 // TODO
3403+
} else if (type == BP_VAR_IS && not_found_exit_addr) {
3404+
| brk #0 // TODO
3405+
} else if (type == BP_VAR_IS && found_exit_addr) {
3406+
| brk #0 // TODO
3407+
} else {
3408+
| beq >2 // NOT_FOUND
3409+
|.cold_code
3410+
|2:
3411+
| brk #0 // TODO
3412+
|.code
3413+
}
33623414
break;
33633415
case BP_VAR_RW:
33643416
| brk #0 // TODO
@@ -3386,7 +3438,34 @@ static int zend_jit_fetch_dimension_address_inner(dasm_State **Dst, const zend_o
33863438
|.cold_code
33873439
|3:
33883440
}
3389-
| brk #0 // TODO
3441+
| SET_EX_OPLINE opline, REG0
3442+
| LOAD_ZVAL_ADDR FCARG2x, op2_addr
3443+
switch (type) {
3444+
case BP_VAR_R:
3445+
| LOAD_ZVAL_ADDR CARG3, res_addr
3446+
| EXT_CALL zend_jit_fetch_dim_r_helper, REG0
3447+
| mov REG0, RETVALx
3448+
| b >9
3449+
break;
3450+
case BP_JIT_IS:
3451+
| brk #0 // TODO
3452+
break;
3453+
case BP_VAR_IS:
3454+
case BP_VAR_UNSET:
3455+
| brk #0 // TODO
3456+
break;
3457+
case BP_VAR_RW:
3458+
| brk #0 // TODO
3459+
break;
3460+
case BP_VAR_W:
3461+
| brk #0 // TODO
3462+
break;
3463+
default:
3464+
ZEND_UNREACHABLE();
3465+
}
3466+
if (op2_info & (MAY_BE_LONG|MAY_BE_STRING)) {
3467+
|.code
3468+
}
33903469
}
33913470

33923471
return 1;
@@ -5381,10 +5460,9 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend
53815460
| // zend_vm_stack_free_call_frame(call);
53825461
| ldrb TMP1w, [RX, #(offsetof(zend_execute_data, This.u1.type_info) + 2)]
53835462
| tst TMP1w, #((ZEND_CALL_ALLOCATED >> 16) & 0xff)
5384-
| bne >1 // TODO: test. In current case, don't jump to cold-code.
5463+
| bne >1
53855464
|.cold_code
53865465
|1:
5387-
| brk #0 // TODO
53885466
| mov FCARG1x, RX
53895467
| EXT_CALL zend_jit_free_call_frame, REG0
53905468
| b >1
@@ -6102,7 +6180,149 @@ static int zend_jit_fetch_dim_read(dasm_State **Dst,
61026180
orig_op1_addr = OP1_ADDR();
61036181
op2_addr = OP2_ADDR();
61046182

6105-
| brk #0 // TODO
6183+
if (opline->opcode != ZEND_FETCH_DIM_IS
6184+
&& JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE) {
6185+
int32_t exit_point = zend_jit_trace_get_exit_point(opline, ZEND_JIT_EXIT_TO_VM);
6186+
exit_addr = zend_jit_trace_get_exit_addr(exit_point);
6187+
if (!exit_addr) {
6188+
return 0;
6189+
}
6190+
}
6191+
6192+
if ((res_info & MAY_BE_GUARD)
6193+
&& JIT_G(current_frame)
6194+
&& (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) {
6195+
uint32_t flags = 0;
6196+
uint32_t old_op1_info = 0;
6197+
uint32_t old_info;
6198+
zend_jit_trace_stack *stack = JIT_G(current_frame)->stack;
6199+
int32_t exit_point;
6200+
6201+
if (opline->opcode != ZEND_FETCH_LIST_R
6202+
&& (opline->op1_type & (IS_VAR|IS_TMP_VAR))
6203+
&& !op1_avoid_refcounting) {
6204+
flags |= ZEND_JIT_EXIT_FREE_OP1;
6205+
}
6206+
if ((opline->op2_type & (IS_VAR|IS_TMP_VAR))
6207+
&& (op2_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE))) {
6208+
flags |= ZEND_JIT_EXIT_FREE_OP2;
6209+
}
6210+
if ((opline->result_type & (IS_VAR|IS_TMP_VAR))
6211+
&& !(flags & ZEND_JIT_EXIT_FREE_OP1)
6212+
&& (res_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE))
6213+
&& (ssa_op+1)->op1_use == ssa_op->result_def
6214+
&& !(op2_info & ((MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF) - (MAY_BE_STRING|MAY_BE_LONG)))
6215+
&& zend_jit_may_avoid_refcounting(opline+1)) {
6216+
result_avoid_refcounting = 1;
6217+
ssa->var_info[ssa_op->result_def].avoid_refcounting = 1;
6218+
}
6219+
6220+
if (op1_avoid_refcounting) {
6221+
old_op1_info = STACK_INFO(stack, EX_VAR_TO_NUM(opline->op1.var));
6222+
SET_STACK_REG(stack, EX_VAR_TO_NUM(opline->op1.var), ZREG_NONE);
6223+
}
6224+
6225+
if (!(op2_info & ((MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF) - (MAY_BE_STRING|MAY_BE_LONG)))) {
6226+
old_info = STACK_INFO(stack, EX_VAR_TO_NUM(opline->result.var));
6227+
SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->result.var), IS_UNKNOWN, 1);
6228+
SET_STACK_REG(stack, EX_VAR_TO_NUM(opline->result.var), ZREG_ZVAL_COPY_GPR0);
6229+
exit_point = zend_jit_trace_get_exit_point(opline+1, flags);
6230+
SET_STACK_INFO(stack, EX_VAR_TO_NUM(opline->result.var), old_info);
6231+
res_exit_addr = zend_jit_trace_get_exit_addr(exit_point);
6232+
if (!res_exit_addr) {
6233+
return 0;
6234+
}
6235+
res_info &= ~MAY_BE_GUARD;
6236+
ssa->var_info[ssa_op->result_def].type &= ~MAY_BE_GUARD;
6237+
}
6238+
6239+
if (opline->opcode == ZEND_FETCH_DIM_IS
6240+
&& !(res_info & MAY_BE_NULL)) {
6241+
old_info = STACK_INFO(stack, EX_VAR_TO_NUM(opline->result.var));
6242+
SET_STACK_TYPE(stack, EX_VAR_TO_NUM(opline->result.var), IS_NULL, 0);
6243+
SET_STACK_REG(stack, EX_VAR_TO_NUM(opline->result.var), ZREG_NULL);
6244+
exit_point = zend_jit_trace_get_exit_point(opline+1, flags);
6245+
SET_STACK_INFO(stack, EX_VAR_TO_NUM(opline->result.var), old_info);
6246+
not_found_exit_addr = zend_jit_trace_get_exit_addr(exit_point);
6247+
if (!not_found_exit_addr) {
6248+
return 0;
6249+
}
6250+
}
6251+
6252+
if (op1_avoid_refcounting) {
6253+
SET_STACK_INFO(stack, EX_VAR_TO_NUM(opline->op1.var), old_op1_info);
6254+
}
6255+
}
6256+
6257+
if (op1_info & MAY_BE_REF) {
6258+
| brk #0 // TODO
6259+
op1_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FCARG1x, 0);
6260+
}
6261+
6262+
if (op1_info & MAY_BE_ARRAY) {
6263+
if (op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF) - MAY_BE_ARRAY)) {
6264+
| brk #0 // TODO
6265+
}
6266+
| GET_ZVAL_LVAL ZREG_FCARG1x, op1_addr, TMP1
6267+
if (!zend_jit_fetch_dimension_address_inner(Dst, opline, (opline->opcode != ZEND_FETCH_DIM_IS) ? BP_VAR_R : BP_VAR_IS, op1_info, op2_info, res_exit_addr, not_found_exit_addr, exit_addr)) {
6268+
return 0;
6269+
}
6270+
}
6271+
6272+
if (op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-MAY_BE_ARRAY)) {
6273+
if (op1_info & MAY_BE_ARRAY) {
6274+
|.cold_code
6275+
|7:
6276+
}
6277+
6278+
| brk #0 // TODO
6279+
6280+
if (op1_info & MAY_BE_ARRAY) {
6281+
|.code
6282+
}
6283+
}
6284+
6285+
if (op1_info & MAY_BE_ARRAY) {
6286+
zend_jit_addr val_addr = ZEND_ADDR_MEM_ZVAL(ZREG_REG0, 0);
6287+
6288+
|8:
6289+
if (res_exit_addr) {
6290+
zend_uchar type = concrete_type(res_info);
6291+
6292+
| brk #0 // TODO
6293+
} else if (op1_info & MAY_BE_ARRAY_OF_REF) {
6294+
| brk #0 // TODO
6295+
if (!zend_jit_zval_copy_deref(Dst, res_addr, val_addr, ZREG_REG2)) {
6296+
return 0;
6297+
}
6298+
} else {
6299+
| // ZVAL_COPY
6300+
| ZVAL_COPY_VALUE res_addr, -1, val_addr, res_info, ZREG_REG1, ZREG_REG2, ZREG_TMP1, ZREG_TMP2, ZREG_FPR0
6301+
| lsr REG1w, REG1w, #8
6302+
| and REG1w, REG1w, #0xff
6303+
| TRY_ADDREF res_info, REG1w, REG2, TMP1
6304+
}
6305+
}
6306+
|9: // END
6307+
6308+
#ifdef ZEND_JIT_USE_RC_INFERENCE
6309+
if ((opline->op2_type & (IS_TMP_VAR|IS_VAR)) && (op1_info & MAY_BE_OBJECT)) {
6310+
/* Magic offsetGet() may increase refcount of the key */
6311+
op2_info |= MAY_BE_RCN;
6312+
}
6313+
#endif
6314+
6315+
| FREE_OP opline->op2_type, opline->op2, op2_info, 0, opline
6316+
if (opline->opcode != ZEND_FETCH_LIST_R && !op1_avoid_refcounting) {
6317+
| FREE_OP opline->op1_type, opline->op1, op1_info, 0, opline
6318+
}
6319+
6320+
if (may_throw) {
6321+
if (!zend_jit_check_exception(Dst)) {
6322+
return 0;
6323+
}
6324+
}
6325+
61066326
return 1;
61076327
}
61086328

0 commit comments

Comments
 (0)