From: Dmitry Stogov Date: Wed, 5 Jul 2017 16:15:16 +0000 (+0300) Subject: Keep information about SSA variables, that may be modified indirectly. X-Git-Tag: php-7.2.0beta1~142 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=acffb7a080eec216ec41212921d8d436ed121863;p=php Keep information about SSA variables, that may be modified indirectly. --- diff --git a/ext/opcache/Optimizer/zend_cfg.c b/ext/opcache/Optimizer/zend_cfg.c index 7cc02b6560..6ae5880c8f 100644 --- a/ext/opcache/Optimizer/zend_cfg.c +++ b/ext/opcache/Optimizer/zend_cfg.c @@ -598,6 +598,8 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b /* Build CFG, Step 4, Mark Reachable Basic Blocks */ zend_mark_reachable_blocks(op_array, cfg, 0); + cfg->dynamic = (flags & ZEND_FUNC_INDIRECT_VAR_ACCESS); + if (func_flags) { *func_flags |= flags; } diff --git a/ext/opcache/Optimizer/zend_cfg.h b/ext/opcache/Optimizer/zend_cfg.h index 315b93ef3a..ccff7d4425 100644 --- a/ext/opcache/Optimizer/zend_cfg.h +++ b/ext/opcache/Optimizer/zend_cfg.h @@ -92,6 +92,7 @@ typedef struct _zend_cfg { unsigned int split_at_live_ranges : 1; unsigned int split_at_calls : 1; unsigned int split_at_recv : 1; + unsigned int dynamic : 1; /* accesses varables by name */ } zend_cfg; /* Build Flags */ diff --git a/ext/opcache/Optimizer/zend_inference.c b/ext/opcache/Optimizer/zend_inference.c index 7f1e791705..5234bc8ef6 100644 --- a/ext/opcache/Optimizer/zend_inference.c +++ b/ext/opcache/Optimizer/zend_inference.c @@ -3835,21 +3835,14 @@ static int zend_infer_types(const zend_op_array *op_array, const zend_script *sc /* Narrowing integer initialization to doubles */ zend_type_narrowing(op_array, script, ssa); - for (j = 0; j < op_array->last_var; j++) { - /* $php_errormsg and $http_response_header may be updated indirectly */ - if (zend_string_equals_literal(op_array->vars[j], "php_errormsg")) { - int i; - for (i = 0; i < ssa_vars_count; i++) { - if (ssa->vars[i].var == j) { - ssa_var_info[i].type |= MAY_BE_STRING | MAY_BE_RC1 | MAY_BE_RCN; - } - } - } else if (zend_string_equals_literal(op_array->vars[j], "http_response_header")) { - int i; - for (i = 0; i < ssa_vars_count; i++) { - if (ssa->vars[i].var == j) { - ssa_var_info[i].type |= MAY_BE_ARRAY | MAY_BE_ARRAY_KEY_LONG | MAY_BE_ARRAY_OF_STRING | MAY_BE_RC1 | MAY_BE_RCN; - } + for (j = 0; j < ssa_vars_count; j++) { + if (ssa->vars[j].alias) { + if (ssa->vars[j].alias == PHP_ERRORMSG_ALIAS) { + ssa_var_info[j].type |= MAY_BE_STRING | MAY_BE_RC1 | MAY_BE_RCN; + } else if (ssa->vars[j].alias == PHP_ERRORMSG_ALIAS) { + ssa_var_info[j].type |= MAY_BE_ARRAY | MAY_BE_ARRAY_KEY_LONG | MAY_BE_ARRAY_OF_STRING | MAY_BE_RC1 | MAY_BE_RCN; + } else { + ssa_var_info[j].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; } } } diff --git a/ext/opcache/Optimizer/zend_ssa.c b/ext/opcache/Optimizer/zend_ssa.c index 54bf985d40..927ebb096c 100644 --- a/ext/opcache/Optimizer/zend_ssa.c +++ b/ext/opcache/Optimizer/zend_ssa.c @@ -1100,6 +1100,22 @@ int zend_ssa_compute_use_def_chains(zend_arena **arena, const zend_op_array *op_ } } + /* Mark indirectly accessed variables */ + for (i = 0; i < op_array->last_var; i++) { + if (ssa->cfg.dynamic) { + ssa_vars[i].alias = SYMTABLE_ALIAS; + } else if (zend_string_equals_literal(op_array->vars[i], "php_errormsg")) { + ssa_vars[i].alias = PHP_ERRORMSG_ALIAS; + } else if (zend_string_equals_literal(op_array->vars[i], "http_response_header")) { + ssa_vars[i].alias = HTTP_RESPONSE_HEADER_ALIAS; + } + } + for (i = op_array->last_var; i < ssa->vars_count; i++) { + if (ssa_vars[i].var < op_array->last_var) { + ssa_vars[i].alias = ssa_vars[ssa_vars[i].var].alias; + } + } + return SUCCESS; } /* }}} */ diff --git a/ext/opcache/Optimizer/zend_ssa.h b/ext/opcache/Optimizer/zend_ssa.h index 1130d9d62a..b8e5d8c3e8 100644 --- a/ext/opcache/Optimizer/zend_ssa.h +++ b/ext/opcache/Optimizer/zend_ssa.h @@ -92,6 +92,13 @@ typedef struct _zend_ssa_op { int res_use_chain; } zend_ssa_op; +typedef enum _zend_ssa_alias_kind { + NO_ALIAS, + SYMTABLE_ALIAS, + PHP_ERRORMSG_ALIAS, + HTTP_RESPONSE_HEADER_ALIAS +} zend_ssa_alias_kind; + typedef struct _zend_ssa_var { int var; /* original var number; op.var for CVs and following numbers for VARs and TMP_VARs */ int scc; /* strongly connected component */ @@ -102,6 +109,7 @@ typedef struct _zend_ssa_var { zend_ssa_phi *sym_use_chain; /* uses of this value in Pi constaints */ unsigned int no_val : 1; /* value doesn't mater (used as op1 in ZEND_ASSIGN) */ unsigned int scc_entry : 1; + zend_ssa_alias_kind alias : 2; /* value may be changed indirectly */ } zend_ssa_var; typedef struct _zend_ssa_var_info {