]> granicus.if.org Git - php/commitdiff
More accurate reference-counter inference (with support for ext/intl/tests/bug72241...
authorDmitry Stogov <dmitry@zend.com>
Tue, 7 Jul 2020 16:11:27 +0000 (19:11 +0300)
committerDmitry Stogov <dmitry@zend.com>
Tue, 7 Jul 2020 16:11:27 +0000 (19:11 +0300)
ext/opcache/Optimizer/zend_inference.c
ext/opcache/Optimizer/zend_inference.h
ext/opcache/jit/zend_jit_x86.dasc

index d45b58d6d7f63226632ab370bc0730e2e743d731..c4189975d59948a8666ce538a76c8f82b5c138b8 100644 (file)
@@ -1952,7 +1952,7 @@ static void emit_type_narrowing_warning(const zend_op_array *op_array, zend_ssa
        zend_error(E_WARNING, "Narrowing occurred during type inference of %s. Please file a bug report on bugs.php.net", def_op_name);
 }
 
-uint32_t zend_array_element_type(uint32_t t1, int write, int insert)
+uint32_t zend_array_element_type(uint32_t t1, zend_uchar op_type, int write, int insert)
 {
        uint32_t tmp = 0;
 
@@ -1972,15 +1972,18 @@ uint32_t zend_array_element_type(uint32_t t1, int write, int insert)
                        if (tmp & MAY_BE_ARRAY) {
                                tmp |= MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
                        }
-                       if (t1 & MAY_BE_ARRAY_OF_REF) {
+                       if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
                                if (!write) {
                                        /* can't be REF  because of ZVAL_COPY_DEREF() usage */
-                                       tmp |= MAY_BE_RC1 | MAY_BE_RCN;
-                               } else {
+                                       tmp |= MAY_BE_RCN;
+                                       if ((op_type & (IS_VAR|IS_TMP_VAR)) && (t1 & MAY_BE_RC1)) {
+                                               tmp |= MAY_BE_RC1;
+                                       }
+                               } else if (t1 & MAY_BE_ARRAY_OF_REF) {
                                        tmp |= MAY_BE_REF | MAY_BE_RC1 | MAY_BE_RCN;
+                               } else {
+                                       tmp |= MAY_BE_RC1 | MAY_BE_RCN;
                                }
-                       } else if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
-                               tmp |= MAY_BE_RC1 | MAY_BE_RCN;
                        }
                }
                if (write) {
@@ -2513,7 +2516,7 @@ static zend_always_inline int _zend_update_type_info(
                                tmp |= MAY_BE_REF;
                                }
                                orig = t1;
-                               t1 = zend_array_element_type(t1, 1, 0);
+                               t1 = zend_array_element_type(t1, opline->op1_type, 1, 0);
                                t2 = OP1_DATA_INFO();
                        } else if (opline->opcode == ZEND_ASSIGN_STATIC_PROP_OP) {
                                prop_info = zend_fetch_static_prop_info(script, op_array, ssa, opline);
@@ -3380,6 +3383,7 @@ static zend_always_inline int _zend_update_type_info(
                        /* FETCH_LIST on a string behaves like FETCH_R on null */
                        tmp = zend_array_element_type(
                                opline->opcode != ZEND_FETCH_LIST_R ? t1 : ((t1 & ~MAY_BE_STRING) | MAY_BE_NULL),
+                               opline->op1_type,
                                opline->result_type == IS_VAR,
                                opline->op2_type == IS_UNUSED);
                        if (opline->opcode == ZEND_FETCH_DIM_IS && (t1 & MAY_BE_STRING)) {
index 78a9cdcbb504caad9a93bf02b742c1e0c13ab6e3..98a647f43ad64c1fa2f6e90916ab12702d5b0298 100644 (file)
@@ -249,7 +249,7 @@ int zend_ssa_find_false_dependencies(const zend_op_array *op_array, zend_ssa *ss
 int zend_ssa_find_sccs(const zend_op_array *op_array, zend_ssa *ssa);
 int zend_ssa_inference(zend_arena **raena, const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa, zend_long optimization_level);
 
-uint32_t zend_array_element_type(uint32_t t1, int write, int insert);
+uint32_t zend_array_element_type(uint32_t t1, zend_uchar op_type, int write, int insert);
 
 int  zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int var, int widening, int narrowing, zend_ssa_range *tmp);
 void zend_inference_init_range(const zend_op_array *op_array, zend_ssa *ssa, int var, zend_bool underflow, zend_long min, zend_long max, zend_bool overflow);
index c186a7ee8fc8d266a7e6fb48e344dbf6c9b725c1..af368defd28b80833733750ec058b419e8a94ff4 100644 (file)
@@ -5558,7 +5558,7 @@ static int zend_jit_assign_dim(dasm_State **Dst, const zend_op *opline, const ze
                                return 0;
                        }
                } else {
-                       uint32_t var_info = zend_array_element_type(op1_info, 0, 0);
+                       uint32_t var_info = zend_array_element_type(op1_info, opline->op1_type, 0, 0);
                        zend_jit_addr var_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FCARG1a, 0);
 
                        if (!zend_jit_fetch_dimension_address_inner(Dst, opline, BP_VAR_W, op1_info, op2_info, 8, 8, NULL, NULL)) {
@@ -5571,6 +5571,9 @@ static int zend_jit_assign_dim(dasm_State **Dst, const zend_op *opline, const ze
                        if (op1_info & (MAY_BE_ARRAY_OF_REF|MAY_BE_OBJECT)) {
                                var_info |= MAY_BE_REF;
                        }
+                       if (var_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
+                               var_info |= MAY_BE_RC1;
+                       }
                        |       // value = zend_assign_to_variable(variable_ptr, value, OP_DATA_TYPE);
                        if (!zend_jit_assign_to_variable(Dst, opline, op_array, var_addr, var_info, -1, (opline+1)->op1_type, (opline+1)->op1, op3_addr, val_info, res_addr, 0)) {
                                return 0;
@@ -5756,7 +5759,7 @@ static int zend_jit_assign_dim_op(dasm_State **Dst, const zend_op *opline, const
 
        if (op1_info & (MAY_BE_UNDEF|MAY_BE_NULL|MAY_BE_FALSE|MAY_BE_ARRAY)) {
                uint32_t var_info;
-               uint32_t var_def_info = zend_array_element_type(op1_def_info, 1, 0);
+               uint32_t var_def_info = zend_array_element_type(op1_def_info, opline->op1_type, 1, 0);
 
                |6:
                if (opline->op2_type == IS_UNUSED) {
@@ -5777,10 +5780,13 @@ static int zend_jit_assign_dim_op(dasm_State **Dst, const zend_op *opline, const
                        |.code
                        |       mov FCARG1a, r0
                } else {
-                       var_info = zend_array_element_type(op1_info, 0, 0);
+                       var_info = zend_array_element_type(op1_info, opline->op1_type, 0, 0);
                        if (op1_info & (MAY_BE_ARRAY_OF_REF|MAY_BE_OBJECT)) {
                                var_info |= MAY_BE_REF;
                        }
+                       if (var_info & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE)) {
+                               var_info |= MAY_BE_RC1;
+                       }
 
                        if (!zend_jit_fetch_dimension_address_inner(Dst, opline, BP_VAR_RW, op1_info, op2_info, 8, 8, NULL, NULL)) {
                                return 0;
@@ -11132,7 +11138,8 @@ static int zend_jit_fetch_obj(dasm_State **Dst, const zend_op *opline, const zen
        |9: // END
        if (opline->op1_type != IS_UNUSED && !use_this && !op1_indirect) {
                if (opline->op1_type == IS_VAR
-                && opline->opcode == ZEND_FETCH_OBJ_W) {
+                && opline->opcode == ZEND_FETCH_OBJ_W
+                && (op1_info & MAY_BE_RC1)) {
                        zend_jit_addr orig_op1_addr = OP1_ADDR();
 
                        |       IF_NOT_ZVAL_REFCOUNTED orig_op1_addr, >1