]> granicus.if.org Git - php/commitdiff
Use guards for ZEND_FETCH_OBJ_R/IS to eliminate repeatable checks
authorDmitry Stogov <dmitry@zend.com>
Thu, 18 Jun 2020 08:10:47 +0000 (11:10 +0300)
committerDmitry Stogov <dmitry@zend.com>
Thu, 18 Jun 2020 08:10:47 +0000 (11:10 +0300)
ext/opcache/jit/zend_jit.c
ext/opcache/jit/zend_jit_trace.c
ext/opcache/jit/zend_jit_x86.dasc

index 3f37a07b3ec2cf9192fa3bc5c2201000e3c446ad..223dd53ba6db2b93af9eb25073e80bc06295bf1d 100644 (file)
@@ -2767,9 +2767,14 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
                                                ce = NULL;
                                                if (opline->op1_type == IS_UNUSED) {
                                                        op1_info = MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN;
+                                                       op1_addr = 0;
                                                        ce = op_array->scope;
                                                } else {
                                                        op1_info = OP1_INFO();
+                                                       if (!(op1_info & MAY_BE_OBJECT)) {
+                                                               break;
+                                                       }
+                                                       op1_addr = OP1_REG_ADDR();
                                                        if (ssa->var_info && ssa->ops) {
                                                                zend_ssa_op *ssa_op = &ssa->ops[opline - op_array->opcodes];
                                                                if (ssa_op->op1_use >= 0) {
@@ -2780,11 +2785,8 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
                                                                }
                                                        }
                                                }
-                                               if (!(op1_info & MAY_BE_OBJECT)) {
-                                                       break;
-                                               }
                                                if (!zend_jit_fetch_obj_read(&dasm_state, opline, op_array,
-                                                               op1_info, ce,
+                                                               op1_info, op1_addr, ce,
                                                                zend_may_throw(opline, ssa_op, op_array, ssa))) {
                                                        goto jit_failure;
                                                }
index 33e0cd714ca41a305314953b35daa702a1b293aa..3bcb5a7697d74f591f8d85ae24ee0b033be0c570 100644 (file)
@@ -1547,6 +1547,23 @@ propagate_arg:
                                                }
                                        }
                                        break;
+                               case ZEND_FETCH_OBJ_FUNC_ARG:
+                                       if (!frame
+                                        || !frame->call
+                                        || !frame->call->func
+                                        || !TRACE_FRAME_IS_LAST_SEND_BY_VAL(frame->call)) {
+                                               break;
+                                       }
+                                       /* break missing intentionally */
+                               case ZEND_FETCH_OBJ_R:
+                               case ZEND_FETCH_OBJ_IS:
+                                       if (opline->op2_type != IS_CONST
+                                        || Z_TYPE_P(RT_CONSTANT(opline, opline->op2)) != IS_STRING
+                                        || Z_STRVAL_P(RT_CONSTANT(opline, opline->op2))[0] == '\0') {
+                                               break;
+                                       }
+                                       ADD_OP1_TRACE_GUARD();
+                                       break;
                                default:
                                        break;
                        }
@@ -3720,8 +3737,21 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
                                                if (opline->op1_type == IS_UNUSED) {
                                                        op1_info = MAY_BE_OBJECT|MAY_BE_RC1|MAY_BE_RCN;
                                                        ce = op_array->scope;
+                                                       op1_addr = 0;
                                                } else {
                                                        op1_info = OP1_INFO();
+                                                       if (!(op1_info & MAY_BE_OBJECT)) {
+                                                               break;
+                                                       }
+                                                       op1_addr = OP1_REG_ADDR();
+                                                       if (orig_op1_type != IS_UNKNOWN
+                                                        && (orig_op1_type & IS_TRACE_REFERENCE)) {
+                                                               if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr, 1)) {
+                                                                       goto jit_failure;
+                                                               }
+                                                       } else {
+                                                               CHECK_OP1_TRACE_TYPE();
+                                                       }
                                                        if (ssa->var_info && ssa->ops) {
                                                                if (ssa_op->op1_use >= 0) {
                                                                        zend_ssa_var_info *op1_ssa = ssa->var_info + ssa_op->op1_use;
@@ -3731,11 +3761,8 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
                                                                }
                                                        }
                                                }
-                                               if (!(op1_info & MAY_BE_OBJECT)) {
-                                                       break;
-                                               }
                                                if (!zend_jit_fetch_obj_read(&dasm_state, opline, op_array,
-                                                               op1_info, ce,
+                                                               op1_info, op1_addr, ce,
                                                                zend_may_throw(opline, ssa_op, op_array, ssa))) {
                                                        goto jit_failure;
                                                }
index d0be13b10846f2352c9d49eb97d07f3c0fe557d4..576bb7badbc038b36ebc54dbb7e541837d76b20f 100644 (file)
@@ -10789,12 +10789,11 @@ static zend_bool zend_may_be_dynamic_property(zend_class_entry *ce, zend_string
        return 0;
 }
 
-static int zend_jit_fetch_obj_read(dasm_State **Dst, const zend_op *opline, const zend_op_array *op_array, uint32_t op1_info, zend_class_entry *ce, int may_throw)
+static int zend_jit_fetch_obj_read(dasm_State **Dst, const zend_op *opline, const zend_op_array *op_array, uint32_t op1_info, zend_jit_addr op1_addr, zend_class_entry *ce, int may_throw)
 {
        zval *member;
        uint32_t offset;
        zend_bool may_be_dynamic = 1;
-       zend_jit_addr op1_addr = 0, orig_op1_addr = 0;
        zend_jit_addr res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->result.var);
        zend_jit_addr this_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, offsetof(zend_execute_data, This));
        zend_jit_addr prop_addr;
@@ -10809,11 +10808,10 @@ static int zend_jit_fetch_obj_read(dasm_State **Dst, const zend_op *opline, cons
        if (opline->op1_type == IS_UNUSED) {
                |       GET_ZVAL_PTR FCARG1a, this_addr
        } else {
-               op1_addr = orig_op1_addr = OP1_ADDR();
                if (op1_info & MAY_BE_REF) {
-                       |       LOAD_ZVAL_ADDR r0, op1_addr
-                       |       ZVAL_DEREF r0, op1_info
-                       op1_addr = ZEND_ADDR_MEM_ZVAL(ZREG_R0, 0);
+                       |       LOAD_ZVAL_ADDR FCARG1a, op1_addr
+                       |       ZVAL_DEREF FCARG1a, op1_info
+                       op1_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FCARG1a, 0);
                }
                if (op1_info & ((MAY_BE_UNDEF|MAY_BE_ANY)- MAY_BE_OBJECT)) {
                        if (JIT_G(trigger) == ZEND_JIT_ON_HOT_TRACE) {
@@ -10895,14 +10893,18 @@ static int zend_jit_fetch_obj_read(dasm_State **Dst, const zend_op *opline, cons
                if (opline->opcode != ZEND_FETCH_OBJ_IS) {
                        |       SAVE_VALID_OPLINE opline, r1
                        if (op1_info & MAY_BE_UNDEF) {
+                               zend_jit_addr orig_op1_addr = OP1_ADDR();
+
                                if (op1_info & MAY_BE_ANY) {
                                        |       IF_NOT_ZVAL_TYPE op1_addr, IS_UNDEF, >1
                                }
                                |       mov FCARG1d, opline->op1.var
                                |       EXT_CALL zend_jit_undefined_op_helper, r0
                                |1:
+                               |       LOAD_ZVAL_ADDR FCARG1a, orig_op1_addr
+                       } else {
+                               |       LOAD_ZVAL_ADDR FCARG1a, op1_addr
                        }
-                       |       LOAD_ZVAL_ADDR FCARG1a, orig_op1_addr
                        |       LOAD_ADDR FCARG2a, Z_STRVAL_P(member)
                        |       EXT_CALL zend_jit_invalid_property_read, r0
                }