From: Dmitry Stogov Date: Tue, 25 Oct 2016 14:20:27 +0000 (+0300) Subject: Export zend_analyze_calls() to allow building call trees. X-Git-Tag: php-7.1.0RC5~1 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=01bc515b4d130ec8c6e9bc973ba902222d676cfa;p=php Export zend_analyze_calls() to allow building call trees. --- diff --git a/ext/opcache/Optimizer/zend_call_graph.c b/ext/opcache/Optimizer/zend_call_graph.c index 297f84b7d6..e892c35672 100644 --- a/ext/opcache/Optimizer/zend_call_graph.c +++ b/ext/opcache/Optimizer/zend_call_graph.c @@ -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; diff --git a/ext/opcache/Optimizer/zend_call_graph.h b/ext/opcache/Optimizer/zend_call_graph.h index 64eb9e8e1b..a5f47f12f0 100644 --- a/ext/opcache/Optimizer/zend_call_graph.h +++ b/ext/opcache/Optimizer/zend_call_graph.h @@ -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() diff --git a/ext/opcache/Optimizer/zend_cfg.h b/ext/opcache/Optimizer/zend_cfg.h index 1ffb62add0..4f570b7fd6 100644 --- a/ext/opcache/Optimizer/zend_cfg.h +++ b/ext/opcache/Optimizer/zend_cfg.h @@ -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) ? \ diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c index 3092b9635f..841be4aed1 100644 --- a/ext/opcache/Optimizer/zend_optimizer.c +++ b/ext/opcache/Optimizer/zend_optimizer.c @@ -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) {