@@ -3039,9 +3039,13 @@ static void zend_jit_setup_disasm(void)
30393039 REGISTER_HELPER(zend_jit_assign_dim_op_helper);
30403040 REGISTER_HELPER(zend_jit_fetch_obj_w_slow);
30413041 REGISTER_HELPER(zend_jit_fetch_obj_r_slow);
3042+ REGISTER_HELPER(zend_jit_fetch_obj_r_slow_ex);
30423043 REGISTER_HELPER(zend_jit_fetch_obj_is_slow);
3044+ REGISTER_HELPER(zend_jit_fetch_obj_is_slow_ex);
30433045 REGISTER_HELPER(zend_jit_fetch_obj_r_dynamic);
3046+ REGISTER_HELPER(zend_jit_fetch_obj_r_dynamic_ex);
30443047 REGISTER_HELPER(zend_jit_fetch_obj_is_dynamic);
3048+ REGISTER_HELPER(zend_jit_fetch_obj_is_dynamic_ex);
30453049 REGISTER_HELPER(zend_jit_check_array_promotion);
30463050 REGISTER_HELPER(zend_jit_create_typed_ref);
30473051 REGISTER_HELPER(zend_jit_invalid_property_write);
@@ -13662,20 +13666,21 @@ static int zend_jit_fetch_obj(zend_jit_ctx *jit,
1366213666 bool delayed_fetch_this,
1366313667 bool op1_avoid_refcounting,
1366413668 zend_class_entry *trace_ce,
13669+ zend_jit_addr res_addr,
1366513670 uint8_t prop_type,
1366613671 int may_throw)
1366713672{
1366813673 zval *member;
1366913674 zend_property_info *prop_info;
1367013675 bool may_be_dynamic = 1;
13671- zend_jit_addr res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->result.var);
1367213676 zend_jit_addr prop_addr;
1367313677 uint32_t res_info = RES_INFO();
1367413678 ir_ref prop_type_ref = IR_UNUSED;
1367513679 ir_ref obj_ref = IR_UNUSED;
1367613680 ir_ref prop_ref = IR_UNUSED;
1367713681 ir_ref end_inputs = IR_UNUSED;
1367813682 ir_ref slow_inputs = IR_UNUSED;
13683+ ir_ref end_values = IR_UNUSED;
1367913684
1368013685 ZEND_ASSERT(opline->op2_type == IS_CONST);
1368113686 ZEND_ASSERT(op1_info & MAY_BE_OBJECT);
@@ -13804,13 +13809,28 @@ static int zend_jit_fetch_obj(zend_jit_ctx *jit,
1380413809 jit_SET_EX_OPLINE(jit, opline);
1380513810
1380613811 if (opline->opcode != ZEND_FETCH_OBJ_IS) {
13807- ir_CALL_2(IR_VOID, ir_CONST_FC_FUNC(zend_jit_fetch_obj_r_dynamic),
13808- obj_ref, offset_ref);
13812+ if (((res_info & MAY_BE_GUARD) && JIT_G(current_frame) && prop_info)
13813+ || Z_MODE(res_addr) == IS_REG) {
13814+ ir_ref val_addr = ir_CALL_2(IR_ADDR, ir_CONST_FC_FUNC(zend_jit_fetch_obj_r_dynamic_ex),
13815+ obj_ref, offset_ref);
13816+ ir_END_PHI_list(end_values, val_addr);
13817+ } else {
13818+ ir_CALL_2(IR_VOID, ir_CONST_FC_FUNC(zend_jit_fetch_obj_r_dynamic),
13819+ obj_ref, offset_ref);
13820+ ir_END_list(end_inputs);
13821+ }
1380913822 } else {
13810- ir_CALL_2(IR_VOID, ir_CONST_FC_FUNC(zend_jit_fetch_obj_is_dynamic),
13811- obj_ref, offset_ref);
13823+ if (((res_info & MAY_BE_GUARD) && JIT_G(current_frame) && prop_info)
13824+ || Z_MODE(res_addr) == IS_REG) {
13825+ ir_ref val_addr = ir_CALL_2(IR_ADDR, ir_CONST_FC_FUNC(zend_jit_fetch_obj_is_dynamic_ex),
13826+ obj_ref, offset_ref);
13827+ ir_END_PHI_list(end_values, val_addr);
13828+ } else {
13829+ ir_CALL_2(IR_VOID, ir_CONST_FC_FUNC(zend_jit_fetch_obj_is_dynamic),
13830+ obj_ref, offset_ref);
13831+ ir_END_list(end_inputs);
13832+ }
1381213833 }
13813- ir_END_list(end_inputs);
1381413834 }
1381513835 ir_IF_FALSE(if_dynamic);
1381613836 }
@@ -13996,12 +14016,56 @@ static int zend_jit_fetch_obj(zend_jit_ctx *jit,
1399614016 }
1399714017 ir_END_list(end_inputs);
1399814018 } else {
14019+ if (((res_info & MAY_BE_GUARD) && JIT_G(current_frame) && prop_info)
14020+ || Z_MODE(res_addr) == IS_REG) {
14021+ ir_END_PHI_list(end_values, jit_ZVAL_ADDR(jit, prop_addr));
14022+ } else {
14023+ prop_type_ref = jit_Z_TYPE_INFO(jit, prop_addr);
14024+
14025+ if (!zend_jit_zval_copy_deref(jit, res_addr, prop_addr, prop_type_ref)) {
14026+ return 0;
14027+ }
14028+ ir_END_list(end_inputs);
14029+ }
14030+ }
14031+
14032+ if (op1_avoid_refcounting) {
14033+ SET_STACK_REG(JIT_G(current_frame)->stack, EX_VAR_TO_NUM(opline->op1.var), ZREG_NONE);
14034+ }
14035+
14036+ if (JIT_G(trigger) != ZEND_JIT_ON_HOT_TRACE || !prop_info) {
14037+ ir_MERGE_list(slow_inputs);
14038+ jit_SET_EX_OPLINE(jit, opline);
14039+
14040+ if (opline->opcode == ZEND_FETCH_OBJ_W) {
14041+ ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_fetch_obj_w_slow), obj_ref);
14042+ ir_END_list(end_inputs);
14043+ } else if (opline->opcode != ZEND_FETCH_OBJ_IS) {
14044+ if (Z_MODE(res_addr) == IS_REG) {
14045+ ir_ref val_ref = ir_CALL_1(IR_ADDR, ir_CONST_FC_FUNC(zend_jit_fetch_obj_r_slow_ex), obj_ref);
14046+ ir_END_PHI_list(end_values, val_ref);
14047+ } else {
14048+ ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_fetch_obj_r_slow), obj_ref);
14049+ ir_END_list(end_inputs);
14050+ }
14051+ } else {
14052+ ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_fetch_obj_is_slow), obj_ref);
14053+ ir_END_list(end_inputs);
14054+ }
14055+ }
14056+
14057+ if (end_values) {
14058+ ir_ref val_ref = ir_PHI_list(end_values);
14059+ zend_jit_addr val_addr = ZEND_ADDR_REF_ZVAL(val_ref);
1399914060 bool result_avoid_refcounting = 0;
1400014061
14001- if ((res_info & MAY_BE_GUARD) && JIT_G(current_frame) && prop_info) {
14062+ ZEND_ASSERT(opline->opcode == ZEND_FETCH_OBJ_R
14063+ || opline->opcode == ZEND_FETCH_OBJ_FUNC_ARG
14064+ || opline->opcode == ZEND_FETCH_OBJ_IS);
14065+ ZEND_ASSERT(end_inputs == IR_UNUSED);
14066+ if ((res_info & MAY_BE_GUARD) && JIT_G(current_frame)) {
1400214067 uint8_t type = concrete_type(res_info);
1400314068 uint32_t flags = 0;
14004- zend_jit_addr val_addr = prop_addr;
1400514069
1400614070 if ((opline->op1_type & (IS_VAR|IS_TMP_VAR))
1400714071 && !delayed_fetch_this
@@ -14026,39 +14090,14 @@ static int zend_jit_fetch_obj(zend_jit_ctx *jit,
1402614090
1402714091 res_info &= ~MAY_BE_GUARD;
1402814092 ssa->var_info[ssa_op->result_def].type &= ~MAY_BE_GUARD;
14029-
14030- // ZVAL_COPY
14031- jit_ZVAL_COPY(jit, res_addr, -1, val_addr, res_info, !result_avoid_refcounting);
14032- } else {
14033- prop_type_ref = jit_Z_TYPE_INFO(jit, prop_addr);
14034-
14035- if (!zend_jit_zval_copy_deref(jit, res_addr, prop_addr, prop_type_ref)) {
14036- return 0;
14037- }
1403814093 }
14039- ir_END_list(end_inputs);
14040- }
14041-
14042- if (op1_avoid_refcounting) {
14043- SET_STACK_REG(JIT_G(current_frame)->stack, EX_VAR_TO_NUM(opline->op1.var), ZREG_NONE);
14044- }
14045-
14046- if (JIT_G(trigger) != ZEND_JIT_ON_HOT_TRACE || !prop_info) {
14047- ir_MERGE_list(slow_inputs);
14048- jit_SET_EX_OPLINE(jit, opline);
1404914094
14050- if (opline->opcode == ZEND_FETCH_OBJ_W) {
14051- ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_fetch_obj_w_slow), obj_ref);
14052- } else if (opline->opcode != ZEND_FETCH_OBJ_IS) {
14053- ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_fetch_obj_r_slow), obj_ref);
14054- } else {
14055- ir_CALL_1(IR_VOID, ir_CONST_FC_FUNC(zend_jit_fetch_obj_is_slow), obj_ref);
14056- }
14057- ir_END_list(end_inputs);
14095+ // ZVAL_COPY
14096+ jit_ZVAL_COPY(jit, res_addr, -1, val_addr, res_info, !result_avoid_refcounting);
14097+ } else {
14098+ ir_MERGE_list(end_inputs);
1405814099 }
1405914100
14060- ir_MERGE_list(end_inputs);
14061-
1406214101 if (opline->op1_type != IS_UNUSED && !delayed_fetch_this && !op1_indirect) {
1406314102 if (opline->op1_type == IS_VAR
1406414103 && opline->opcode == ZEND_FETCH_OBJ_W
@@ -16662,6 +16701,14 @@ static bool zend_jit_opline_supports_reg(const zend_op_array *op_array, zend_ssa
1666216701 return ((op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) &&
1666316702 (((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_LONG) ||
1666416703 ((op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_STRING));
16704+ case ZEND_FETCH_OBJ_R:
16705+ if (opline->op2_type != IS_CONST
16706+ || Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) != IS_STRING
16707+ || Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))[0] == '\0') {
16708+ return 0;
16709+ }
16710+ op1_info = OP1_INFO();
16711+ return opline->op1_type == IS_UNUSED || (op1_info & MAY_BE_OBJECT);
1666516712 }
1666616713 return 0;
1666716714}
0 commit comments