]> granicus.if.org Git - php/commitdiff
Use ZEND_FUNC_INDIRECT_VAR_ASSESS instead of ZEND_FUNC_TOO_DYNAMIC. Handle function...
authorDmitry Stogov <dmitry@zend.com>
Tue, 19 Jan 2016 12:33:08 +0000 (15:33 +0300)
committerDmitry Stogov <dmitry@zend.com>
Tue, 19 Jan 2016 12:33:08 +0000 (15:33 +0300)
ext/opcache/Optimizer/dfa_pass.c
ext/opcache/Optimizer/zend_cfg.c
ext/opcache/Optimizer/zend_dump.c
ext/opcache/Optimizer/zend_func_info.h
ext/opcache/Optimizer/zend_inference.c

index a1872e3d8147390046af26ace32339f31b332af6..9dbfb7a56eb058a93c4acaf59468134796b2dd9e 100644 (file)
@@ -34,6 +34,11 @@ int zend_dfa_analyze_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx,
 {
        uint32_t build_flags;
 
+       if (op_array->last_try_catch) {
+               /* TODO: we can't analyze functions with try/catch/finally ??? */
+               return FAILURE;
+       }
+
     /* Build SSA */
        memset(ssa, 0, sizeof(zend_ssa));
 
@@ -41,7 +46,8 @@ int zend_dfa_analyze_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx,
                return FAILURE;
        }
 
-       if (*flags & ZEND_FUNC_TOO_DYNAMIC) {
+       if (*flags & ZEND_FUNC_INDIRECT_VAR_ASSESS) {
+               /* TODO: we can't analyze functions with indirect variable access ??? */
                return FAILURE;
        }
 
index 728d58602667a81cae18de004ded76092bc0d246..8258e0e25a53c3b8c7dd1c581581ce3c3aed93a5 100644 (file)
@@ -251,10 +251,6 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
 
        /* Build CFG, Step 1: Find basic blocks starts, calculate number of blocks */
        BB_START(0);
-       if ((op_array->fn_flags & ZEND_ACC_CLOSURE) && op_array->static_variables) {
-               // FIXME: Really we should try to perform variable initialization
-               flags |= ZEND_FUNC_TOO_DYNAMIC;
-       }
        for (i = 0; i < op_array->last; i++) {
                zend_op *opline = op_array->opcodes + i;
                switch(opline->opcode) {
@@ -268,9 +264,9 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
                                }
                                break;
                        case ZEND_INCLUDE_OR_EVAL:
+                               flags |= ZEND_FUNC_INDIRECT_VAR_ASSESS;
                        case ZEND_YIELD:
                        case ZEND_YIELD_FROM:
-                               flags |= ZEND_FUNC_TOO_DYNAMIC;
                                if (build_flags & ZEND_CFG_STACKLESS) {
                                        BB_START(i + 1);
                                }
@@ -296,15 +292,17 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
                                if ((fn = zend_hash_find_ptr(EG(function_table), Z_STR_P(zv))) != NULL) {
                                        if (fn->type == ZEND_INTERNAL_FUNCTION) {
                                                if (zend_string_equals_literal(Z_STR_P(zv), "extract")) {
-                                                       flags |= ZEND_FUNC_TOO_DYNAMIC;
+                                                       flags |= ZEND_FUNC_INDIRECT_VAR_ASSESS;
                                                } else if (zend_string_equals_literal(Z_STR_P(zv), "compact")) {
-                                                       flags |= ZEND_FUNC_TOO_DYNAMIC;
-                                               } else if (zend_string_equals_literal(Z_STR_P(zv), "parse_str")) {
-                                                       flags |= ZEND_FUNC_TOO_DYNAMIC;
-                                               } else if (zend_string_equals_literal(Z_STR_P(zv), "mb_parse_str")) {
-                                                       flags |= ZEND_FUNC_TOO_DYNAMIC;
+                                                       flags |= ZEND_FUNC_INDIRECT_VAR_ASSESS;
+                                               } else if (zend_string_equals_literal(Z_STR_P(zv), "parse_str") &&
+                                                          opline->extended_value == 1) {
+                                                       flags |= ZEND_FUNC_INDIRECT_VAR_ASSESS;
+                                               } else if (zend_string_equals_literal(Z_STR_P(zv), "mb_parse_str") &&
+                                                          opline->extended_value == 1) {
+                                                       flags |= ZEND_FUNC_INDIRECT_VAR_ASSESS;
                                                } else if (zend_string_equals_literal(Z_STR_P(zv), "get_defined_vars")) {
-                                                       flags |= ZEND_FUNC_TOO_DYNAMIC;
+                                                       flags |= ZEND_FUNC_INDIRECT_VAR_ASSESS;
                                                } else if (zend_string_equals_literal(Z_STR_P(zv), "func_num_args")) {
                                                        flags |= ZEND_FUNC_VARARG;
                                                } else if (zend_string_equals_literal(Z_STR_P(zv), "func_get_arg")) {
@@ -316,12 +314,10 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
                                }
                                break;
                        case ZEND_FAST_CALL:
-                               flags |= ZEND_FUNC_TOO_DYNAMIC;
                                BB_START(OP_JMP_ADDR(opline, opline->op1) - op_array->opcodes);
                                BB_START(i + 1);
                                break;
                        case ZEND_FAST_RET:
-                               flags |= ZEND_FUNC_TOO_DYNAMIC;
                                if (i + 1 < op_array->last) {
                                        BB_START(i + 1);
                                }
@@ -350,7 +346,6 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
                                BB_START(i + 1);
                                break;
                        case ZEND_CATCH:
-                               flags |= ZEND_FUNC_TOO_DYNAMIC;
                                if (!opline->result.num) {
                                        BB_START(ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value));
                                }
@@ -371,7 +366,7 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
                                break;
                        case ZEND_UNSET_VAR:
                                if (!(opline->extended_value & ZEND_QUICK_SET)) {
-                                       flags |= ZEND_FUNC_TOO_DYNAMIC;
+                                       flags |= ZEND_FUNC_INDIRECT_VAR_ASSESS;
                                }
                                break;
                        case ZEND_FETCH_R:
@@ -381,11 +376,11 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
                        case ZEND_FETCH_IS:
                        case ZEND_FETCH_UNSET:
                                if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_LOCAL) {
-                                       flags |= ZEND_FUNC_TOO_DYNAMIC;
+                                       flags |= ZEND_FUNC_INDIRECT_VAR_ASSESS;
                                } else if (((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_GLOBAL ||
                                            (opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_GLOBAL_LOCK) &&
                                           !op_array->function_name) {
-                                       flags |= ZEND_FUNC_TOO_DYNAMIC;
+                                       flags |= ZEND_FUNC_INDIRECT_VAR_ASSESS;
                                }
                                break;
                }
index 53458644fc70d94d2c5d4719ccd1e95460871171..06f4423a1be6c02f4bc7fa67b99030423dbe3915 100644 (file)
@@ -853,6 +853,9 @@ void zend_dump_op_array(const zend_op_array *op_array, uint32_t dump_flags, cons
        if (ssa) {
                fprintf(stderr, ", ssa_vars=%d", ssa->vars_count);
        }
+       if (func_flags & ZEND_FUNC_INDIRECT_VAR_ASSESS) {
+               fprintf(stderr, ", dynamic");
+       }
        if (func_flags & ZEND_FUNC_RECURSIVE) {
                fprintf(stderr, ", recursive");
                if (func_flags & ZEND_FUNC_RECURSIVE_DIRECTLY) {
index 4b0aadd4ee3b45859af2b445ceec33e6327dd701..ee4afebf8cf93b4386c581df82a34314074096a7 100644 (file)
@@ -22,7 +22,7 @@
 #include "zend_ssa.h"
 
 /* func flags */
-#define ZEND_FUNC_TOO_DYNAMIC              (1<<0)
+#define ZEND_FUNC_INDIRECT_VAR_ASSESS      (1<<0)
 #define ZEND_FUNC_HAS_CALLS                (1<<1)
 #define ZEND_FUNC_VARARG                   (1<<2)
 #define ZEND_FUNC_NO_LOOPS                 (1<<3)
index 41bd4eebb052097db245194ec8bdee245b7453b8..2ff97272546e57261059b12846f38c125dd2256d 100644 (file)
@@ -3067,8 +3067,11 @@ static void zend_update_type_info(const zend_op_array *op_array,
                        }
                        break;
                case ZEND_BIND_GLOBAL:
+                       tmp = (MAY_BE_REF | MAY_BE_ANY);
+                       UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
+                       break;
                case ZEND_BIND_STATIC:
-                       tmp = (MAY_BE_REF | MAY_BE_ANY );
+                       tmp = MAY_BE_ANY | (opline->extended_value ? MAY_BE_REF : (MAY_BE_RC1 | MAY_BE_RCN));
                        UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def);
                        break;
                case ZEND_SEND_VAR:
@@ -4071,17 +4074,22 @@ int zend_ssa_inference(zend_arena **arena, const zend_op_array *op_array, const
        }
        ssa_var_info = ssa->var_info;
 
-       for (i = 0; i < op_array->last_var; i++) {
-               if (!op_array->function_name) {
+       if (!op_array->function_name) {
+               for (i = 0; i < op_array->last_var; i++) {
                        ssa_var_info[i].type = MAY_BE_UNDEF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | MAY_BE_ANY  | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
-               } else if (i == EX_VAR_TO_NUM(op_array->this_var)) {
-                       ssa_var_info[i].type = MAY_BE_UNDEF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_OBJECT;
-                       ssa_var_info[i].ce = op_array->scope;
-                       ssa_var_info[i].is_instanceof = 1;
-               } else {
-                       ssa_var_info[i].type = MAY_BE_UNDEF | MAY_BE_RCN;
+                       ssa_var_info[i].has_range = 0;
+               }
+       } else {
+               for (i = 0; i < op_array->last_var; i++) {
+                       if (i == EX_VAR_TO_NUM(op_array->this_var)) {
+                               ssa_var_info[i].type = MAY_BE_UNDEF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_OBJECT;
+                               ssa_var_info[i].ce = op_array->scope;
+                               ssa_var_info[i].is_instanceof = 1;
+                       } else {
+                               ssa_var_info[i].type = MAY_BE_UNDEF | MAY_BE_RCN;
+                       }
+                       ssa_var_info[i].has_range = 0;
                }
-               ssa_var_info[i].has_range = 0;
        }
        for (i = op_array->last_var; i < ssa->vars_count; i++) {
                ssa_var_info[i].type = 0;