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

Generated by: LCOV version 1.10

Generated at Wed, 22 Oct 2014 07:24:53 +0000 (15 hours ago)

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