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: 106 226 46.9 %
Date: 2014-12-13 Functions: 7 11 63.6 %
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           0 : static void zend_optimizer_zval_dtor_wrapper(zval *zvalue)
      31             : {
      32             :         zval_dtor(zvalue);
      33           0 : }
      34             : 
      35           0 : void zend_optimizer_collect_constant(zend_optimizer_ctx *ctx, zval *name, zval* value)
      36             : {
      37             :         zval val;
      38             : 
      39           0 :         if (!ctx->constants) {
      40           0 :                 ctx->constants = zend_arena_alloc(&ctx->arena, sizeof(HashTable));
      41           0 :                 zend_hash_init(ctx->constants, 16, NULL, zend_optimizer_zval_dtor_wrapper, 0);
      42             :         }
      43           0 :         ZVAL_DUP(&val, value);
      44           0 :         zend_hash_add(ctx->constants, Z_STR_P(name), &val);
      45           0 : }
      46             : 
      47           0 : int zend_optimizer_get_collected_constant(HashTable *constants, zval *name, zval* value)
      48             : {
      49             :         zval *val;
      50             : 
      51           0 :         if ((val = zend_hash_find(constants, Z_STR_P(name))) != NULL) {
      52           0 :                 ZVAL_DUP(value, val);
      53           0 :                 return 1;
      54             :         }
      55           0 :         return 0;
      56             : }
      57             : 
      58           0 : int zend_optimizer_lookup_cv(zend_op_array *op_array, zend_string* name)
      59             : {
      60           0 :         int i = 0;
      61           0 :         zend_ulong hash_value = zend_string_hash_val(name);
      62             : 
      63           0 :         while (i < op_array->last_var) {
      64           0 :                 if (op_array->vars[i] == name ||
      65           0 :                     (op_array->vars[i]->h == hash_value &&
      66           0 :                      op_array->vars[i]->len == name->len &&
      67           0 :                      memcmp(op_array->vars[i]->val, name->val, name->len) == 0)) {
      68           0 :                         return (int)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, i);
      69             :                 }
      70           0 :                 i++;
      71             :         }
      72           0 :         i = op_array->last_var;
      73           0 :         op_array->last_var++;
      74           0 :         op_array->vars = erealloc(op_array->vars, op_array->last_var * sizeof(zend_string*));
      75           0 :         op_array->vars[i] = zend_string_dup(name, 0);
      76             : 
      77             :         /* all IS_TMP_VAR and IS_VAR variable numbers have to be adjusted */
      78             :         {
      79           0 :                 zend_op *opline = op_array->opcodes;
      80           0 :                 zend_op *end = opline + op_array->last;
      81           0 :                 while (opline < end) {
      82           0 :                         if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
      83           0 :                                 opline->op1.var += sizeof(zval);
      84             :                         }
      85           0 :                         if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) {
      86           0 :                                 opline->op2.var += sizeof(zval);
      87             :                         }
      88           0 :                         if (opline->result_type & (IS_TMP_VAR|IS_VAR)) {
      89           0 :                                 opline->result.var += sizeof(zval);
      90             :                         }
      91           0 :                         if (opline->opcode == ZEND_DECLARE_INHERITED_CLASS ||
      92           0 :                             opline->opcode == ZEND_DECLARE_INHERITED_CLASS_DELAYED) {
      93           0 :                                 opline->extended_value += sizeof(zval);
      94             :                         }
      95           0 :                         opline++;
      96             :                 }
      97             :         }
      98             :         
      99           0 :         return (int)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, i);
     100             : }
     101             : 
     102         541 : int zend_optimizer_add_literal(zend_op_array *op_array, zval *zv TSRMLS_DC)
     103             : {
     104         541 :         int i = op_array->last_literal;
     105         541 :         op_array->last_literal++;
     106         541 :         op_array->literals = (zval*)erealloc(op_array->literals, op_array->last_literal * sizeof(zval));
     107         541 :         ZVAL_COPY_VALUE(&op_array->literals[i], zv);
     108         541 :         Z_CACHE_SLOT(op_array->literals[i]) = -1;
     109             : //???   Z_SET_REFCOUNT(op_array->literals[i].constant, 2);
     110             : //???   Z_SET_ISREF(op_array->literals[i].constant);
     111         541 :         return i;
     112             : }
     113             : 
     114         524 : void zend_optimizer_update_op1_const(zend_op_array *op_array,
     115             :                                      zend_op       *opline,
     116             :                                      zval          *val TSRMLS_DC)
     117             : {
     118         524 :         if (opline->opcode == ZEND_FREE) {
     119           0 :                 MAKE_NOP(opline);
     120             :                 zval_dtor(val);
     121             :         } else {
     122         524 :                 ZEND_OP1_TYPE(opline) = IS_CONST;
     123         524 :                 if (Z_TYPE_P(val) == IS_STRING) {
     124          38 :                         switch (opline->opcode) {
     125             :                                 case ZEND_INIT_STATIC_METHOD_CALL:
     126             :                                 case ZEND_CATCH:
     127             :                                 case ZEND_FETCH_CONSTANT:
     128             :                                 case ZEND_DEFINED:
     129             :                                 case ZEND_NEW:
     130           0 :                                         opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
     131           0 :                                         zend_string_hash_val(Z_STR(ZEND_OP1_LITERAL(opline)));
     132           0 :                                         Z_CACHE_SLOT(op_array->literals[opline->op1.constant]) = op_array->last_cache_slot++;
     133           0 :                                         zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
     134           0 :                                         zend_optimizer_add_literal(op_array, val TSRMLS_CC);
     135           0 :                                         zend_string_hash_val(Z_STR(op_array->literals[opline->op1.constant+1]));
     136           0 :                                         break;
     137             :                                 default:
     138          38 :                                         opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
     139          38 :                                         zend_string_hash_val(Z_STR(ZEND_OP1_LITERAL(opline)));
     140             :                                         break;
     141             :                         }
     142             :                 } else {
     143         486 :                         opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
     144             :                 }
     145             :         }
     146         524 : }
     147             : 
     148          15 : void zend_optimizer_update_op2_const(zend_op_array *op_array,
     149             :                                      zend_op       *opline,
     150             :                                      zval          *val TSRMLS_DC)
     151             : {
     152          15 :         ZEND_OP2_TYPE(opline) = IS_CONST;
     153          15 :         if (opline->opcode == ZEND_INIT_FCALL) {
     154           0 :                 zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
     155           0 :                 opline->op2.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
     156           0 :                 zend_string_hash_val(Z_STR(ZEND_OP2_LITERAL(opline)));
     157           0 :                 Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = op_array->last_cache_slot++;
     158           0 :                 return;
     159             :         }
     160          15 :         opline->op2.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
     161          15 :         if (Z_TYPE_P(val) == IS_STRING) {
     162           4 :                 zend_string_hash_val(Z_STR(ZEND_OP2_LITERAL(opline)));
     163           4 :                 switch (opline->opcode) {
     164             :                         case ZEND_FETCH_R:
     165             :                         case ZEND_FETCH_W:
     166             :                         case ZEND_FETCH_RW:
     167             :                         case ZEND_FETCH_IS:
     168             :                         case ZEND_FETCH_UNSET:
     169             :                         case ZEND_FETCH_FUNC_ARG:
     170             :                         case ZEND_FETCH_CLASS:
     171             :                         case ZEND_INIT_FCALL_BY_NAME:
     172             :                         /*case ZEND_INIT_NS_FCALL_BY_NAME:*/
     173             :                         case ZEND_UNSET_VAR:
     174             :                         case ZEND_ISSET_ISEMPTY_VAR:
     175             :                         case ZEND_ADD_INTERFACE:
     176             :                         case ZEND_ADD_TRAIT:
     177             :                         case ZEND_INSTANCEOF:
     178           0 :                                 Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = op_array->last_cache_slot++;
     179           0 :                                 zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
     180           0 :                                 zend_optimizer_add_literal(op_array, val TSRMLS_CC);
     181           0 :                                 zend_string_hash_val(Z_STR(op_array->literals[opline->op2.constant+1]));
     182           0 :                                 break;
     183             :                         case ZEND_INIT_METHOD_CALL:
     184             :                         case ZEND_INIT_STATIC_METHOD_CALL:
     185           0 :                                 zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
     186           0 :                                 zend_optimizer_add_literal(op_array, val TSRMLS_CC);
     187           0 :                                 zend_string_hash_val(Z_STR(op_array->literals[opline->op2.constant+1]));
     188             :                                 /* break missing intentionally */                                               
     189             :                         /*case ZEND_FETCH_CONSTANT:*/
     190             :                         case ZEND_ASSIGN_OBJ:
     191             :                         case ZEND_FETCH_OBJ_R:
     192             :                         case ZEND_FETCH_OBJ_W:
     193             :                         case ZEND_FETCH_OBJ_RW:
     194             :                         case ZEND_FETCH_OBJ_IS:
     195             :                         case ZEND_FETCH_OBJ_UNSET:
     196             :                         case ZEND_FETCH_OBJ_FUNC_ARG:
     197             :                         case ZEND_UNSET_OBJ:
     198             :                         case ZEND_PRE_INC_OBJ:
     199             :                         case ZEND_PRE_DEC_OBJ:
     200             :                         case ZEND_POST_INC_OBJ:
     201             :                         case ZEND_POST_DEC_OBJ:
     202             :                         case ZEND_ISSET_ISEMPTY_PROP_OBJ:
     203           0 :                                 Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = op_array->last_cache_slot;
     204           0 :                                 op_array->last_cache_slot += 2;
     205           0 :                                 break;
     206             :                         case ZEND_ASSIGN_ADD:
     207             :                         case ZEND_ASSIGN_SUB:
     208             :                         case ZEND_ASSIGN_MUL:
     209             :                         case ZEND_ASSIGN_DIV:
     210             :                         case ZEND_ASSIGN_MOD:
     211             :                         case ZEND_ASSIGN_SL:
     212             :                         case ZEND_ASSIGN_SR:
     213             :                         case ZEND_ASSIGN_CONCAT:
     214             :                         case ZEND_ASSIGN_BW_OR:
     215             :                         case ZEND_ASSIGN_BW_AND:
     216             :                         case ZEND_ASSIGN_BW_XOR:
     217           0 :                                 if (opline->extended_value == ZEND_ASSIGN_OBJ) {
     218           0 :                                         Z_CACHE_SLOT(op_array->literals[opline->op2.constant]) = op_array->last_cache_slot;
     219           0 :                                         op_array->last_cache_slot += 2;
     220             :                                 }
     221           0 :                                 break;
     222             :                         case ZEND_OP_DATA:
     223           0 :                                 if ((opline-1)->opcode == ZEND_ASSIGN_DIM ||
     224           0 :                                     ((opline-1)->extended_value == ZEND_ASSIGN_DIM &&
     225           0 :                                      ((opline-1)->opcode == ZEND_ASSIGN_ADD ||
     226           0 :                                      (opline-1)->opcode == ZEND_ASSIGN_SUB ||
     227           0 :                                      (opline-1)->opcode == ZEND_ASSIGN_MUL ||
     228           0 :                                      (opline-1)->opcode == ZEND_ASSIGN_DIV ||
     229           0 :                                      (opline-1)->opcode == ZEND_ASSIGN_MOD ||
     230           0 :                                      (opline-1)->opcode == ZEND_ASSIGN_SL ||
     231           0 :                                      (opline-1)->opcode == ZEND_ASSIGN_SR ||
     232           0 :                                      (opline-1)->opcode == ZEND_ASSIGN_CONCAT ||
     233           0 :                                      (opline-1)->opcode == ZEND_ASSIGN_BW_OR ||
     234           0 :                                      (opline-1)->opcode == ZEND_ASSIGN_BW_AND ||
     235           0 :                                      (opline-1)->opcode == ZEND_ASSIGN_BW_XOR))) {
     236             :                                         goto check_numeric;
     237             :                                 }
     238           0 :                                 break;
     239             :                         case ZEND_ISSET_ISEMPTY_DIM_OBJ:
     240             :                         case ZEND_ADD_ARRAY_ELEMENT:
     241             :                         case ZEND_INIT_ARRAY:
     242             :                         case ZEND_UNSET_DIM:
     243             :                         case ZEND_FETCH_DIM_R:
     244             :                         case ZEND_FETCH_DIM_W:
     245             :                         case ZEND_FETCH_DIM_RW:
     246             :                         case ZEND_FETCH_DIM_IS:
     247             :                         case ZEND_FETCH_DIM_FUNC_ARG:
     248             :                         case ZEND_FETCH_DIM_UNSET:
     249             :                         case ZEND_FETCH_LIST:
     250             : check_numeric:
     251             :                                 {
     252             :                                         zend_ulong index;
     253             : 
     254           0 :                                         if (ZEND_HANDLE_NUMERIC(Z_STR_P(val), index)) {
     255             :                                                 zval_dtor(val);
     256           0 :                                                 ZVAL_LONG(val, index);
     257           0 :                                                 op_array->literals[opline->op2.constant] = *val;
     258             :                                 }
     259             :                                 }
     260             :                                 break;
     261             :                         default:
     262             :                                 break;
     263             :                 }
     264             :         }
     265             : }
     266             : 
     267         539 : int zend_optimizer_replace_by_const(zend_op_array *op_array,
     268             :                                     zend_op       *opline,
     269             :                                     zend_uchar     type,
     270             :                                     uint32_t       var,
     271             :                                     zval          *val TSRMLS_DC)
     272             : {
     273         539 :         zend_op *end = op_array->opcodes + op_array->last;
     274             : 
     275        1244 :         while (opline < end) {
     276        1229 :                 if (ZEND_OP1_TYPE(opline) == type &&
     277         524 :                         ZEND_OP1(opline).var == var) {
     278         524 :                         switch (opline->opcode) {
     279             :                                 case ZEND_FETCH_DIM_W:
     280             :                                 case ZEND_FETCH_DIM_RW:
     281             :                                 case ZEND_FETCH_DIM_FUNC_ARG:
     282             :                                 case ZEND_FETCH_DIM_UNSET:
     283             :                                 case ZEND_ASSIGN_DIM:
     284             :                                 case ZEND_SEPARATE:
     285           0 :                                         return 0;
     286             :                                 case ZEND_SEND_VAR:
     287           0 :                                         opline->extended_value = 0;
     288           0 :                                         opline->opcode = ZEND_SEND_VAL;
     289           0 :                                         break;
     290             :                                 case ZEND_SEND_VAR_EX:
     291           0 :                                         opline->extended_value = 0;
     292           0 :                                         opline->opcode = ZEND_SEND_VAL_EX;
     293           0 :                                         break;
     294             :                                 case ZEND_SEND_VAR_NO_REF:
     295           0 :                                         if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) {
     296           0 :                                                 if (opline->extended_value & ZEND_ARG_SEND_BY_REF) {
     297           0 :                                                         return 0;
     298             :                                                 }
     299           0 :                                                 opline->extended_value = 0;
     300           0 :                                                 opline->opcode = ZEND_SEND_VAL_EX;
     301             :                                         } else {
     302           0 :                                                 opline->extended_value = 0;
     303           0 :                                                 opline->opcode = ZEND_SEND_VAL;
     304             :                                         }
     305           0 :                                         break;
     306             :                                 /* In most cases IS_TMP_VAR operand may be used only once.
     307             :                                  * The operands are usually destroyed by the opcode handler.
     308             :                                  * ZEND_CASE is an exception, that keeps operand unchanged,
     309             :                                  * and allows its reuse. The number of ZEND_CASE instructions
     310             :                                  * usually terminated by ZEND_FREE that finally kills the value.
     311             :                                  */
     312             :                                 case ZEND_CASE: {
     313             :                                         zval old_val;
     314           0 :                                         ZVAL_COPY_VALUE(&old_val, val);
     315             :                                         zval_copy_ctor(val);
     316           0 :                                         zend_optimizer_update_op1_const(op_array, opline, val TSRMLS_CC);
     317           0 :                                         ZVAL_COPY_VALUE(val, &old_val);
     318           0 :                                         opline++;
     319           0 :                                         continue;
     320             :                                 }
     321             :                                 case ZEND_FREE:
     322           0 :                                         MAKE_NOP(opline);
     323             :                                         zval_dtor(val);
     324           0 :                                         return 1;
     325             :                                 default:
     326             :                                         break;
     327             :                         } 
     328         524 :                         zend_optimizer_update_op1_const(op_array, opline, val TSRMLS_CC);
     329         524 :                         break;
     330             :                 }
     331             :                 
     332         196 :                 if (ZEND_OP2_TYPE(opline) == type &&
     333          15 :                         ZEND_OP2(opline).var == var) {
     334          15 :                         switch (opline->opcode) {
     335             :                                 case ZEND_ASSIGN_REF:
     336           0 :                                         return 0;
     337             :                                 default:
     338             :                                         break;
     339             :                         }
     340          15 :                         zend_optimizer_update_op2_const(op_array, opline, val TSRMLS_CC);
     341          15 :                         break;
     342             :                 }
     343         166 :                 opline++;
     344             :         }
     345             : 
     346         539 :         return 1;
     347             : }
     348             : 
     349         451 : static void zend_optimize(zend_op_array      *op_array,
     350             :                           zend_optimizer_ctx *ctx TSRMLS_DC)
     351             : {
     352         451 :         if (op_array->type == ZEND_EVAL_CODE) {
     353           0 :                 return;
     354             :         }
     355             : 
     356             :         /* pass 1
     357             :          * - substitute persistent constants (true, false, null, etc)
     358             :          * - perform compile-time evaluation of constant binary and unary operations
     359             :          * - optimize series of ADD_STRING and/or ADD_CHAR
     360             :          * - convert CAST(IS_BOOL,x) into BOOL(x)
     361             :          */
     362         451 :         if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
     363         451 :                 zend_optimizer_pass1(op_array, ctx TSRMLS_CC);
     364             :         }
     365             : 
     366             :         /* pass 2:
     367             :          * - convert non-numeric constants to numeric constants in numeric operators
     368             :          * - optimize constant conditional JMPs
     369             :          * - optimize static BRKs and CONTs
     370             :          * - pre-evaluate constant function calls
     371             :          */
     372         451 :         if (ZEND_OPTIMIZER_PASS_2 & OPTIMIZATION_LEVEL) {
     373         451 :                 zend_optimizer_pass2(op_array TSRMLS_CC);
     374             :         }
     375             : 
     376             :         /* pass 3:
     377             :          * - optimize $i = $i+expr to $i+=expr
     378             :          * - optimize series of JMPs
     379             :          * - change $i++ to ++$i where possible
     380             :          */
     381         451 :         if (ZEND_OPTIMIZER_PASS_3 & OPTIMIZATION_LEVEL) {
     382         451 :                 zend_optimizer_pass3(op_array TSRMLS_CC);
     383             :         }
     384             : 
     385             :         /* pass 4:
     386             :          * - INIT_FCALL_BY_NAME -> DO_FCALL
     387             :          */
     388         451 :         if (ZEND_OPTIMIZER_PASS_4 & OPTIMIZATION_LEVEL) {
     389         451 :                 optimize_func_calls(op_array, ctx TSRMLS_CC);
     390             :         }
     391             : 
     392             :         /* pass 5:
     393             :          * - CFG optimization
     394             :          */
     395         451 :         if (ZEND_OPTIMIZER_PASS_5 & OPTIMIZATION_LEVEL) {
     396         451 :                 optimize_cfg(op_array, ctx TSRMLS_CC);
     397             :         }
     398             : 
     399             :         /* pass 9:
     400             :          * - Optimize temp variables usage
     401             :          */
     402         451 :         if (ZEND_OPTIMIZER_PASS_9 & OPTIMIZATION_LEVEL) {
     403         451 :                 optimize_temporary_variables(op_array, ctx);
     404             :         }
     405             : 
     406             :         /* pass 10:
     407             :          * - remove NOPs
     408             :          */
     409         451 :         if (((ZEND_OPTIMIZER_PASS_10|ZEND_OPTIMIZER_PASS_5) & OPTIMIZATION_LEVEL) == ZEND_OPTIMIZER_PASS_10) {
     410           0 :                 zend_optimizer_nop_removal(op_array);
     411             :         }
     412             : 
     413             :         /* pass 11:
     414             :          * - Compact literals table 
     415             :          */
     416         451 :         if (ZEND_OPTIMIZER_PASS_11 & OPTIMIZATION_LEVEL) {
     417         451 :                 zend_optimizer_compact_literals(op_array, ctx TSRMLS_CC);
     418             :         }
     419             : }
     420             : 
     421         451 : static void zend_accel_optimize(zend_op_array      *op_array,
     422             :                                 zend_optimizer_ctx *ctx TSRMLS_DC)
     423             : {
     424             :         zend_op *opline, *end;
     425             : 
     426             :         /* Revert pass_two() */
     427         451 :         opline = op_array->opcodes;
     428         451 :         end = opline + op_array->last;
     429        8310 :         while (opline < end) {
     430        7408 :                 if (opline->op1_type == IS_CONST) {
     431        2419 :                         opline->op1.constant = opline->op1.zv - op_array->literals;
     432             :                 }
     433        7408 :                 if (opline->op2_type == IS_CONST) {
     434        1814 :                         opline->op2.constant = opline->op2.zv - op_array->literals;
     435             :                 }
     436        7408 :                 switch (opline->opcode) {
     437             :                         case ZEND_JMP:
     438             :                         case ZEND_GOTO:
     439             :                         case ZEND_FAST_CALL:
     440          37 :                                 ZEND_OP1(opline).opline_num = ZEND_OP1(opline).jmp_addr - op_array->opcodes;
     441          37 :                                 break;
     442             :                         case ZEND_JMPZNZ:
     443             :                                 /* relative offset into absolute index */
     444           0 :                                 opline->extended_value = (zend_op*)(((char*)opline) + opline->extended_value) - op_array->opcodes;
     445             :                                 /* break omitted intentionally */
     446             :                         case ZEND_JMPZ:
     447             :                         case ZEND_JMPNZ:
     448             :                         case ZEND_JMPZ_EX:
     449             :                         case ZEND_JMPNZ_EX:
     450             :                         case ZEND_JMP_SET:
     451             :                         case ZEND_COALESCE:
     452             :                         case ZEND_NEW:
     453             :                         case ZEND_FE_RESET:
     454             :                         case ZEND_FE_FETCH:
     455         403 :                                 ZEND_OP2(opline).opline_num = ZEND_OP2(opline).jmp_addr - op_array->opcodes;
     456             :                                 break;
     457             :                 }
     458        7408 :                 opline++;
     459             :         }
     460             : 
     461             :         /* Do actual optimizations */
     462         451 :         zend_optimize(op_array, ctx TSRMLS_CC); 
     463             :         
     464             :         /* Redo pass_two() */
     465         451 :         opline = op_array->opcodes;
     466         451 :         end = opline + op_array->last;
     467        6700 :         while (opline < end) {
     468        5798 :                 if (opline->op1_type == IS_CONST) {
     469        2054 :                         opline->op1.zv = &op_array->literals[opline->op1.constant];
     470             :                 }
     471        5798 :                 if (opline->op2_type == IS_CONST) {
     472        1424 :                         opline->op2.zv = &op_array->literals[opline->op2.constant];
     473             :                 }
     474        5798 :                 switch (opline->opcode) {
     475             :                         case ZEND_JMP:
     476             :                         case ZEND_GOTO:
     477             :                         case ZEND_FAST_CALL:
     478          35 :                                 ZEND_OP1(opline).jmp_addr = &op_array->opcodes[ZEND_OP1(opline).opline_num];
     479          35 :                                 break;
     480             :                         case ZEND_JMPZNZ:
     481             :                                 /* absolute index to relative offset */
     482           0 :                                 opline->extended_value = (char*)(op_array->opcodes + opline->extended_value) - (char*)opline;
     483             :                                 /* break omitted intentionally */
     484             :                         case ZEND_JMPZ:
     485             :                         case ZEND_JMPNZ:
     486             :                         case ZEND_JMPZ_EX:
     487             :                         case ZEND_JMPNZ_EX:
     488             :                         case ZEND_JMP_SET:
     489             :                         case ZEND_COALESCE:
     490             :                         case ZEND_NEW:
     491             :                         case ZEND_FE_RESET:
     492             :                         case ZEND_FE_FETCH:
     493         197 :                                 ZEND_OP2(opline).jmp_addr = &op_array->opcodes[ZEND_OP2(opline).opline_num];
     494             :                                 break;
     495             :                 }
     496        5798 :                 ZEND_VM_SET_OPCODE_HANDLER(opline);
     497        5798 :                 opline++;
     498             :         }
     499         451 : }
     500             : 
     501         422 : int zend_accel_script_optimize(zend_persistent_script *script TSRMLS_DC)
     502             : {
     503             :         uint idx, j;
     504             :         Bucket *p, *q;
     505             :         zend_class_entry *ce;
     506             :         zend_op_array *op_array;
     507             :         zend_optimizer_ctx ctx;
     508             : 
     509         422 :         ctx.arena = zend_arena_create(64 * 1024);
     510         422 :         ctx.script = script;
     511         422 :         ctx.constants = NULL;
     512             : 
     513         422 :         zend_accel_optimize(&script->main_op_array, &ctx TSRMLS_CC);
     514             : 
     515         446 :         for (idx = 0; idx < script->function_table.nNumUsed; idx++) {
     516          24 :                 p = script->function_table.arData + idx;
     517          48 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
     518          24 :                 op_array = (zend_op_array*)Z_PTR(p->val);
     519          24 :                 zend_accel_optimize(op_array, &ctx TSRMLS_CC);
     520             :         }
     521             : 
     522         424 :         for (idx = 0; idx < script->class_table.nNumUsed; idx++) {
     523           2 :                 p = script->class_table.arData + idx;
     524           4 :                 if (Z_TYPE(p->val) == IS_UNDEF) continue;
     525           1 :                 ce = (zend_class_entry*)Z_PTR(p->val);
     526           6 :                 for (j = 0; j < ce->function_table.nNumUsed; j++) {
     527           5 :                         q = ce->function_table.arData + j;
     528          10 :                         if (Z_TYPE(q->val) == IS_UNDEF) continue;
     529           5 :                         op_array = (zend_op_array*)Z_PTR(q->val);
     530           5 :                         if (op_array->scope == ce) {
     531           5 :                                 zend_accel_optimize(op_array, &ctx TSRMLS_CC);
     532           0 :                         } else if (op_array->type == ZEND_USER_FUNCTION) {
     533             :                                 zend_op_array *orig_op_array;
     534           0 :                                 if ((orig_op_array = zend_hash_find_ptr(&op_array->scope->function_table, q->key)) != NULL) {
     535           0 :                                         HashTable *ht = op_array->static_variables;
     536           0 :                                         *op_array = *orig_op_array;
     537           0 :                                         op_array->static_variables = ht;
     538             :                                 }
     539             :                         }
     540             :                 }
     541             :         }
     542             : 
     543         422 :         if (ctx.constants) {
     544           0 :                 zend_hash_destroy(ctx.constants);
     545             :         }
     546         422 :         zend_arena_destroy(ctx.arena);
     547             : 
     548         422 :         return 1;
     549             : }

Generated by: LCOV version 1.10

Generated at Sat, 13 Dec 2014 06:16:17 +0000 (9 days ago)

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