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: 120 215 55.8 %
Date: 2014-07-21 Functions: 9 12 75.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend OPcache                                                         |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2014 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             : 
      30             : #define OPTIMIZATION_LEVEL \
      31             :         ZCG(accel_directives).optimization_level
      32             : 
      33           0 : static void zend_optimizer_zval_dtor_wrapper(zval *zvalue)
      34             : {
      35             :         zval_dtor(zvalue);
      36           0 : }
      37             : 
      38           0 : static void zend_optimizer_collect_constant(HashTable **constants, zval *name, zval* value)
      39             : {
      40             :         zval val;
      41             : 
      42           0 :         if (!*constants) {
      43           0 :                 *constants = emalloc(sizeof(HashTable));
      44           0 :                 zend_hash_init(*constants, 16, NULL, (void (*)(void *))zend_optimizer_zval_dtor_wrapper, 0);
      45             :         }
      46           0 :         val = *value;
      47             :         zval_copy_ctor(&val);
      48           0 :         zend_hash_add(*constants, Z_STRVAL_P(name), Z_STRLEN_P(name)+1, (void**)&val, sizeof(zval), NULL);
      49           0 : }
      50             : 
      51           0 : static int zend_optimizer_get_collected_constant(HashTable *constants, zval *name, zval* value)
      52             : {
      53             :         zval *val;
      54             : 
      55           0 :         if (zend_hash_find(constants, Z_STRVAL_P(name), Z_STRLEN_P(name)+1, (void**)&val) == SUCCESS) {
      56           0 :                 *value = *val;
      57             :                 zval_copy_ctor(value);
      58           0 :                 return 1;
      59             :         }
      60           0 :         return 0;
      61             : }
      62             : 
      63             : #if ZEND_EXTENSION_API_NO >= PHP_5_5_X_API_NO
      64          37 : static int zend_optimizer_lookup_cv(zend_op_array *op_array, char* name, int name_len)
      65             : {
      66          37 :         int i = 0;
      67          37 :         ulong hash_value = zend_inline_hash_func(name, name_len+1);
      68             : 
      69         162 :         while (i < op_array->last_var) {
      70         324 :                 if (op_array->vars[i].name == name ||
      71         125 :                     (op_array->vars[i].hash_value == hash_value &&
      72          37 :                      op_array->vars[i].name_len == name_len &&
      73          37 :                      memcmp(op_array->vars[i].name, name, name_len) == 0)) {
      74          37 :                         return i;
      75             :                 }
      76          88 :                 i++;
      77             :         }
      78           0 :         i = op_array->last_var;
      79           0 :         op_array->last_var++;
      80           0 :         op_array->vars = erealloc(op_array->vars, op_array->last_var * sizeof(zend_compiled_variable));
      81           0 :         if (IS_INTERNED(name)) {
      82           0 :                 op_array->vars[i].name = name;
      83             :         } else {
      84           0 :                 op_array->vars[i].name = estrndup(name, name_len);
      85             :         }
      86           0 :         op_array->vars[i].name_len = name_len;
      87           0 :         op_array->vars[i].hash_value = hash_value;
      88           0 :         return i;
      89             : }
      90             : #endif
      91             : 
      92             : #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
      93         540 : int zend_optimizer_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC)
      94             : {
      95         540 :         int i = op_array->last_literal;
      96         540 :         op_array->last_literal++;
      97         540 :         op_array->literals = (zend_literal*)erealloc(op_array->literals, op_array->last_literal * sizeof(zend_literal));
      98         540 :         op_array->literals[i].constant = *zv;
      99         540 :         op_array->literals[i].hash_value = 0;
     100         540 :         op_array->literals[i].cache_slot = -1;
     101         540 :         Z_SET_REFCOUNT(op_array->literals[i].constant, 2);
     102         540 :         Z_SET_ISREF(op_array->literals[i].constant);
     103         540 :         return i;
     104             : }
     105             : 
     106             : # define LITERAL_LONG(op, val) do { \
     107             :                 zval _c; \
     108             :                 ZVAL_LONG(&_c, val); \
     109             :                 op.constant = zend_optimizer_add_literal(op_array, &_c TSRMLS_CC); \
     110             :         } while (0)
     111             : 
     112             : # define LITERAL_BOOL(op, val) do { \
     113             :                 zval _c; \
     114             :                 ZVAL_BOOL(&_c, val); \
     115             :                 op.constant = zend_optimizer_add_literal(op_array, &_c TSRMLS_CC); \
     116             :         } while (0)
     117             : 
     118             : # define literal_dtor(zv) do { \
     119             :                 zval_dtor(zv); \
     120             :                 Z_TYPE_P(zv) = IS_NULL; \
     121             :         } while (0)
     122             : 
     123             : #define COPY_NODE(target, src) do { \
     124             :                 target ## _type = src ## _type; \
     125             :                 target = src; \
     126             :         } while (0)
     127             : 
     128             : #else
     129             : 
     130             : # define LITERAL_LONG(op, val) ZVAL_LONG(&op.u.constant, val)
     131             : 
     132             : # define LITERAL_BOOL(op, val) ZVAL_BOOL(&op.u.constant, val)
     133             : 
     134             : # define literal_dtor(zv) zval_dtor(zv)
     135             : 
     136             : #define COPY_NODE(target, src) do { \
     137             :                 target = src; \
     138             :         } while (0)
     139             : 
     140             : #endif
     141             : 
     142         519 : static void update_op1_const(zend_op_array *op_array,
     143             :                              zend_op       *opline,
     144             :                              zval          *val TSRMLS_DC)
     145             : {
     146         519 :         if (opline->opcode == ZEND_FREE) {
     147           0 :                 MAKE_NOP(opline);
     148             :                 zval_dtor(val);
     149             :         } else {
     150         519 :                 ZEND_OP1_TYPE(opline) = IS_CONST;
     151             : #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
     152         519 :                 if (Z_TYPE_P(val) == IS_STRING) {
     153          33 :                         switch (opline->opcode) {
     154             :                                 case ZEND_INIT_STATIC_METHOD_CALL:
     155             :                                 case ZEND_CATCH:
     156             :                                 case ZEND_FETCH_CONSTANT:
     157           0 :                                         opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
     158           0 :                                         Z_HASH_P(&ZEND_OP1_LITERAL(opline)) = zend_hash_func(Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)) + 1);
     159           0 :                                         op_array->literals[opline->op1.constant].cache_slot = op_array->last_cache_slot++;
     160           0 :                                         zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
     161           0 :                                         zend_optimizer_add_literal(op_array, val TSRMLS_CC);
     162           0 :                                         op_array->literals[opline->op1.constant+1].hash_value = zend_hash_func(Z_STRVAL(op_array->literals[opline->op1.constant+1].constant), Z_STRLEN(op_array->literals[opline->op1.constant+1].constant) + 1);
     163           0 :                                         break;
     164             :                                 case ZEND_DO_FCALL:
     165           0 :                                         zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
     166           0 :                                         opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
     167           0 :                                         Z_HASH_P(&ZEND_OP1_LITERAL(opline)) = zend_hash_func(Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)) + 1);
     168           0 :                                         op_array->literals[opline->op1.constant].cache_slot = op_array->last_cache_slot++;
     169           0 :                                         break;
     170             :                                 default:
     171          33 :                                         opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
     172          33 :                                         Z_HASH_P(&ZEND_OP1_LITERAL(opline)) = zend_hash_func(Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)) + 1);
     173             :                                         break;
     174             :                         }
     175             :                 } else {
     176         486 :                         opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
     177             :                 }
     178             : #else
     179             :                 ZEND_OP1_LITERAL(opline) = *val;
     180             : #endif
     181             :         }
     182         519 : }
     183             : 
     184          19 : static void update_op2_const(zend_op_array *op_array,
     185             :                              zend_op       *opline,
     186             :                              zval          *val TSRMLS_DC)
     187             : {
     188          19 :         ZEND_OP2_TYPE(opline) = IS_CONST;
     189             : #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
     190          19 :         opline->op2.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
     191          19 :         if (Z_TYPE_P(val) == IS_STRING) {
     192           8 :                 Z_HASH_P(&ZEND_OP2_LITERAL(opline)) = zend_hash_func(Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)) + 1);
     193           8 :                 switch (opline->opcode) {
     194             :                         case ZEND_FETCH_R:
     195             :                         case ZEND_FETCH_W:
     196             :                         case ZEND_FETCH_RW:
     197             :                         case ZEND_FETCH_IS:
     198             :                         case ZEND_FETCH_UNSET:
     199             :                         case ZEND_FETCH_FUNC_ARG:
     200             :                         case ZEND_FETCH_CLASS:
     201             :                         case ZEND_INIT_FCALL_BY_NAME:
     202             :                         /*case ZEND_INIT_NS_FCALL_BY_NAME:*/
     203             :                         case ZEND_UNSET_VAR:
     204             :                         case ZEND_ISSET_ISEMPTY_VAR:
     205             :                         case ZEND_ADD_INTERFACE:
     206             :                         case ZEND_ADD_TRAIT:
     207           0 :                                 op_array->literals[opline->op2.constant].cache_slot = op_array->last_cache_slot++;
     208           0 :                                 zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
     209           0 :                                 zend_optimizer_add_literal(op_array, val TSRMLS_CC);
     210           0 :                                 op_array->literals[opline->op2.constant+1].hash_value = zend_hash_func(Z_STRVAL(op_array->literals[opline->op2.constant+1].constant), Z_STRLEN(op_array->literals[opline->op2.constant+1].constant) + 1);
     211           0 :                                 break;
     212             :                         case ZEND_INIT_METHOD_CALL:
     213             :                         case ZEND_INIT_STATIC_METHOD_CALL:
     214           0 :                                 zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
     215           0 :                                 zend_optimizer_add_literal(op_array, val TSRMLS_CC);
     216           0 :                                 op_array->literals[opline->op2.constant+1].hash_value = zend_hash_func(Z_STRVAL(op_array->literals[opline->op2.constant+1].constant), Z_STRLEN(op_array->literals[opline->op2.constant+1].constant) + 1);
     217             :                                 /* break missing intentionally */                                               
     218             :                         /*case ZEND_FETCH_CONSTANT:*/
     219             :                         case ZEND_ASSIGN_OBJ:
     220             :                         case ZEND_FETCH_OBJ_R:
     221             :                         case ZEND_FETCH_OBJ_W:
     222             :                         case ZEND_FETCH_OBJ_RW:
     223             :                         case ZEND_FETCH_OBJ_IS:
     224             :                         case ZEND_FETCH_OBJ_UNSET:
     225             :                         case ZEND_FETCH_OBJ_FUNC_ARG:
     226             :                         case ZEND_UNSET_OBJ:
     227             :                         case ZEND_PRE_INC_OBJ:
     228             :                         case ZEND_PRE_DEC_OBJ:
     229             :                         case ZEND_POST_INC_OBJ:
     230             :                         case ZEND_POST_DEC_OBJ:
     231             :                         case ZEND_ISSET_ISEMPTY_PROP_OBJ:
     232           0 :                                 op_array->literals[opline->op2.constant].cache_slot = op_array->last_cache_slot;
     233           0 :                                 op_array->last_cache_slot += 2;
     234           0 :                                 break;
     235             :                         case ZEND_ASSIGN_ADD:
     236             :                         case ZEND_ASSIGN_SUB:
     237             :                         case ZEND_ASSIGN_MUL:
     238             :                         case ZEND_ASSIGN_DIV:
     239             :                         case ZEND_ASSIGN_MOD:
     240             :                         case ZEND_ASSIGN_SL:
     241             :                         case ZEND_ASSIGN_SR:
     242             :                         case ZEND_ASSIGN_CONCAT:
     243             :                         case ZEND_ASSIGN_BW_OR:
     244             :                         case ZEND_ASSIGN_BW_AND:
     245             :                         case ZEND_ASSIGN_BW_XOR:
     246           0 :                                 if (opline->extended_value == ZEND_ASSIGN_OBJ) {
     247           0 :                                         op_array->literals[opline->op2.constant].cache_slot = op_array->last_cache_slot;
     248           0 :                                         op_array->last_cache_slot += 2;
     249             :                                 }
     250           0 :                                 break;
     251             : #if ZEND_EXTENSION_API_NO >= PHP_5_4_X_API_NO
     252             :                         case ZEND_OP_DATA:
     253           0 :                                 if ((opline-1)->opcode == ZEND_ASSIGN_DIM ||
     254           0 :                                     ((opline-1)->extended_value == ZEND_ASSIGN_DIM &&
     255           0 :                                      ((opline-1)->opcode == ZEND_ASSIGN_ADD ||
     256           0 :                                      (opline-1)->opcode == ZEND_ASSIGN_SUB ||
     257           0 :                                      (opline-1)->opcode == ZEND_ASSIGN_MUL ||
     258           0 :                                      (opline-1)->opcode == ZEND_ASSIGN_DIV ||
     259           0 :                                      (opline-1)->opcode == ZEND_ASSIGN_MOD ||
     260           0 :                                      (opline-1)->opcode == ZEND_ASSIGN_SL ||
     261           0 :                                      (opline-1)->opcode == ZEND_ASSIGN_SR ||
     262           0 :                                      (opline-1)->opcode == ZEND_ASSIGN_CONCAT ||
     263           0 :                                      (opline-1)->opcode == ZEND_ASSIGN_BW_OR ||
     264           0 :                                      (opline-1)->opcode == ZEND_ASSIGN_BW_AND ||
     265           0 :                                      (opline-1)->opcode == ZEND_ASSIGN_BW_XOR))) {
     266             :                                         goto check_numeric;
     267             :                                 }
     268           0 :                                 break;
     269             :                         case ZEND_ISSET_ISEMPTY_DIM_OBJ:
     270             :                         case ZEND_ADD_ARRAY_ELEMENT:
     271             :                         case ZEND_INIT_ARRAY:
     272             :                         case ZEND_UNSET_DIM:
     273             :                         case ZEND_FETCH_DIM_R:
     274             :                         case ZEND_FETCH_DIM_W:
     275             :                         case ZEND_FETCH_DIM_RW:
     276             :                         case ZEND_FETCH_DIM_IS:
     277             :                         case ZEND_FETCH_DIM_FUNC_ARG:
     278             :                         case ZEND_FETCH_DIM_UNSET:
     279             :                         case ZEND_FETCH_DIM_TMP_VAR:
     280             : check_numeric:
     281             :                                 {
     282             :                                         ulong index;
     283           0 :                                         int numeric = 0;
     284             : 
     285           0 :                                         ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(val), Z_STRLEN_P(val)+1, index, numeric = 1);
     286           0 :                                         if (numeric) {
     287             :                                                 zval_dtor(val);
     288           0 :                                                 ZVAL_LONG(val, index);
     289           0 :                                                 op_array->literals[opline->op2.constant].constant = *val;
     290             :                                 }
     291             :                                 }
     292             :                                 break;
     293             : #endif
     294             :                         default:
     295             :                                 break;
     296             :                 }
     297             :         }
     298             : #else
     299             :         ZEND_OP2_LITERAL(opline) = *val;
     300             : #endif
     301          19 : }
     302             : 
     303         180 : static int replace_var_by_const(zend_op_array *op_array,
     304             :                                 zend_op       *opline,
     305             :                                 zend_uint      var,
     306             :                                 zval          *val TSRMLS_DC)
     307             : {
     308         180 :         zend_op *end = op_array->opcodes + op_array->last;
     309             : 
     310         360 :         while (opline < end) {
     311         360 :                 if (ZEND_OP1_TYPE(opline) == IS_VAR &&
     312         180 :                         ZEND_OP1(opline).var == var) {
     313         180 :                         switch (opline->opcode) {
     314             :                                 case ZEND_FETCH_DIM_W:
     315             :                                 case ZEND_FETCH_DIM_RW:
     316             :                                 case ZEND_FETCH_DIM_FUNC_ARG:
     317             :                                 case ZEND_FETCH_DIM_UNSET:
     318             :                                 case ZEND_ASSIGN_DIM:
     319             : #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
     320             :                                 case ZEND_SEPARATE:
     321             : #endif
     322           0 :                                         return 0;
     323             :                                 case ZEND_SEND_VAR_NO_REF:
     324           0 :                                         if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) {
     325           0 :                                                 if (opline->extended_value & ZEND_ARG_SEND_BY_REF) {
     326           0 :                                                         return 0;
     327             :                                                 }
     328           0 :                                                 opline->extended_value = ZEND_DO_FCALL;
     329             :                                         } else {
     330           0 :                                                 opline->extended_value = ZEND_DO_FCALL_BY_NAME;
     331             :                                         }
     332           0 :                                         opline->opcode = ZEND_SEND_VAL;
     333             :                                         break;
     334             :                                 default:
     335             :                                         break;
     336             :                         } 
     337         180 :                         update_op1_const(op_array, opline, val TSRMLS_CC);
     338         180 :                         break;
     339             :                 }
     340             :                 
     341           0 :                 if (ZEND_OP2_TYPE(opline) == IS_VAR &&
     342           0 :                         ZEND_OP2(opline).var == var) {
     343           0 :                         switch (opline->opcode) {
     344             :                                 case ZEND_ASSIGN_REF:
     345           0 :                                         return 0;
     346             :                                 default:
     347             :                                         break;
     348             :                         }
     349           0 :                         update_op2_const(op_array, opline, val TSRMLS_CC);
     350           0 :                         break;
     351             :                 }
     352           0 :                 opline++;
     353             :         }
     354             : 
     355         180 :         return 1;
     356             : }
     357             : 
     358         359 : static void replace_tmp_by_const(zend_op_array *op_array,
     359             :                                  zend_op       *opline,
     360             :                                  zend_uint      var,
     361             :                                  zval          *val
     362             :                                  TSRMLS_DC)
     363             : {
     364         359 :         zend_op *end = op_array->opcodes + op_array->last;
     365             : 
     366         889 :         while (opline < end) {
     367         870 :                 if (ZEND_OP1_TYPE(opline) == IS_TMP_VAR &&
     368         340 :                         ZEND_OP1(opline).var == var) {
     369             : 
     370             :                         /* In most cases IS_TMP_VAR operand may be used only once.
     371             :                          * The operands are usually destroyed by the opcode handler.
     372             :                          * ZEND_CASE is an exception, that keeps operand unchanged,
     373             :                          * and allows its reuse. The number of ZEND_CASE instructions
     374             :                          * usually terminated by ZEND_FREE that finally kills the value.
     375             :                          */
     376         340 :                         if (opline->opcode == ZEND_CASE) {
     377             :                                 zval old_val;
     378           0 :                                 old_val = *val;
     379             :                                 zval_copy_ctor(val);
     380           0 :                                 update_op1_const(op_array, opline, val TSRMLS_CC);
     381           0 :                                 *val = old_val;
     382         340 :                         } else if (opline->opcode == ZEND_FREE) {
     383           1 :                                 MAKE_NOP(opline);
     384           1 :                                 break;
     385             :                         } else {                                
     386         339 :                                 update_op1_const(op_array, opline, val TSRMLS_CC);
     387         339 :                                 val = NULL;
     388         339 :                                 break;
     389             :                         }
     390             :                 }
     391             : 
     392         209 :                 if (ZEND_OP2_TYPE(opline) == IS_TMP_VAR &&
     393          19 :                         ZEND_OP2(opline).var == var) {
     394             : 
     395          19 :                         update_op2_const(op_array, opline, val TSRMLS_CC);
     396             :                         /* TMP_VAR may be used only once */
     397          19 :                         val = NULL;
     398          19 :                         break;
     399             :                 }
     400         171 :                 opline++;
     401             :         }
     402         359 :         if (val) {
     403             :                 zval_dtor(val);
     404             :         }
     405         359 : }
     406             : 
     407             : #include "Optimizer/nop_removal.c"
     408             : #include "Optimizer/block_pass.c"
     409             : #include "Optimizer/optimize_temp_vars_5.c"
     410             : #include "Optimizer/compact_literals.c"
     411             : #include "Optimizer/optimize_func_calls.c"
     412             : 
     413         451 : static void zend_optimize(zend_op_array           *op_array,
     414             :                           zend_persistent_script  *script,
     415             :                           HashTable              **constants TSRMLS_DC)
     416             : {
     417         902 :         if (op_array->type == ZEND_EVAL_CODE ||
     418         451 :             (op_array->fn_flags & ZEND_ACC_INTERACTIVE)) {
     419           0 :                 return;
     420             :         }
     421             : 
     422             :         /* pass 1
     423             :          * - substitute persistent constants (true, false, null, etc)
     424             :          * - perform compile-time evaluation of constant binary and unary operations
     425             :          * - optimize series of ADD_STRING and/or ADD_CHAR
     426             :          * - convert CAST(IS_BOOL,x) into BOOL(x)
     427             :          */
     428             : #include "Optimizer/pass1_5.c"
     429             : 
     430             :         /* pass 2:
     431             :          * - convert non-numeric constants to numeric constants in numeric operators
     432             :          * - optimize constant conditional JMPs
     433             :          * - optimize static BRKs and CONTs
     434             :          * - pre-evaluate constant function calls
     435             :          */
     436             : #include "Optimizer/pass2.c"
     437             : 
     438             :         /* pass 3:
     439             :          * - optimize $i = $i+expr to $i+=expr
     440             :          * - optimize series of JMPs
     441             :          * - change $i++ to ++$i where possible
     442             :          */
     443             : #include "Optimizer/pass3.c"
     444             : 
     445             : #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
     446             :         /* pass 4:
     447             :          * - INIT_FCALL_BY_NAME -> DO_FCALL
     448             :          */
     449         451 :         if (ZEND_OPTIMIZER_PASS_4 & OPTIMIZATION_LEVEL) {
     450         451 :                 optimize_func_calls(op_array, script TSRMLS_CC);
     451             :         }
     452             : #endif
     453             : 
     454             :         /* pass 5:
     455             :          * - CFG optimization
     456             :          */
     457             : #include "Optimizer/pass5.c"
     458             : 
     459             :         /* pass 9:
     460             :          * - Optimize temp variables usage
     461             :          */
     462             : #include "Optimizer/pass9.c"
     463             : 
     464             :         /* pass 10:
     465             :          * - remove NOPs
     466             :          */
     467             : #include "Optimizer/pass10.c"
     468             : 
     469             : #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
     470             :         /* pass 11:
     471             :          * - Compact literals table 
     472             :          */
     473         451 :         if (ZEND_OPTIMIZER_PASS_11 & OPTIMIZATION_LEVEL) {
     474         451 :                 optimizer_compact_literals(op_array TSRMLS_CC);
     475             :         }
     476             : #endif
     477             : }
     478             : 
     479         451 : static void zend_accel_optimize(zend_op_array           *op_array,
     480             :                                 zend_persistent_script  *script,
     481             :                                 HashTable              **constants TSRMLS_DC)
     482             : {
     483             :         zend_op *opline, *end;
     484             : 
     485             :         /* Revert pass_two() */
     486         451 :         opline = op_array->opcodes;
     487         451 :         end = opline + op_array->last;
     488        7766 :         while (opline < end) {
     489             : #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
     490        6864 :                 if (opline->op1_type == IS_CONST) {
     491        3560 :                         opline->op1.constant = opline->op1.literal - op_array->literals;
     492             :                 }
     493        6864 :                 if (opline->op2_type == IS_CONST) {
     494         839 :                         opline->op2.constant = opline->op2.literal - op_array->literals;
     495             :                 }
     496             : #endif
     497        6864 :                 switch (opline->opcode) {
     498             :                         case ZEND_JMP:
     499             : #if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO
     500             :                         case ZEND_GOTO:
     501             : #endif
     502             : #if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
     503             :                         case ZEND_FAST_CALL:
     504             : #endif
     505         350 :                                 ZEND_OP1(opline).opline_num = ZEND_OP1(opline).jmp_addr - op_array->opcodes;
     506         350 :                                 break;
     507             :                         case ZEND_JMPZ:
     508             :                         case ZEND_JMPNZ:
     509             :                         case ZEND_JMPZ_EX:
     510             :                         case ZEND_JMPNZ_EX:
     511             : #if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO
     512             :                         case ZEND_JMP_SET:
     513             : #endif
     514             : #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
     515             :                         case ZEND_JMP_SET_VAR:
     516             : #endif
     517         386 :                                 ZEND_OP2(opline).opline_num = ZEND_OP2(opline).jmp_addr - op_array->opcodes;
     518             :                                 break;
     519             :                 }
     520        6864 :                 opline++;
     521             :         }
     522             : 
     523             :         /* Do actual optimizations */
     524         451 :         zend_optimize(op_array, script, constants TSRMLS_CC);   
     525             :         
     526             :         /* Redo pass_two() */
     527         451 :         opline = op_array->opcodes;
     528         451 :         end = opline + op_array->last;
     529        5920 :         while (opline < end) {
     530             : #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
     531        5018 :                 if (opline->op1_type == IS_CONST) {
     532        2950 :                         opline->op1.zv = &op_array->literals[opline->op1.constant].constant;
     533             :                 }
     534        5018 :                 if (opline->op2_type == IS_CONST) {
     535         630 :                         opline->op2.zv = &op_array->literals[opline->op2.constant].constant;
     536             :                 }
     537             : #endif
     538        5018 :                 switch (opline->opcode) {
     539             :                         case ZEND_JMP:
     540             : #if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO
     541             :                         case ZEND_GOTO:
     542             : #endif
     543             : #if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
     544             :                         case ZEND_FAST_CALL:
     545             : #endif
     546          24 :                                 ZEND_OP1(opline).jmp_addr = &op_array->opcodes[ZEND_OP1(opline).opline_num];
     547          24 :                                 break;
     548             :                         case ZEND_JMPZ:
     549             :                         case ZEND_JMPNZ:
     550             :                         case ZEND_JMPZ_EX:
     551             :                         case ZEND_JMPNZ_EX:
     552             : #if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO
     553             :                         case ZEND_JMP_SET:
     554             : #endif
     555             : #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
     556             :                         case ZEND_JMP_SET_VAR:
     557             : #endif
     558         180 :                                 ZEND_OP2(opline).jmp_addr = &op_array->opcodes[ZEND_OP2(opline).opline_num];
     559             :                                 break;
     560             :                 }
     561        5018 :                 ZEND_VM_SET_OPCODE_HANDLER(opline);
     562        5018 :                 opline++;
     563             :         }
     564         451 : }
     565             : 
     566         422 : int zend_accel_script_optimize(zend_persistent_script *script TSRMLS_DC)
     567             : {
     568             :         Bucket *p, *q;
     569         422 :         HashTable *constants = NULL;
     570             : 
     571         422 :         zend_accel_optimize(&script->main_op_array, script, &constants TSRMLS_CC);
     572             : 
     573         422 :         p = script->function_table.pListHead;
     574         868 :         while (p) {
     575          24 :                 zend_op_array *op_array = (zend_op_array*)p->pData;
     576          24 :                 zend_accel_optimize(op_array, script, &constants TSRMLS_CC);
     577          24 :                 p = p->pListNext;
     578             :         }
     579             : 
     580         422 :         p = script->class_table.pListHead;
     581         845 :         while (p) {
     582           1 :                 zend_class_entry *ce = (zend_class_entry*)p->pDataPtr;
     583           1 :                 q = ce->function_table.pListHead;
     584           7 :                 while (q) {
     585           5 :                         zend_op_array *op_array = (zend_op_array*)q->pData;
     586           5 :                         if (op_array->scope == ce) {
     587           5 :                                 zend_accel_optimize(op_array, script, &constants TSRMLS_CC);
     588           0 :                         } else if (op_array->type == ZEND_USER_FUNCTION) {
     589             :                                 zend_op_array *orig_op_array;
     590           0 :                                 if (zend_hash_find(&op_array->scope->function_table, q->arKey, q->nKeyLength, (void**)&orig_op_array) == SUCCESS) {
     591           0 :                                         HashTable *ht = op_array->static_variables;
     592           0 :                                         *op_array = *orig_op_array;
     593           0 :                                         op_array->static_variables = ht;
     594             :                                 }
     595             :                         }
     596           5 :                         q = q->pListNext;
     597             :                 }
     598           1 :                 p = p->pListNext;
     599             :         }
     600             : 
     601         422 :         if (constants) {
     602           0 :                 zend_hash_destroy(constants);
     603           0 :                 efree(constants);
     604             :         }
     605             : 
     606         422 :         return 1;
     607             : }

Generated by: LCOV version 1.10

Generated at Tue, 22 Jul 2014 01:33:14 +0000 (10 days ago)

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