summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2016-01-19 15:33:08 +0300
committerDmitry Stogov <dmitry@zend.com>2016-01-19 15:33:08 +0300
commita2ff3a46a4c9b064b0866729f0a4a24fba834c1d (patch)
tree874c7a12943fea57c053c417dcb8a0c7b41e0f7b
parent29176aaa015a57f0124c152cefe325ea88ec3172 (diff)
downloadphp-git-a2ff3a46a4c9b064b0866729f0a4a24fba834c1d.tar.gz
Use ZEND_FUNC_INDIRECT_VAR_ASSESS instead of ZEND_FUNC_TOO_DYNAMIC. Handle function with exceptions handlers and generators separately.
-rw-r--r--ext/opcache/Optimizer/dfa_pass.c8
-rw-r--r--ext/opcache/Optimizer/zend_cfg.c31
-rw-r--r--ext/opcache/Optimizer/zend_dump.c3
-rw-r--r--ext/opcache/Optimizer/zend_func_info.h2
-rw-r--r--ext/opcache/Optimizer/zend_inference.c28
5 files changed, 42 insertions, 30 deletions
diff --git a/ext/opcache/Optimizer/dfa_pass.c b/ext/opcache/Optimizer/dfa_pass.c
index a1872e3d81..9dbfb7a56e 100644
--- a/ext/opcache/Optimizer/dfa_pass.c
+++ b/ext/opcache/Optimizer/dfa_pass.c
@@ -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;
}
diff --git a/ext/opcache/Optimizer/zend_cfg.c b/ext/opcache/Optimizer/zend_cfg.c
index 728d586026..8258e0e25a 100644
--- a/ext/opcache/Optimizer/zend_cfg.c
+++ b/ext/opcache/Optimizer/zend_cfg.c
@@ -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;
}
diff --git a/ext/opcache/Optimizer/zend_dump.c b/ext/opcache/Optimizer/zend_dump.c
index 53458644fc..06f4423a1b 100644
--- a/ext/opcache/Optimizer/zend_dump.c
+++ b/ext/opcache/Optimizer/zend_dump.c
@@ -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) {
diff --git a/ext/opcache/Optimizer/zend_func_info.h b/ext/opcache/Optimizer/zend_func_info.h
index 4b0aadd4ee..ee4afebf8c 100644
--- a/ext/opcache/Optimizer/zend_func_info.h
+++ b/ext/opcache/Optimizer/zend_func_info.h
@@ -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)
diff --git a/ext/opcache/Optimizer/zend_inference.c b/ext/opcache/Optimizer/zend_inference.c
index 41bd4eebb0..2ff9727254 100644
--- a/ext/opcache/Optimizer/zend_inference.c
+++ b/ext/opcache/Optimizer/zend_inference.c
@@ -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;