@@ -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