PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/opcache/Optimizer - zend_optimizer.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 222 470 47.2 %
Date: 2016-07-26 Functions: 17 26 65.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend OPcache                                                         |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2016 The PHP Group                                |
       6             :    +----------------------------------------------------------------------+
       7             :    | This source file is subject to version 3.01 of the PHP license,      |
       8             :    | that is bundled with this package in the file LICENSE, and is        |
       9             :    | available through the world-wide-web at the following url:           |
      10             :    | http://www.php.net/license/3_01.txt                                  |
      11             :    | If you did not receive a copy of the PHP license and are unable to   |
      12             :    | obtain it through the world-wide-web, please send a note to          |
      13             :    | license@php.net so we can mail you a copy immediately.               |
      14             :    +----------------------------------------------------------------------+
      15             :    | Authors: Andi Gutmans <andi@zend.com>                                |
      16             :    |          Zeev Suraski <zeev@zend.com>                                |
      17             :    |          Stanislav Malyshev <stas@zend.com>                          |
      18             :    |          Dmitry Stogov <dmitry@zend.com>                             |
      19             :    +----------------------------------------------------------------------+
      20             : */
      21             : 
      22             : #include "php.h"
      23             : #include "Optimizer/zend_optimizer.h"
      24             : #include "Optimizer/zend_optimizer_internal.h"
      25             : #include "zend_API.h"
      26             : #include "zend_constants.h"
      27             : #include "zend_execute.h"
      28             : #include "zend_vm.h"
      29             : #include "zend_cfg.h"
      30             : #include "zend_func_info.h"
      31             : #include "zend_call_graph.h"
      32             : #include "zend_inference.h"
      33             : #include "zend_dump.h"
      34             : 
      35             : #ifndef HAVE_DFA_PASS
      36             : # define HAVE_DFA_PASS 1
      37             : #endif
      38             : 
      39           0 : static void zend_optimizer_zval_dtor_wrapper(zval *zvalue)
      40             : {
      41             :         zval_dtor(zvalue);
      42           0 : }
      43             : 
      44           0 : void zend_optimizer_collect_constant(zend_optimizer_ctx *ctx, zval *name, zval* value)
      45             : {
      46             :         zval val;
      47             : 
      48           0 :         if (!ctx->constants) {
      49           0 :                 ctx->constants = zend_arena_alloc(&ctx->arena, sizeof(HashTable));
      50           0 :                 zend_hash_init(ctx->constants, 16, NULL, zend_optimizer_zval_dtor_wrapper, 0);
      51             :         }
      52           0 :         ZVAL_DUP(&val, value);
      53           0 :         zend_hash_add(ctx->constants, Z_STR_P(name), &val);
      54           0 : }
      55             : 
      56           0 : int zend_optimizer_get_collected_constant(HashTable *constants, zval *name, zval* value)
      57             : {
      58             :         zval *val;
      59             : 
      60           0 :         if ((val = zend_hash_find(constants, Z_STR_P(name))) != NULL) {
      61           0 :                 ZVAL_DUP(value, val);
      62           0 :                 return 1;
      63             :         }
      64           0 :         return 0;
      65             : }
      66             : 
      67           0 : int zend_optimizer_lookup_cv(zend_op_array *op_array, zend_string* name)
      68             : {
      69           0 :         int i = 0;
      70           0 :         zend_ulong hash_value = zend_string_hash_val(name);
      71             : 
      72           0 :         while (i < op_array->last_var) {
      73           0 :                 if (op_array->vars[i] == name ||
      74           0 :                     (ZSTR_H(op_array->vars[i]) == hash_value &&
      75           0 :                      ZSTR_LEN(op_array->vars[i]) == ZSTR_LEN(name) &&
      76           0 :                      memcmp(ZSTR_VAL(op_array->vars[i]), ZSTR_VAL(name), ZSTR_LEN(name)) == 0)) {
      77           0 :                         return (int)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, i);
      78             :                 }
      79           0 :                 i++;
      80             :         }
      81           0 :         i = op_array->last_var;
      82           0 :         op_array->last_var++;
      83           0 :         op_array->vars = erealloc(op_array->vars, op_array->last_var * sizeof(zend_string*));
      84           0 :         op_array->vars[i] = zend_string_dup(name, 0);
      85             : 
      86             :         /* all IS_TMP_VAR and IS_VAR variable numbers have to be adjusted */
      87             :         {
      88           0 :                 zend_op *opline = op_array->opcodes;
      89           0 :                 zend_op *end = opline + op_array->last;
      90           0 :                 while (opline < end) {
      91           0 :                         if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
      92           0 :                                 opline->op1.var += sizeof(zval);
      93             :                         }
      94           0 :                         if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) {
      95           0 :                                 opline->op2.var += sizeof(zval);
      96             :                         }
      97           0 :                         if (opline->result_type & (IS_TMP_VAR|IS_VAR)) {
      98           0 :                                 opline->result.var += sizeof(zval);
      99             :                         }
     100           0 :                         opline++;
     101             :                 }
     102             :         }
     103             : 
     104           0 :         return (int)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, i);
     105             : }
     106             : 
     107         430 : int zend_optimizer_add_literal(zend_op_array *op_array, zval *zv)
     108             : {
     109         430 :         int i = op_array->last_literal;
     110         430 :         op_array->last_literal++;
     111         430 :         op_array->literals = (zval*)erealloc(op_array->literals, op_array->last_literal * sizeof(zval));
     112         430 :         ZVAL_COPY_VALUE(&op_array->literals[i], zv);
     113         430 :         Z_CACHE_SLOT(op_array->literals[i]) = -1;
     114         430 :         return i;
     115             : }
     116             : 
     117           0 : static inline int zend_optimizer_add_literal_string(zend_op_array *op_array, zend_string *str) {
     118             :         zval zv;
     119           0 :         ZVAL_STR(&zv, str);
     120             :         zend_string_hash_val(str);
     121           0 :         return zend_optimizer_add_literal(op_array, &zv);
     122             : }
     123             : 
     124         191 : int zend_optimizer_is_disabled_func(const char *name, size_t len) {
     125         382 :         zend_function *fbc = (zend_function *)zend_hash_str_find_ptr(EG(function_table), name, len);
     126             : 
     127         382 :         return (fbc && fbc->type == ZEND_INTERNAL_FUNCTION &&
     128         191 :                         fbc->internal_function.handler == ZEND_FN(display_disabled_function));
     129             : }
     130             : 
     131           0 : static inline void drop_leading_backslash(zval *val) {
     132           0 :         if (Z_STRVAL_P(val)[0] == '\\') {
     133           0 :                 zend_string *str = zend_string_init(Z_STRVAL_P(val) + 1, Z_STRLEN_P(val) - 1, 0);
     134             :                 zval_dtor(val);
     135           0 :                 ZVAL_STR(val, str);
     136             :         }
     137           0 : }
     138             : 
     139           0 : static inline void alloc_cache_slots_op1(zend_op_array *op_array, zend_op *opline, uint32_t num) {
     140           0 :         Z_CACHE_SLOT(op_array->literals[opline->op1.constant]) = op_array->cache_size;
     141           0 :         op_array->cache_size += num * sizeof(void *);
     142           0 : }
     143           0 : static inline void alloc_cache_slots_op2(zend_op_array *op_array, zend_op *opline, uint32_t num) {
     144           0 :         Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = op_array->cache_size;
     145           0 :         op_array->cache_size += num * sizeof(void *);
     146           0 : }
     147             : 
     148             : #define REQUIRES_STRING(val) do { \
     149             :         if (Z_TYPE_P(val) != IS_STRING) { \
     150             :                 zval_dtor(val); \
     151             :                 return 0; \
     152             :         } \
     153             : } while (0)
     154             : 
     155             : #define TO_STRING_NOWARN(val) do { \
     156             :         if (Z_TYPE_P(val) >= IS_ARRAY) { \
     157             :                 zval_dtor(val); \
     158             :                 return 0; \
     159             :         } \
     160             :         convert_to_string(val); \
     161             : } while (0)
     162             : 
     163         427 : int zend_optimizer_update_op1_const(zend_op_array *op_array,
     164             :                                     zend_op       *opline,
     165             :                                     zval          *val)
     166             : {
     167         427 :         switch (opline->opcode) {
     168             :                 case ZEND_FREE:
     169           0 :                         MAKE_NOP(opline);
     170             :                         zval_dtor(val);
     171           0 :                         return 1;
     172             :                 case ZEND_INIT_STATIC_METHOD_CALL:
     173             :                 case ZEND_CATCH:
     174             :                 case ZEND_FETCH_CONSTANT:
     175             :                 case ZEND_FETCH_CLASS_CONSTANT:
     176             :                 case ZEND_DEFINED:
     177             :                 case ZEND_NEW:
     178           0 :                         REQUIRES_STRING(val);
     179           0 :                         drop_leading_backslash(val);
     180           0 :                         opline->op1.constant = zend_optimizer_add_literal(op_array, val);
     181           0 :                         alloc_cache_slots_op1(op_array, opline, 1);
     182           0 :                         zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val)));
     183           0 :                         break;
     184             :                 case ZEND_FETCH_STATIC_PROP_R:
     185             :                 case ZEND_FETCH_STATIC_PROP_W:
     186             :                 case ZEND_FETCH_STATIC_PROP_RW:
     187             :                 case ZEND_FETCH_STATIC_PROP_IS:
     188             :                 case ZEND_FETCH_STATIC_PROP_UNSET:
     189             :                 case ZEND_FETCH_STATIC_PROP_FUNC_ARG:
     190           0 :                         TO_STRING_NOWARN(val);
     191           0 :                         opline->op1.constant = zend_optimizer_add_literal(op_array, val);
     192           0 :                         alloc_cache_slots_op1(op_array, opline, 2);
     193           0 :                         break;
     194             :                 case ZEND_SEND_VAR:
     195           0 :                         opline->opcode = ZEND_SEND_VAL;
     196           0 :                         opline->op1.constant = zend_optimizer_add_literal(op_array, val);
     197           0 :                         break;
     198             :                 case ZEND_SEPARATE:
     199             :                 case ZEND_SEND_VAR_NO_REF:
     200             :                 case ZEND_SEND_VAR_NO_REF_EX:
     201           0 :                         zval_ptr_dtor(val);
     202           0 :                         return 0;
     203             :                 case ZEND_CONCAT:
     204             :                 case ZEND_FAST_CONCAT:
     205             :                 case ZEND_FETCH_R:
     206             :                 case ZEND_FETCH_W:
     207             :                 case ZEND_FETCH_RW:
     208             :                 case ZEND_FETCH_IS:
     209             :                 case ZEND_FETCH_UNSET:
     210             :                 case ZEND_FETCH_FUNC_ARG:
     211          14 :                         TO_STRING_NOWARN(val);
     212             :                         /* break missing intentionally */
     213             :                 default:
     214         427 :                         opline->op1.constant = zend_optimizer_add_literal(op_array, val);
     215             :                         break;
     216             :         }
     217             : 
     218         427 :         ZEND_OP1_TYPE(opline) = IS_CONST;
     219         854 :         if (Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING) {
     220          14 :                 zend_string_hash_val(Z_STR(ZEND_OP1_LITERAL(opline)));
     221             :         }
     222         427 :         return 1;
     223             : }
     224             : 
     225           1 : int zend_optimizer_update_op2_const(zend_op_array *op_array,
     226             :                                     zend_op       *opline,
     227             :                                     zval          *val)
     228             : {
     229           1 :         switch (opline->opcode) {
     230             :                 case ZEND_ASSIGN_REF:
     231             :                 case ZEND_FAST_CALL:
     232             :                         zval_dtor(val);
     233           0 :                         return 0;
     234             :                 case ZEND_FETCH_CLASS:
     235             :                 case ZEND_INIT_FCALL_BY_NAME:
     236             :                 /*case ZEND_INIT_NS_FCALL_BY_NAME:*/
     237             :                 case ZEND_ADD_INTERFACE:
     238             :                 case ZEND_ADD_TRAIT:
     239             :                 case ZEND_INSTANCEOF:
     240             :                 case ZEND_FETCH_STATIC_PROP_R:
     241             :                 case ZEND_FETCH_STATIC_PROP_W:
     242             :                 case ZEND_FETCH_STATIC_PROP_RW:
     243             :                 case ZEND_FETCH_STATIC_PROP_IS:
     244             :                 case ZEND_FETCH_STATIC_PROP_UNSET:
     245             :                 case ZEND_FETCH_STATIC_PROP_FUNC_ARG:
     246             :                 case ZEND_UNSET_STATIC_PROP:
     247             :                 case ZEND_ISSET_ISEMPTY_STATIC_PROP:
     248           0 :                         REQUIRES_STRING(val);
     249           0 :                         drop_leading_backslash(val);
     250           0 :                         opline->op2.constant = zend_optimizer_add_literal(op_array, val);
     251           0 :                         zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val)));
     252           0 :                         alloc_cache_slots_op2(op_array, opline, 1);
     253           0 :                         break;
     254             :                 case ZEND_INIT_FCALL:
     255           0 :                         REQUIRES_STRING(val);
     256           0 :                         zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
     257           0 :                         opline->op2.constant = zend_optimizer_add_literal(op_array, val);
     258           0 :                         alloc_cache_slots_op2(op_array, opline, 1);
     259           0 :                         break;
     260             :                 case ZEND_INIT_DYNAMIC_CALL:
     261           0 :                         if (Z_TYPE_P(val) == IS_STRING) {
     262           0 :                                 if (zend_memrchr(Z_STRVAL_P(val), ':', Z_STRLEN_P(val))) {
     263             :                                         zval_dtor(val);
     264           0 :                                         return 0;
     265             :                                 }
     266             : 
     267           0 :                                 if (zend_optimizer_classify_function(Z_STR_P(val), opline->extended_value)) {
     268             :                                         /* Dynamic call to various special functions must stay dynamic,
     269             :                                          * otherwise would drop a warning */
     270             :                                         zval_dtor(val);
     271           0 :                                         return 0;
     272             :                                 }
     273             : 
     274           0 :                                 opline->opcode = ZEND_INIT_FCALL_BY_NAME;
     275           0 :                                 drop_leading_backslash(val);
     276           0 :                                 opline->op2.constant = zend_optimizer_add_literal(op_array, val);
     277           0 :                                 zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val)));
     278           0 :                                 alloc_cache_slots_op2(op_array, opline, 1);
     279             :                         } else {
     280           0 :                                 opline->op2.constant = zend_optimizer_add_literal(op_array, val);
     281             :                         }
     282           0 :                         break;
     283             :                 case ZEND_INIT_METHOD_CALL:
     284             :                 case ZEND_INIT_STATIC_METHOD_CALL:
     285           0 :                         REQUIRES_STRING(val);
     286           0 :                         opline->op2.constant = zend_optimizer_add_literal(op_array, val);
     287           0 :                         zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val)));
     288           0 :                         alloc_cache_slots_op2(op_array, opline, 2);
     289           0 :                         break;
     290             :                 /*case ZEND_FETCH_CLASS_CONSTANT:*/
     291             :                 case ZEND_ASSIGN_OBJ:
     292             :                 case ZEND_FETCH_OBJ_R:
     293             :                 case ZEND_FETCH_OBJ_W:
     294             :                 case ZEND_FETCH_OBJ_RW:
     295             :                 case ZEND_FETCH_OBJ_IS:
     296             :                 case ZEND_FETCH_OBJ_UNSET:
     297             :                 case ZEND_FETCH_OBJ_FUNC_ARG:
     298             :                 case ZEND_UNSET_OBJ:
     299             :                 case ZEND_PRE_INC_OBJ:
     300             :                 case ZEND_PRE_DEC_OBJ:
     301             :                 case ZEND_POST_INC_OBJ:
     302             :                 case ZEND_POST_DEC_OBJ:
     303             :                 case ZEND_ISSET_ISEMPTY_PROP_OBJ:
     304           0 :                         TO_STRING_NOWARN(val);
     305           0 :                         opline->op2.constant = zend_optimizer_add_literal(op_array, val);
     306           0 :                         alloc_cache_slots_op2(op_array, opline, 2);
     307           0 :                         break;
     308             :                 case ZEND_ASSIGN_ADD:
     309             :                 case ZEND_ASSIGN_SUB:
     310             :                 case ZEND_ASSIGN_MUL:
     311             :                 case ZEND_ASSIGN_DIV:
     312             :                 case ZEND_ASSIGN_POW:
     313             :                 case ZEND_ASSIGN_MOD:
     314             :                 case ZEND_ASSIGN_SL:
     315             :                 case ZEND_ASSIGN_SR:
     316             :                 case ZEND_ASSIGN_CONCAT:
     317             :                 case ZEND_ASSIGN_BW_OR:
     318             :                 case ZEND_ASSIGN_BW_AND:
     319             :                 case ZEND_ASSIGN_BW_XOR:
     320           0 :                         if (opline->extended_value == ZEND_ASSIGN_OBJ) {
     321           0 :                                 TO_STRING_NOWARN(val);
     322           0 :                                 opline->op2.constant = zend_optimizer_add_literal(op_array, val);
     323           0 :                                 alloc_cache_slots_op2(op_array, opline, 2);
     324             :                         } else {
     325           0 :                                 opline->op2.constant = zend_optimizer_add_literal(op_array, val);
     326             :                         }
     327           0 :                         break;
     328             :                 case ZEND_ISSET_ISEMPTY_DIM_OBJ:
     329             :                 case ZEND_ADD_ARRAY_ELEMENT:
     330             :                 case ZEND_INIT_ARRAY:
     331             :                 case ZEND_ASSIGN_DIM:
     332             :                 case ZEND_UNSET_DIM:
     333             :                 case ZEND_FETCH_DIM_R:
     334             :                 case ZEND_FETCH_DIM_W:
     335             :                 case ZEND_FETCH_DIM_RW:
     336             :                 case ZEND_FETCH_DIM_IS:
     337             :                 case ZEND_FETCH_DIM_FUNC_ARG:
     338             :                 case ZEND_FETCH_DIM_UNSET:
     339             :                 case ZEND_FETCH_LIST:
     340           0 :                         if (Z_TYPE_P(val) == IS_STRING) {
     341             :                                 zend_ulong index;
     342           0 :                                 if (ZEND_HANDLE_NUMERIC(Z_STR_P(val), index)) {
     343             :                                         zval_dtor(val);
     344           0 :                                         ZVAL_LONG(val, index);
     345             :                                 }
     346             :                         }
     347           0 :                         opline->op2.constant = zend_optimizer_add_literal(op_array, val);
     348           0 :                         break;
     349             :                 case ZEND_ROPE_INIT:
     350             :                 case ZEND_ROPE_ADD:
     351             :                 case ZEND_ROPE_END:
     352             :                 case ZEND_CONCAT:
     353             :                 case ZEND_FAST_CONCAT:
     354           0 :                         TO_STRING_NOWARN(val);
     355             :                         /* break missing intentionally */
     356             :                 default:
     357           1 :                         opline->op2.constant = zend_optimizer_add_literal(op_array, val);
     358             :                         break;
     359             :         }
     360             : 
     361           1 :         ZEND_OP2_TYPE(opline) = IS_CONST;
     362           2 :         if (Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) {
     363           1 :                 zend_string_hash_val(Z_STR(ZEND_OP2_LITERAL(opline)));
     364             :         }
     365           1 :         return 1;
     366             : }
     367             : 
     368         428 : void zend_optimizer_remove_live_range(zend_op_array *op_array, uint32_t var)
     369             : {
     370         428 :         if (op_array->last_live_range) {
     371         117 :                 int i = 0;
     372         117 :                 int j = 0;
     373             :                 uint32_t *map;
     374             :                 ALLOCA_FLAG(use_heap);
     375             : 
     376         117 :                 map = (uint32_t *)do_alloca(sizeof(uint32_t) * op_array->last_live_range, use_heap);
     377             : 
     378             :                 do {
     379         355 :                         if ((op_array->live_range[i].var & ~ZEND_LIVE_MASK) != var) {
     380         355 :                                 map[i] = j;
     381         355 :                                 if (i != j) {
     382           0 :                                         op_array->live_range[j] = op_array->live_range[i];
     383             :                                 }
     384         355 :                                 j++;
     385             :                         }
     386         355 :                         i++;
     387         355 :                 } while (i < op_array->last_live_range);
     388         117 :                 if (i != j) {
     389           0 :                         if ((op_array->last_live_range = j)) {
     390           0 :                                 zend_op *opline = op_array->opcodes;
     391           0 :                                 zend_op *end = opline + op_array->last;
     392             : 
     393           0 :                                 while (opline != end) {
     394           0 :                                         if ((opline->opcode == ZEND_FREE || opline->opcode == ZEND_FE_FREE) &&
     395           0 :                                                         opline->extended_value == ZEND_FREE_ON_RETURN) {
     396           0 :                                                 opline->op2.num = map[opline->op2.num];
     397             :                                         }
     398           0 :                                         opline++;
     399             :                                 }
     400             :                         } else {
     401           0 :                                 efree(op_array->live_range);
     402           0 :                                 op_array->live_range = NULL;
     403             :                         }
     404             :                 }
     405         117 :                 free_alloca(map, use_heap);
     406             :         }
     407         428 : }
     408             : 
     409         428 : int zend_optimizer_replace_by_const(zend_op_array *op_array,
     410             :                                     zend_op       *opline,
     411             :                                     zend_uchar     type,
     412             :                                     uint32_t       var,
     413             :                                     zval          *val)
     414             : {
     415         428 :         zend_op *end = op_array->opcodes + op_array->last;
     416             : 
     417         912 :         while (opline < end) {
     418         911 :                 if (ZEND_OP1_TYPE(opline) == type &&
     419         427 :                         ZEND_OP1(opline).var == var) {
     420         427 :                         switch (opline->opcode) {
     421             :                                 case ZEND_FETCH_DIM_W:
     422             :                                 case ZEND_FETCH_DIM_RW:
     423             :                                 case ZEND_FETCH_DIM_FUNC_ARG:
     424             :                                 case ZEND_FETCH_DIM_UNSET:
     425             :                                 case ZEND_ASSIGN_DIM:
     426             :                                 case ZEND_SEPARATE:
     427             :                                 case ZEND_RETURN_BY_REF:
     428             :                                         zval_dtor(val);
     429           0 :                                         return 0;
     430             :                                 case ZEND_SEND_VAR:
     431           0 :                                         opline->extended_value = 0;
     432           0 :                                         opline->opcode = ZEND_SEND_VAL;
     433           0 :                                         break;
     434             :                                 case ZEND_SEND_VAR_EX:
     435           0 :                                         opline->extended_value = 0;
     436           0 :                                         opline->opcode = ZEND_SEND_VAL_EX;
     437           0 :                                         break;
     438             :                                 case ZEND_SEND_VAR_NO_REF:
     439             :                                         zval_dtor(val);
     440           0 :                                         return 0;
     441             :                                 case ZEND_SEND_VAR_NO_REF_EX:
     442           0 :                                         opline->opcode = ZEND_SEND_VAL;
     443           0 :                                         break;
     444             :                                 case ZEND_SEND_USER:
     445           0 :                                         opline->opcode = ZEND_SEND_VAL_EX;
     446           0 :                                         break;
     447             :                                 /* In most cases IS_TMP_VAR operand may be used only once.
     448             :                                  * The operands are usually destroyed by the opcode handler.
     449             :                                  * ZEND_CASE is an exception, that keeps operand unchanged,
     450             :                                  * and allows its reuse. The number of ZEND_CASE instructions
     451             :                                  * usually terminated by ZEND_FREE that finally kills the value.
     452             :                                  */
     453             :                                 case ZEND_FREE:
     454             :                                 case ZEND_CASE: {
     455             :                                         zend_op *m, *n;
     456           0 :                                         int brk = op_array->last_live_range;
     457           0 :                                         zend_bool in_switch = 0;
     458           0 :                                         while (brk--) {
     459           0 :                                                 if (op_array->live_range[brk].start <= (uint32_t)(opline - op_array->opcodes) &&
     460           0 :                                                     op_array->live_range[brk].end > (uint32_t)(opline - op_array->opcodes)) {
     461           0 :                                                         in_switch = 1;
     462           0 :                                                         break;
     463             :                                                 }
     464             :                                         }
     465             : 
     466           0 :                                         if (!in_switch) {
     467             :                                                 ZEND_ASSERT(opline->opcode == ZEND_FREE);
     468           0 :                                                 MAKE_NOP(opline);
     469             :                                                 zval_dtor(val);
     470           0 :                                                 return 1;
     471             :                                         }
     472             : 
     473           0 :                                         m = opline;
     474           0 :                                         n = op_array->opcodes + op_array->live_range[brk].end;
     475           0 :                                         if (n->opcode == ZEND_FREE &&
     476           0 :                                             !(n->extended_value & ZEND_FREE_ON_RETURN)) {
     477           0 :                                                 n++;
     478             :                                         } else {
     479           0 :                                                 n = op_array->opcodes + op_array->last;
     480             :                                         }
     481           0 :                                         while (m < n) {
     482           0 :                                                 if (ZEND_OP1_TYPE(m) == type &&
     483           0 :                                                                 ZEND_OP1(m).var == var) {
     484           0 :                                                         if (m->opcode == ZEND_CASE) {
     485             :                                                                 zval old_val;
     486           0 :                                                                 ZVAL_COPY_VALUE(&old_val, val);
     487             :                                                                 zval_copy_ctor(val);
     488           0 :                                                                 zend_optimizer_update_op1_const(op_array, m, val);
     489           0 :                                                                 ZVAL_COPY_VALUE(val, &old_val);
     490           0 :                                                         } else if (m->opcode == ZEND_FREE) {
     491           0 :                                                                 MAKE_NOP(m);
     492             :                                                         } else {
     493             :                                                                 ZEND_ASSERT(0);
     494             :                                                         }
     495             :                                                 }
     496           0 :                                                 m++;
     497             :                                         }
     498             :                                         zval_dtor(val);
     499           0 :                                         zend_optimizer_remove_live_range(op_array, var);
     500           0 :                                         return 1;
     501             :                                 }
     502             :                                 case ZEND_VERIFY_RETURN_TYPE: {
     503           0 :                                         zend_arg_info *ret_info = op_array->arg_info - 1;
     504             :                                         ZEND_ASSERT((opline + 1)->opcode == ZEND_RETURN || (opline + 1)->opcode == ZEND_RETURN_BY_REF);
     505           0 :                                         if (ret_info->class_name
     506           0 :                                                 || ret_info->type_hint == IS_CALLABLE
     507           0 :                                                 || !ZEND_SAME_FAKE_TYPE(ret_info->type_hint, Z_TYPE_P(val))
     508           0 :                                                 || (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
     509             :                                                 zval_dtor(val);
     510           0 :                                                 return 0;
     511             :                                         }
     512           0 :                                         MAKE_NOP(opline);
     513           0 :                                         opline++;
     514             :                                         break;
     515             :                                   }
     516             :                                 default:
     517             :                                         break;
     518             :                         }
     519         427 :                         if (zend_optimizer_update_op1_const(op_array, opline, val)) {
     520         427 :                                 zend_optimizer_remove_live_range(op_array, var);
     521         427 :                                 return 1;
     522             :                         }
     523           0 :                         return 0;
     524             :                 }
     525             : 
     526          58 :                 if (ZEND_OP2_TYPE(opline) == type &&
     527           1 :                         ZEND_OP2(opline).var == var) {
     528           1 :                         if (zend_optimizer_update_op2_const(op_array, opline, val)) {
     529           1 :                                 zend_optimizer_remove_live_range(op_array, var);
     530           1 :                                 return 1;
     531             :                         }
     532           0 :                         return 0;
     533             :                 }
     534          56 :                 opline++;
     535             :         }
     536             : 
     537           0 :         return 1;
     538             : }
     539             : 
     540        2047 : zend_function *zend_optimizer_get_called_func(
     541             :                 zend_script *script, zend_op_array *op_array, zend_op *opline, zend_bool rt_constants)
     542             : {
     543             : #define GET_OP(op) CRT_CONSTANT_EX(op_array, opline->op, rt_constants)
     544        2047 :         switch (opline->opcode) {
     545             :                 case ZEND_INIT_FCALL:
     546             :                 {
     547        1766 :                         zend_string *function_name = Z_STR_P(GET_OP(op2));
     548             :                         zend_function *func;
     549        3532 :                         if ((func = zend_hash_find_ptr(&script->function_table, function_name)) != NULL) {
     550           0 :                                 return func;
     551        3532 :                         } else if ((func = zend_hash_find_ptr(EG(function_table), function_name)) != NULL) {
     552             :                                 ZEND_ASSERT(func->type == ZEND_INTERNAL_FUNCTION);
     553        1766 :                                 return func;
     554             :                         }
     555           0 :                         break;
     556             :                 }
     557             :                 case ZEND_INIT_FCALL_BY_NAME:
     558             :                 case ZEND_INIT_NS_FCALL_BY_NAME:
     559          10 :                         if (opline->op2_type == IS_CONST && Z_TYPE_P(GET_OP(op2)) == IS_STRING) {
     560           5 :                                 zval *function_name = GET_OP(op2) + 1;
     561          10 :                                 return zend_hash_find_ptr(&script->function_table, Z_STR_P(function_name));
     562             :                         }
     563           0 :                         break;
     564             :                 case ZEND_INIT_STATIC_METHOD_CALL:
     565         480 :                         if (opline->op2_type == IS_CONST && Z_TYPE_P(GET_OP(op2)) == IS_STRING) {
     566         240 :                                 zend_class_entry *ce = NULL;
     567         700 :                                 if (opline->op1_type == IS_CONST && Z_TYPE_P(GET_OP(op1)) == IS_STRING) {
     568         230 :                                         zend_string *class_name = Z_STR_P(GET_OP(op1) + 1);
     569         460 :                                         ce = zend_hash_find_ptr(&script->class_table, class_name);
     570          40 :                                 } else if (opline->op1_type == IS_UNUSED && op_array->scope
     571          20 :                                                 && !(op_array->scope->ce_flags & ZEND_ACC_TRAIT)
     572          10 :                                                 && (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
     573          10 :                                         ce = op_array->scope;
     574             :                                 }
     575         240 :                                 if (ce) {
     576          22 :                                         zend_string *func_name = Z_STR_P(GET_OP(op2) + 1);
     577          44 :                                         return zend_hash_find_ptr(&ce->function_table, func_name);
     578             :                                 }
     579             :                         }
     580         218 :                         break;
     581             :                 case ZEND_INIT_METHOD_CALL:
     582          36 :                         if (opline->op1_type == IS_UNUSED
     583          36 :                                         && opline->op2_type == IS_CONST && Z_TYPE_P(GET_OP(op2)) == IS_STRING
     584           0 :                                         && op_array->scope && !(op_array->scope->ce_flags & ZEND_ACC_TRAIT)) {
     585           0 :                                 zend_string *method_name = Z_STR_P(GET_OP(op2) + 1);
     586             :                                 zend_function *fbc = zend_hash_find_ptr(
     587           0 :                                         &op_array->scope->function_table, method_name);
     588           0 :                                 if (fbc) {
     589           0 :                                         zend_bool is_private = (fbc->common.fn_flags & ZEND_ACC_PRIVATE) != 0;
     590           0 :                                         zend_bool is_final = (fbc->common.fn_flags & ZEND_ACC_FINAL) != 0;
     591           0 :                                         zend_bool same_scope = fbc->common.scope == op_array->scope;
     592           0 :                                         if ((is_private && same_scope)
     593             :                                                         || (is_final && (!is_private || same_scope))) {
     594           0 :                                                 return fbc;
     595             :                                         }
     596             :                                 }
     597             :                         }
     598             :                         break;
     599             :         }
     600         254 :         return NULL;
     601             : #undef GET_OP
     602             : }
     603             : 
     604        1760 : uint32_t zend_optimizer_classify_function(zend_string *name, uint32_t num_args) {
     605        1760 :         if (zend_string_equals_literal(name, "extract")) {
     606           0 :                 return ZEND_FUNC_INDIRECT_VAR_ACCESS;
     607        1760 :         } else if (zend_string_equals_literal(name, "compact")) {
     608           0 :                 return ZEND_FUNC_INDIRECT_VAR_ACCESS;
     609        1760 :         } else if (zend_string_equals_literal(name, "parse_str") && num_args <= 1) {
     610           0 :                 return ZEND_FUNC_INDIRECT_VAR_ACCESS;
     611        1760 :         } else if (zend_string_equals_literal(name, "mb_parse_str") && num_args <= 1) {
     612           0 :                 return ZEND_FUNC_INDIRECT_VAR_ACCESS;
     613        1760 :         } else if (zend_string_equals_literal(name, "get_defined_vars")) {
     614           0 :                 return ZEND_FUNC_INDIRECT_VAR_ACCESS;
     615        1760 :         } else if (zend_string_equals_literal(name, "assert")) {
     616           2 :                 return ZEND_FUNC_INDIRECT_VAR_ACCESS;
     617        1758 :         } else if (zend_string_equals_literal(name, "func_num_args")) {
     618           0 :                 return ZEND_FUNC_VARARG;
     619        1758 :         } else if (zend_string_equals_literal(name, "func_get_arg")) {
     620           0 :                 return ZEND_FUNC_VARARG;
     621        1758 :         } else if (zend_string_equals_literal(name, "func_get_args")) {
     622           0 :                 return ZEND_FUNC_VARARG;
     623             :         } else {
     624        1758 :                 return 0;
     625             :         }
     626             : }
     627             : 
     628         466 : static void zend_optimize(zend_op_array      *op_array,
     629             :                           zend_optimizer_ctx *ctx)
     630             : {
     631         466 :         if (op_array->type == ZEND_EVAL_CODE) {
     632           0 :                 return;
     633             :         }
     634             : 
     635         466 :         if (ctx->debug_level & ZEND_DUMP_BEFORE_OPTIMIZER) {
     636           0 :                 zend_dump_op_array(op_array, 0, "before optimizer", NULL);
     637             :         }
     638             : 
     639             :         /* pass 1
     640             :          * - substitute persistent constants (true, false, null, etc)
     641             :          * - perform compile-time evaluation of constant binary and unary operations
     642             :          * - optimize series of ADD_STRING and/or ADD_CHAR
     643             :          * - convert CAST(IS_BOOL,x) into BOOL(x)
     644             :          * - pre-evaluate constant function calls
     645             :          */
     646         466 :         if (ZEND_OPTIMIZER_PASS_1 & ctx->optimization_level) {
     647         466 :                 zend_optimizer_pass1(op_array, ctx);
     648         466 :                 if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_1) {
     649           0 :                         zend_dump_op_array(op_array, 0, "after pass 1", NULL);
     650             :                 }
     651             :         }
     652             : 
     653             :         /* pass 2:
     654             :          * - convert non-numeric constants to numeric constants in numeric operators
     655             :          * - optimize constant conditional JMPs
     656             :          */
     657         466 :         if (ZEND_OPTIMIZER_PASS_2 & ctx->optimization_level) {
     658         466 :                 zend_optimizer_pass2(op_array);
     659         466 :                 if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_2) {
     660           0 :                         zend_dump_op_array(op_array, 0, "after pass 2", NULL);
     661             :                 }
     662             :         }
     663             : 
     664             :         /* pass 3:
     665             :          * - optimize $i = $i+expr to $i+=expr
     666             :          * - optimize series of JMPs
     667             :          * - change $i++ to ++$i where possible
     668             :          */
     669         466 :         if (ZEND_OPTIMIZER_PASS_3 & ctx->optimization_level) {
     670         466 :                 zend_optimizer_pass3(op_array);
     671         466 :                 if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_3) {
     672           0 :                         zend_dump_op_array(op_array, 0, "after pass 3", NULL);
     673             :                 }
     674             :         }
     675             : 
     676             :         /* pass 4:
     677             :          * - INIT_FCALL_BY_NAME -> DO_FCALL
     678             :          */
     679         466 :         if (ZEND_OPTIMIZER_PASS_4 & ctx->optimization_level) {
     680         466 :                 zend_optimize_func_calls(op_array, ctx);
     681         466 :                 if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_4) {
     682           0 :                         zend_dump_op_array(op_array, 0, "after pass 4", NULL);
     683             :                 }
     684             :         }
     685             : 
     686             :         /* pass 5:
     687             :          * - CFG optimization
     688             :          */
     689         466 :         if (ZEND_OPTIMIZER_PASS_5 & ctx->optimization_level) {
     690         466 :                 zend_optimize_cfg(op_array, ctx);
     691         466 :                 if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_5) {
     692           0 :                         zend_dump_op_array(op_array, 0, "after pass 5", NULL);
     693             :                 }
     694             :         }
     695             : 
     696             : #if HAVE_DFA_PASS
     697             :         /* pass 6:
     698             :          * - DFA optimization
     699             :          */
     700         932 :         if ((ZEND_OPTIMIZER_PASS_6 & ctx->optimization_level) &&
     701         466 :             !(ZEND_OPTIMIZER_PASS_7 & ctx->optimization_level)) {
     702           0 :                 zend_optimize_dfa(op_array, ctx);
     703           0 :                 if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_6) {
     704           0 :                         zend_dump_op_array(op_array, 0, "after pass 6", NULL);
     705             :                 }
     706             :         }
     707             : #endif
     708             : 
     709             :         /* pass 9:
     710             :          * - Optimize temp variables usage
     711             :          */
     712         466 :         if (ZEND_OPTIMIZER_PASS_9 & ctx->optimization_level) {
     713         466 :                 zend_optimize_temporary_variables(op_array, ctx);
     714         466 :                 if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_9) {
     715           0 :                         zend_dump_op_array(op_array, 0, "after pass 9", NULL);
     716             :                 }
     717             :         }
     718             : 
     719             :         /* pass 10:
     720             :          * - remove NOPs
     721             :          */
     722         466 :         if (((ZEND_OPTIMIZER_PASS_10|ZEND_OPTIMIZER_PASS_5) & ctx->optimization_level) == ZEND_OPTIMIZER_PASS_10) {
     723           0 :                 zend_optimizer_nop_removal(op_array);
     724           0 :                 if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_10) {
     725           0 :                         zend_dump_op_array(op_array, 0, "after pass 10", NULL);
     726             :                 }
     727             :         }
     728             : 
     729             :         /* pass 11:
     730             :          * - Compact literals table
     731             :          */
     732         466 :         if (ZEND_OPTIMIZER_PASS_11 & ctx->optimization_level) {
     733         466 :                 zend_optimizer_compact_literals(op_array, ctx);
     734         466 :                 if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_11) {
     735           0 :                         zend_dump_op_array(op_array, 0, "after pass 11", NULL);
     736             :                 }
     737             :         }
     738             : 
     739         466 :         if (ctx->debug_level & ZEND_DUMP_AFTER_OPTIMIZER) {
     740           0 :                 zend_dump_op_array(op_array, 0, "after optimizer", NULL);
     741             :         }
     742             : }
     743             : 
     744         932 : static void zend_revert_pass_two(zend_op_array *op_array)
     745             : {
     746             :         zend_op *opline, *end;
     747             : 
     748         932 :         opline = op_array->opcodes;
     749         932 :         end = opline + op_array->last;
     750       15086 :         while (opline < end) {
     751       13222 :                 if (opline->op1_type == IS_CONST) {
     752        4627 :                         ZEND_PASS_TWO_UNDO_CONSTANT(op_array, opline->op1);
     753             :                 }
     754       13222 :                 if (opline->op2_type == IS_CONST) {
     755        3175 :                         ZEND_PASS_TWO_UNDO_CONSTANT(op_array, opline->op2);
     756             :                 }
     757       13222 :                 opline++;
     758             :         }
     759         932 : }
     760             : 
     761         677 : static void zend_redo_pass_two(zend_op_array *op_array)
     762             : {
     763             :         zend_op *opline, *end;
     764             : 
     765         677 :         opline = op_array->opcodes;
     766         677 :         end = opline + op_array->last;
     767       10584 :         while (opline < end) {
     768        9230 :                 if (opline->op1_type == IS_CONST) {
     769        3406 :                         ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op1);
     770             :                 }
     771        9230 :                 if (opline->op2_type == IS_CONST) {
     772        2357 :                         ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op2);
     773             :                 }
     774        9230 :                 ZEND_VM_SET_OPCODE_HANDLER(opline);
     775        9230 :                 opline++;
     776             :         }
     777         677 : }
     778             : 
     779             : #if HAVE_DFA_PASS
     780         255 : static void zend_redo_pass_two_ex(zend_op_array *op_array, zend_ssa *ssa)
     781             : {
     782             :         zend_op *opline, *end;
     783             : 
     784         255 :         opline = op_array->opcodes;
     785         255 :         end = opline + op_array->last;
     786        2841 :         while (opline < end) {
     787       13741 :                 zend_vm_set_opcode_handler_ex(opline,
     788             :                         opline->op1_type == IS_UNUSED ? 0 : (OP1_INFO() & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_KEY_ANY)),
     789             :                         opline->op2_type == IS_UNUSED ? 0 : (OP2_INFO() & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_KEY_ANY)),
     790        2331 :                         (opline->opcode == ZEND_PRE_INC ||
     791        2316 :                          opline->opcode == ZEND_PRE_DEC ||
     792        2315 :                          opline->opcode == ZEND_POST_INC ||
     793        2315 :                          opline->opcode == ZEND_POST_DEC) ?
     794          32 :                                 ((ssa->ops[opline - op_array->opcodes].op1_def >= 0) ? (OP1_DEF_INFO() & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_KEY_ANY)) : MAY_BE_ANY) :
     795        2849 :                                 (opline->result_type == IS_UNUSED ? 0 : (RES_INFO() & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_KEY_ANY))));
     796        2331 :                 if (opline->op1_type == IS_CONST) {
     797         726 :                         ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op1);
     798             :                 }
     799        2331 :                 if (opline->op2_type == IS_CONST) {
     800         507 :                         ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op2);
     801             :                 }
     802        2331 :                 opline++;
     803             :         }
     804         255 : }
     805             : #endif
     806             : 
     807         466 : static void zend_optimize_op_array(zend_op_array      *op_array,
     808             :                                    zend_optimizer_ctx *ctx)
     809             : {
     810             :         /* Revert pass_two() */
     811         466 :         zend_revert_pass_two(op_array);
     812             : 
     813             :         /* Do actual optimizations */
     814         466 :         zend_optimize(op_array, ctx);
     815             : 
     816             :         /* Redo pass_two() */
     817         466 :         zend_redo_pass_two(op_array);
     818         466 : }
     819             : 
     820           0 : static void zend_adjust_fcall_stack_size(zend_op_array *op_array, zend_optimizer_ctx *ctx)
     821             : {
     822             :         zend_function *func;
     823             :         zend_op *opline, *end;
     824             : 
     825           0 :         opline = op_array->opcodes;
     826           0 :         end = opline + op_array->last;
     827           0 :         while (opline < end) {
     828           0 :                 if (opline->opcode == ZEND_INIT_FCALL) {
     829           0 :                         func = zend_hash_find_ptr(
     830           0 :                                 &ctx->script->function_table,
     831           0 :                                 Z_STR_P(RT_CONSTANT(op_array, opline->op2)));
     832           0 :                         if (func) {
     833           0 :                                 opline->op1.num = zend_vm_calc_used_stack(opline->extended_value, func);
     834             :                         }
     835             :                 }
     836           0 :                 opline++;
     837             :         }
     838           0 : }
     839             : 
     840             : #if HAVE_DFA_PASS
     841         466 : static void zend_adjust_fcall_stack_size_graph(zend_op_array *op_array)
     842             : {
     843         466 :         zend_func_info *func_info = ZEND_FUNC_INFO(op_array);
     844             : 
     845         466 :         if (func_info) {
     846         466 :                 zend_call_info *call_info =func_info->callee_info;
     847             : 
     848        1805 :                 while (call_info) {
     849         873 :                         zend_op *opline = call_info->caller_init_opline;
     850             : 
     851         873 :                         if (opline && call_info->callee_func && opline->opcode == ZEND_INIT_FCALL) {
     852        1724 :                                 opline->op1.num = zend_vm_calc_used_stack(opline->extended_value, call_info->callee_func);
     853             :                         }
     854         873 :                         call_info = call_info->next_callee;
     855             :                 }
     856             :         }
     857         466 : }
     858             : #endif
     859             : 
     860         433 : int zend_optimize_script(zend_script *script, zend_long optimization_level, zend_long debug_level)
     861             : {
     862             :         zend_class_entry *ce;
     863             :         zend_op_array *op_array;
     864             :         zend_string *name;
     865             :         zend_optimizer_ctx ctx;
     866             : #if HAVE_DFA_PASS
     867             :         zend_call_graph call_graph;
     868             : #endif
     869             : 
     870         433 :         ctx.arena = zend_arena_create(64 * 1024);
     871         433 :         ctx.script = script;
     872         433 :         ctx.constants = NULL;
     873         433 :         ctx.optimization_level = optimization_level;
     874         433 :         ctx.debug_level = debug_level;
     875             : 
     876         433 :         zend_optimize_op_array(&script->main_op_array, &ctx);
     877             : 
     878         481 :         ZEND_HASH_FOREACH_PTR(&script->function_table, op_array) {
     879          24 :                 zend_optimize_op_array(op_array, &ctx);
     880             :         } ZEND_HASH_FOREACH_END();
     881             : 
     882         461 :         ZEND_HASH_FOREACH_PTR(&script->class_table, ce) {
     883          25 :                 ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->function_table, name, op_array) {
     884           9 :                         if (op_array->scope == ce) {
     885           9 :                                 zend_optimize_op_array(op_array, &ctx);
     886           0 :                         } else if (op_array->type == ZEND_USER_FUNCTION) {
     887             :                                 zend_op_array *orig_op_array;
     888           0 :                                 if ((orig_op_array = zend_hash_find_ptr(&op_array->scope->function_table, name)) != NULL) {
     889           0 :                                         HashTable *ht = op_array->static_variables;
     890           0 :                                         *op_array = *orig_op_array;
     891           0 :                                         op_array->static_variables = ht;
     892             :                                 }
     893             :                         }
     894             :                 } ZEND_HASH_FOREACH_END();
     895             :         } ZEND_HASH_FOREACH_END();
     896             : 
     897             : #if HAVE_DFA_PASS
     898        1732 :         if ((ZEND_OPTIMIZER_PASS_6 & optimization_level) &&
     899         433 :             (ZEND_OPTIMIZER_PASS_7 & optimization_level) &&
     900         433 :             zend_build_call_graph(&ctx.arena, script, ZEND_RT_CONSTANTS, &call_graph) == SUCCESS) {
     901             :                 /* Optimize using call-graph */
     902         866 :                 void *checkpoint = zend_arena_checkpoint(ctx.arena);
     903             :                 int i;
     904             :                 zend_func_info *func_info;
     905             : 
     906         899 :                 for (i = 0; i < call_graph.op_arrays_count; i++) {
     907         466 :                         zend_revert_pass_two(call_graph.op_arrays[i]);
     908             :                 }
     909             : 
     910         899 :                 for (i = 0; i < call_graph.op_arrays_count; i++) {
     911         466 :                         if (call_graph.op_arrays[i]->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
     912           4 :                                 func_info = ZEND_FUNC_INFO(call_graph.op_arrays[i]);
     913           4 :                                 if (func_info) {
     914           4 :                                         zend_init_func_return_info(call_graph.op_arrays[i], script, &func_info->return_info);
     915             :                                 }
     916             :                         }
     917             :                 }
     918             : 
     919         899 :                 for (i = 0; i < call_graph.op_arrays_count; i++) {
     920         466 :                         func_info = ZEND_FUNC_INFO(call_graph.op_arrays[i]);
     921         466 :                         if (func_info) {
     922         466 :                                 zend_dfa_analyze_op_array(call_graph.op_arrays[i], &ctx, &func_info->ssa, &func_info->flags);
     923             :                         }
     924             :                 }
     925             : 
     926             :                 //TODO: perform inner-script inference???
     927         899 :                 for (i = 0; i < call_graph.op_arrays_count; i++) {
     928         466 :                         func_info = ZEND_FUNC_INFO(call_graph.op_arrays[i]);
     929         466 :                         if (func_info) {
     930         466 :                                 zend_dfa_optimize_op_array(call_graph.op_arrays[i], &ctx, &func_info->ssa);
     931             :                         }
     932             :                 }
     933             : 
     934         433 :                 if (debug_level & ZEND_DUMP_AFTER_PASS_7) {
     935           0 :                         for (i = 0; i < call_graph.op_arrays_count; i++) {
     936           0 :                                 zend_dump_op_array(call_graph.op_arrays[i], 0, "after pass 7", NULL);
     937             :                         }
     938             :                 }
     939             : 
     940         433 :                 if (ZEND_OPTIMIZER_PASS_12 & optimization_level) {
     941         899 :                         for (i = 0; i < call_graph.op_arrays_count; i++) {
     942         466 :                                 zend_adjust_fcall_stack_size_graph(call_graph.op_arrays[i]);
     943             :                         }
     944             :                 }
     945             : 
     946         899 :                 for (i = 0; i < call_graph.op_arrays_count; i++) {
     947         466 :                         func_info = ZEND_FUNC_INFO(call_graph.op_arrays[i]);
     948         721 :                         if (func_info && func_info->ssa.var_info) {
     949         255 :                                 zend_redo_pass_two_ex(call_graph.op_arrays[i], &func_info->ssa);
     950         255 :                                 ZEND_SET_FUNC_INFO(call_graph.op_arrays[i], NULL);
     951             :                         } else {
     952         211 :                                 zend_redo_pass_two(call_graph.op_arrays[i]);
     953             :                         }
     954             :                 }
     955             : 
     956             :                 zend_arena_release(&ctx.arena, checkpoint);
     957             :         } else
     958             : #endif
     959             : 
     960           0 :         if (ZEND_OPTIMIZER_PASS_12 & optimization_level) {
     961           0 :                 zend_adjust_fcall_stack_size(&script->main_op_array, &ctx);
     962             : 
     963           0 :                 ZEND_HASH_FOREACH_PTR(&script->function_table, op_array) {
     964           0 :                         zend_adjust_fcall_stack_size(op_array, &ctx);
     965             :                 } ZEND_HASH_FOREACH_END();
     966             : 
     967           0 :                 ZEND_HASH_FOREACH_PTR(&script->class_table, ce) {
     968           0 :                         ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->function_table, name, op_array) {
     969           0 :                                 if (op_array->scope == ce) {
     970           0 :                                         zend_adjust_fcall_stack_size(op_array, &ctx);
     971           0 :                                 } else if (op_array->type == ZEND_USER_FUNCTION) {
     972             :                                         zend_op_array *orig_op_array;
     973           0 :                                         if ((orig_op_array = zend_hash_find_ptr(&op_array->scope->function_table, name)) != NULL) {
     974           0 :                                                 HashTable *ht = op_array->static_variables;
     975           0 :                                                 *op_array = *orig_op_array;
     976           0 :                                                 op_array->static_variables = ht;
     977             :                                         }
     978             :                                 }
     979             :                         } ZEND_HASH_FOREACH_END();
     980             :                 } ZEND_HASH_FOREACH_END();
     981             :         }
     982             : 
     983         433 :         if (ctx.constants) {
     984           0 :                 zend_hash_destroy(ctx.constants);
     985             :         }
     986         433 :         zend_arena_destroy(ctx.arena);
     987             : 
     988         433 :         return 1;
     989             : }
     990             : 
     991         380 : int zend_optimizer_startup(void)
     992             : {
     993         380 :         return zend_func_info_startup();
     994             : }
     995             : 
     996       23316 : int zend_optimizer_shutdown(void)
     997             : {
     998       23316 :         return zend_func_info_shutdown();
     999             : }
    1000             : 
    1001             : /*
    1002             :  * Local variables:
    1003             :  * tab-width: 4
    1004             :  * c-basic-offset: 4
    1005             :  * indent-tabs-mode: t
    1006             :  * End:
    1007             :  */

Generated by: LCOV version 1.10

Generated at Tue, 26 Jul 2016 17:07:39 +0000 (3 days ago)

Copyright © 2005-2016 The PHP Group
All rights reserved.