]> granicus.if.org Git - php/commitdiff
Export zend_analyze_calls() to allow building call trees.
authorDmitry Stogov <dmitry@zend.com>
Tue, 25 Oct 2016 14:20:27 +0000 (17:20 +0300)
committerDmitry Stogov <dmitry@zend.com>
Tue, 25 Oct 2016 14:20:27 +0000 (17:20 +0300)
ext/opcache/Optimizer/zend_call_graph.c
ext/opcache/Optimizer/zend_call_graph.h
ext/opcache/Optimizer/zend_cfg.h
ext/opcache/Optimizer/zend_optimizer.c

index 297f84b7d65626b8a481601635715836f6e90a55..e892c3567222ba3a6072c18b6f545b8781622dae 100644 (file)
@@ -80,7 +80,7 @@ static int zend_foreach_op_array(zend_call_graph *call_graph, zend_script *scrip
        return SUCCESS;
 }
 
-static int zend_analyze_calls(zend_arena **arena, zend_script *script, uint32_t build_flags, zend_op_array *op_array, zend_func_info *func_info)
+int zend_analyze_calls(zend_arena **arena, zend_script *script, uint32_t build_flags, zend_op_array *op_array, zend_func_info *func_info)
 {
        zend_op *opline = op_array->opcodes;
        zend_op *end = opline + op_array->last;
@@ -110,11 +110,18 @@ static int zend_analyze_calls(zend_arena **arena, zend_script *script, uint32_t
                                        call_info->next_callee = func_info->callee_info;
                                        func_info->callee_info = call_info;
 
-                                       if (func->type == ZEND_INTERNAL_FUNCTION) {
+                                       if (build_flags & ZEND_CALL_TREE) {
+                                               call_info->next_caller = NULL;
+                                       } else if (func->type == ZEND_INTERNAL_FUNCTION) {
                                                call_info->next_caller = NULL;
                                        } else {
                                                zend_func_info *callee_func_info = ZEND_FUNC_INFO(&func->op_array);
-                                               call_info->next_caller = callee_func_info ? callee_func_info->caller_info : NULL;
+                                               if (callee_func_info) {
+                                                       call_info->next_caller = callee_func_info->caller_info;
+                                                       callee_func_info->caller_info = call_info;
+                                               } else {
+                                                       call_info->next_caller = NULL;
+                                               }
                                        }
                                } else {
                                        call_info = NULL;
index 64eb9e8e1baab15a5b879ebdf8d9269b34fb8ab5..a5f47f12f0eac438b7bedfb7c12ee5672c104dee 100644 (file)
@@ -69,6 +69,7 @@ typedef struct _zend_call_graph {
 BEGIN_EXTERN_C()
 
 int zend_build_call_graph(zend_arena **arena, zend_script *script, uint32_t build_flags, zend_call_graph *call_graph);
+int zend_analyze_calls(zend_arena **arena, zend_script *script, uint32_t build_flags, zend_op_array *op_array, zend_func_info *func_info);
 
 END_EXTERN_C()
 
index 1ffb62add08e154b2baf961c879a11156fef2af2..4f570b7fd6bcd91ddb3b4aeccb365d9cf65086f4 100644 (file)
@@ -101,6 +101,7 @@ typedef struct _zend_cfg {
 #define ZEND_CFG_SPLIT_AT_LIVE_RANGES  (1<<26)
 #define ZEND_CFG_NO_ENTRY_PREDECESSORS (1<<25)
 #define ZEND_CFG_RECV_ENTRY            (1<<24)
+#define ZEND_CALL_TREE                 (1<<23)
 
 #define CRT_CONSTANT_EX(op_array, node, rt_constants) \
        ((rt_constants) ? \
index 3092b9635f3a7a93ccb68c2d94e6bb9b3962d21a..841be4aed1f9d460b8b29684b502fee20d4d0ab3 100644 (file)
@@ -546,11 +546,16 @@ zend_function *zend_optimizer_get_called_func(
                {
                        zend_string *function_name = Z_STR_P(GET_OP(op2));
                        zend_function *func;
-                       if ((func = zend_hash_find_ptr(&script->function_table, function_name)) != NULL) {
+                       if (script && (func = zend_hash_find_ptr(&script->function_table, function_name)) != NULL) {
                                return func;
                        } else if ((func = zend_hash_find_ptr(EG(function_table), function_name)) != NULL) {
-                               ZEND_ASSERT(func->type == ZEND_INTERNAL_FUNCTION);
-                               return func;
+                               if (func->type == ZEND_INTERNAL_FUNCTION) {
+                                       return func;
+                               } else if (func->type == ZEND_USER_FUNCTION &&
+                                          func->op_array.filename &&
+                                          func->op_array.filename == op_array->filename) {
+                                       return func;
+                               }
                        }
                        break;
                }
@@ -558,7 +563,18 @@ zend_function *zend_optimizer_get_called_func(
                case ZEND_INIT_NS_FCALL_BY_NAME:
                        if (opline->op2_type == IS_CONST && Z_TYPE_P(GET_OP(op2)) == IS_STRING) {
                                zval *function_name = GET_OP(op2) + 1;
-                               return zend_hash_find_ptr(&script->function_table, Z_STR_P(function_name));
+                               zend_function *func;
+                               if (script && (func = zend_hash_find_ptr(&script->function_table, Z_STR_P(function_name)))) {
+                                       return func;
+                               } else if ((func = zend_hash_find_ptr(EG(function_table), function_name)) != NULL) {
+                                       if (func->type == ZEND_INTERNAL_FUNCTION) {
+                                               return func;
+                                       } else if (func->type == ZEND_USER_FUNCTION &&
+                                                  func->op_array.filename &&
+                                                  func->op_array.filename == op_array->filename) {
+                                               return func;
+                                       }
+                               }
                        }
                        break;
                case ZEND_INIT_STATIC_METHOD_CALL:
@@ -566,7 +582,17 @@ zend_function *zend_optimizer_get_called_func(
                                zend_class_entry *ce = NULL;
                                if (opline->op1_type == IS_CONST && Z_TYPE_P(GET_OP(op1)) == IS_STRING) {
                                        zend_string *class_name = Z_STR_P(GET_OP(op1) + 1);
-                                       ce = zend_hash_find_ptr(&script->class_table, class_name);
+                                       if (script && (ce = zend_hash_find_ptr(&script->class_table, class_name))) {
+                                               /* pass */
+                                       } else if ((ce = zend_hash_find_ptr(EG(class_table), class_name))) {
+                                               if (ce->type == ZEND_INTERNAL_CLASS) {
+                                                       /* pass */
+                                               } else if (ce->type != ZEND_USER_CLASS ||
+                                                          !ce->info.user.filename ||
+                                                          ce->info.user.filename != op_array->filename) {
+                                                       ce = NULL;
+                                               }
+                                       }
                                } else if (opline->op1_type == IS_UNUSED && op_array->scope
                                                && !(op_array->scope->ce_flags & ZEND_ACC_TRAIT)
                                                && (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {