]> granicus.if.org Git - php/commitdiff
Use information about recorded classes for speculative FETCH_OBJ optimization
authorDmitry Stogov <dmitry@zend.com>
Wed, 8 Jul 2020 11:09:28 +0000 (14:09 +0300)
committerDmitry Stogov <dmitry@zend.com>
Wed, 8 Jul 2020 11:09:28 +0000 (14:09 +0300)
ext/opcache/Optimizer/zend_inference.h
ext/opcache/jit/zend_jit.c
ext/opcache/jit/zend_jit_trace.c
ext/opcache/jit/zend_jit_x86.dasc

index 98a647f43ad64c1fa2f6e90916ab12702d5b0298..0708d5df94516e39c83c2df7653778e56f56ee79 100644 (file)
@@ -26,6 +26,7 @@
 /* Bitmask for type inference (zend_ssa_var_info.type) */
 #include "zend_type_info.h"
 
+#define MAY_BE_CLASS_GUARD          (1<<27) /* needs class guard */
 #define MAY_BE_GUARD                (1<<28) /* needs type guard */
 #define MAY_BE_IN_REG               (1<<29) /* value allocated in CPU register */
 
index 3b7c9e1ec46824f3e0fed27851c373a1d247b1d9..debf4df866a6c57784990827b17c6f4c1957aad7 100644 (file)
@@ -2790,8 +2790,8 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
                                                                }
                                                        }
                                                }
-                                               if (!zend_jit_fetch_obj(&dasm_state, opline, op_array,
-                                                               op1_info, op1_addr, 0, ce, ce_is_instanceof, 0,
+                                               if (!zend_jit_fetch_obj(&dasm_state, opline, op_array, ssa, ssa_op,
+                                                               op1_info, op1_addr, 0, ce, ce_is_instanceof, 0, NULL,
                                                                zend_may_throw(opline, ssa_op, op_array, ssa))) {
                                                        goto jit_failure;
                                                }
index e207aa35d13fc7b12611f52d97331a2648150794..ca8c72ff3fde91a12e3f4dcb60a993550159b0f4 100644 (file)
@@ -2921,6 +2921,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
                        uint8_t op3_type = p->op3_type;
                        uint8_t orig_op1_type = op1_type;
                        zend_bool op1_indirect;
+                       zend_class_entry *op1_ce = NULL;
 
                        opline = p->opline;
                        if (op1_type & (IS_TRACE_REFERENCE|IS_TRACE_INDIRECT)) {
@@ -2934,7 +2935,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
                        }
 
                        if ((p+1)->op == ZEND_JIT_TRACE_OP1_TYPE) {
-                               // TODO: support for recorded classes ???
+                               op1_ce = (zend_class_entry*)(p+1)->ce;
                                p++;
                        }
                        if ((p+1)->op == ZEND_JIT_TRACE_OP2_TYPE) {
@@ -3837,9 +3838,9 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
                                                                delayed_fetch_this = ssa->var_info[ssa_op->op1_use].delayed_fetch_this;
                                                        }
                                                }
-                                               if (!zend_jit_fetch_obj(&dasm_state, opline, op_array,
+                                               if (!zend_jit_fetch_obj(&dasm_state, opline, op_array, ssa, ssa_op,
                                                                op1_info, op1_addr, op1_indirect, ce, ce_is_instanceof,
-                                                               delayed_fetch_this,
+                                                               delayed_fetch_this, op1_ce,
                                                                zend_may_throw_ex(opline, ssa_op, op_array, ssa, op1_info, MAY_BE_STRING))) {
                                                        goto jit_failure;
                                                }
index 04573476d257c9dd3be00c264610973fe1c7c81d..12dccc00ff6935e79a337374748031dd9a7db491 100644 (file)
@@ -10898,7 +10898,31 @@ static zend_bool zend_may_be_dynamic_property(zend_class_entry *ce, zend_string
        return 0;
 }
 
-static int zend_jit_fetch_obj(dasm_State **Dst, const zend_op *opline, const zend_op_array *op_array, uint32_t op1_info, zend_jit_addr op1_addr, zend_bool op1_indirect, zend_class_entry *ce, zend_bool ce_is_instanceof, zend_bool use_this, int may_throw)
+static int zend_jit_class_guard(dasm_State **Dst, const zend_op *opline, zend_class_entry *ce)
+{
+       int32_t exit_point = zend_jit_trace_get_exit_point(opline, opline, NULL, 0);
+       const void *exit_addr = zend_jit_trace_get_exit_addr(exit_point);
+
+       if (!exit_addr) {
+               return 0;
+       }
+
+       |.if X64
+       ||      if (!IS_SIGNED_32BIT(ce)) {
+       |               mov64 r0, ((ptrdiff_t)ce)
+       |               cmp aword [FCARG1a + offsetof(zend_object, ce)], r0
+       ||      } else {
+       |               cmp aword [FCARG1a + offsetof(zend_object, ce)], ce
+       ||      }
+       |.else
+       |       cmp aword [FCARG1a + offsetof(zend_object, ce)], ce
+       |.endif
+       |       jne &exit_addr
+
+       return 1;
+}
+
+static int zend_jit_fetch_obj(dasm_State **Dst, const zend_op *opline, const zend_op_array *op_array, zend_ssa *ssa, const zend_ssa_op *ssa_op, uint32_t op1_info, zend_jit_addr op1_addr, zend_bool op1_indirect, zend_class_entry *ce, zend_bool ce_is_instanceof, zend_bool use_this, zend_class_entry *trace_ce, int may_throw)
 {
        zval *member;
        zend_property_info *prop_info;
@@ -10950,6 +10974,20 @@ static int zend_jit_fetch_obj(dasm_State **Dst, const zend_op *opline, const zen
                |       GET_ZVAL_PTR FCARG1a, op1_addr
        }
 
+       if (!prop_info && trace_ce && (trace_ce->ce_flags & ZEND_ACC_IMMUTABLE)) {
+               prop_info = zend_get_known_property_info(trace_ce, Z_STR_P(member), opline->op1_type == IS_UNUSED, op_array->filename);
+               if (prop_info) {
+                       if (!(op1_info & MAY_BE_CLASS_GUARD)) {
+                               if (!zend_jit_class_guard(Dst, opline, trace_ce)) {
+                                       return 0;
+                               }
+                               if (ssa->var_info && ssa_op->op1_use >= 0) {
+                                       ssa->var_info[ssa_op->op1_use].type |= MAY_BE_CLASS_GUARD;
+                               }
+                       }
+               }
+       }
+
        if (!prop_info) {
                |       mov r0, EX->run_time_cache
                |       mov r2, aword [r0 + (opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS)]