]> granicus.if.org Git - php/commitdiff
Tracing JIT support for PHP references in ASSIGN instruction
authorDmitry Stogov <dmitry@zend.com>
Wed, 17 Jun 2020 09:24:51 +0000 (12:24 +0300)
committerDmitry Stogov <dmitry@zend.com>
Wed, 17 Jun 2020 09:24:51 +0000 (12:24 +0300)
ext/opcache/jit/zend_jit_trace.c
ext/opcache/jit/zend_jit_x86.dasc

index a39486a2896bbb0e9b86d83ae8e88307f227590a..33e0cd714ca41a305314953b35daa702a1b293aa 100644 (file)
@@ -3156,7 +3156,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
                                                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)) {
+                                                       if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr, 1)) {
                                                                goto jit_failure;
                                                        }
                                                } else {
@@ -3182,7 +3182,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
                                                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)) {
+                                                       if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr, 1)) {
                                                                goto jit_failure;
                                                        }
                                                } else {
@@ -3221,10 +3221,28 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
                                                CHECK_OP2_TRACE_TYPE();
                                                op1_info = OP1_INFO();
                                                op1_def_info = OP1_DEF_INFO();
-                                               USE_OP1_TRACE_TYPE();
+                                               op1_addr = OP1_REG_ADDR();
+                                               op1_def_addr = OP1_DEF_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, 0)) {
+                                                               goto jit_failure;
+                                                       }
+                                                       op1_def_addr = op1_addr;
+                                               } else {
+                                                       USE_OP1_TRACE_TYPE();
+                                                       if (orig_op1_type != IS_UNKNOWN
+                                                        && (op1_info & MAY_BE_REF)) {
+                                                               if (!zend_jit_noref_guard(&dasm_state, opline, op1_addr)) {
+                                                                       goto jit_failure;
+                                                               }
+                                                               op1_info &= ~MAY_BE_REF;
+                                                               op1_def_info &= ~MAY_BE_REF;
+                                                       }
+                                               }
                                                if (!zend_jit_assign(&dasm_state, opline, op_array,
-                                                               op1_info, OP1_REG_ADDR(),
-                                                               op1_def_info, OP1_DEF_REG_ADDR(),
+                                                               op1_info, op1_addr,
+                                                               op1_def_info, op1_def_addr,
                                                                op2_info, op2_addr, op2_def_addr,
                                                                res_info, res_addr,
                                                                zend_may_throw(opline, ssa_op, op_array, ssa))) {
@@ -3616,7 +3634,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
                                                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)) {
+                                                       if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr, 1)) {
                                                                goto jit_failure;
                                                        }
                                                } else {
@@ -3649,7 +3667,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
                                                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)) {
+                                                       if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr, 1)) {
                                                                goto jit_failure;
                                                        }
                                                } else {
index 5e3e88e920646f3afa143aa51422e28034b2c8f2..6c7eb925638718158238049f20da20f9872c9feb 100644 (file)
@@ -11350,7 +11350,20 @@ static zend_bool zend_jit_verify_return_type(dasm_State **Dst, const zend_op *op
        return 1;
 }
 
-static zend_bool zend_jit_fetch_reference(dasm_State **Dst, const zend_op *opline, uint8_t var_type, uint32_t *var_info_ptr, zend_jit_addr *var_addr_ptr)
+static zend_bool zend_jit_noref_guard(dasm_State **Dst, const zend_op *opline, zend_jit_addr var_addr)
+{
+       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_ZVAL_TYPE var_addr, IS_REFERENCE, &exit_addr
+
+       return 1;
+}
+
+static zend_bool zend_jit_fetch_reference(dasm_State **Dst, const zend_op *opline, uint8_t var_type, uint32_t *var_info_ptr, zend_jit_addr *var_addr_ptr, zend_bool add_type_guard)
 {
        zend_jit_addr var_addr = *var_addr_ptr;
        uint32_t var_info = *var_info_ptr;
@@ -11369,7 +11382,8 @@ static zend_bool zend_jit_fetch_reference(dasm_State **Dst, const zend_op *oplin
        *var_addr_ptr = var_addr;
 
        var_type &= ~IS_TRACE_REFERENCE;
-       if (var_type != IS_UNKNOWN
+       if (add_type_guard
+        && var_type != IS_UNKNOWN
         && (var_info & (MAY_BE_ANY|MAY_BE_UNDEF)) != (1 << var_type)) {
                |       IF_NOT_Z_TYPE FCARG1a, var_type, &exit_addr
 
@@ -11382,6 +11396,9 @@ static zend_bool zend_jit_fetch_reference(dasm_State **Dst, const zend_op *oplin
                        var_info = MAY_BE_ARRAY | (var_info & (MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF|MAY_BE_ARRAY_KEY_ANY|MAY_BE_RC1|MAY_BE_RCN));
                }
 
+               *var_info_ptr = var_info;
+       } else {
+               var_info &= ~MAY_BE_REF;
                *var_info_ptr = var_info;
        }