com php-src: Export zend_analyze_calls() to allow building call trees.: ext/opcache/Optimizer/zend _call_graph.c
ext/opcache/Optimizer/zend_call_graph .h ext/opcache/Optimizer/zend_cfg.h ext/opcache/Optim izer/zend_optimizer.c
| From: | Dmitry Stogov | Date: | Tue, 25 Oct 2016 14:20:27 +0000 |
| Subject: | com php-src: Export zend_analyze_calls() to allow building call trees.: ext/opcache/Optimizer/zend _call_graph.c ext/opcache/Optimizer/zend_call_graph .h ext/opcache/Optimizer/zend_cfg.h ext/opcache/Optim izer/zend_optimizer.c |
||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-95280@lists.php.net to get a copy of this message | ||
Commit: 01bc515b4d130ec8c6e9bc973ba902222d676cfa
Author: Dmitry Stogov <dmitry@zend.com> Tue, 25 Oct 2016 17:20:27 +0300
Parents: c30e5a32c1a68f62a2356eb52965551252f8131c
Branches: PHP-7.1 master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=01bc515b4d130ec8c6e9bc973ba902222d676cfa
Log:
Export zend_analyze_calls() to allow building call trees.
Changed paths:
M ext/opcache/Optimizer/zend_call_graph.c
M ext/opcache/Optimizer/zend_call_graph.h
M ext/opcache/Optimizer/zend_cfg.h
M ext/opcache/Optimizer/zend_optimizer.c
Diff:
diff --git a/ext/opcache/Optimizer/zend_call_graph.c b/ext/opcache/Optimizer/zend_call_graph.c
index 297f84b..e892c35 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 64eb9e8..a5f47f1 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 1ffb62a..4f570b7 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 3092b96...841be4a 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) {