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 - pass1_5.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 235 330 71.2 %
Date: 2018-03-13 Functions: 1 1 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | Zend OPcache                                                         |
       4             :    +----------------------------------------------------------------------+
       5             :    | Copyright (c) 1998-2018 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             : /* pass 1
      23             :  * - substitute persistent constants (true, false, null, etc)
      24             :  * - perform compile-time evaluation of constant binary and unary operations
      25             :  * - optimize series of ADD_STRING and/or ADD_CHAR
      26             :  * - convert CAST(IS_BOOL,x) into BOOL(x)
      27             :  * - pre-evaluate constant function calls
      28             :  */
      29             : 
      30             : #include "php.h"
      31             : #include "Optimizer/zend_optimizer.h"
      32             : #include "Optimizer/zend_optimizer_internal.h"
      33             : #include "zend_API.h"
      34             : #include "zend_constants.h"
      35             : #include "zend_execute.h"
      36             : #include "zend_vm.h"
      37             : 
      38             : #define ZEND_IS_CONSTANT_TYPE(t)        ((t) == IS_CONSTANT)
      39             : 
      40         727 : void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
      41             : {
      42         727 :         int i = 0;
      43         727 :         zend_op *opline = op_array->opcodes;
      44         727 :         zend_op *end = opline + op_array->last;
      45        1454 :         zend_bool collect_constants = (ZEND_OPTIMIZER_PASS_15 & ctx->optimization_level)?
      46         727 :                 (op_array == &ctx->script->main_op_array) : 0;
      47             : 
      48       11896 :         while (opline < end) {
      49       10442 :                 switch (opline->opcode) {
      50         287 :                 case ZEND_ADD:
      51             :                 case ZEND_SUB:
      52             :                 case ZEND_MUL:
      53             :                 case ZEND_DIV:
      54             :                 case ZEND_MOD:
      55             :                 case ZEND_POW:
      56             :                 case ZEND_SL:
      57             :                 case ZEND_SR:
      58             :                 case ZEND_CONCAT:
      59             :                 case ZEND_FAST_CONCAT:
      60             :                 case ZEND_IS_EQUAL:
      61             :                 case ZEND_IS_NOT_EQUAL:
      62             :                 case ZEND_IS_SMALLER:
      63             :                 case ZEND_IS_SMALLER_OR_EQUAL:
      64             :                 case ZEND_IS_IDENTICAL:
      65             :                 case ZEND_IS_NOT_IDENTICAL:
      66             :                 case ZEND_BW_OR:
      67             :                 case ZEND_BW_AND:
      68             :                 case ZEND_BW_XOR:
      69             :                 case ZEND_BOOL_XOR:
      70             :                 case ZEND_SPACESHIP:
      71         369 :                         if (ZEND_OP1_TYPE(opline) == IS_CONST &&
      72          82 :                                 ZEND_OP2_TYPE(opline) == IS_CONST) {
      73             :                                 /* binary operation with constant operands */
      74          12 :                                 binary_op_type binary_op = get_binary_op(opline->opcode);
      75          12 :                                 uint32_t tv = ZEND_RESULT(opline).var;          /* temporary variable */
      76             :                                 zval result;
      77             :                                 int er;
      78             : 
      79          12 :                                 if ((opline->opcode == ZEND_DIV || opline->opcode == ZEND_MOD) &&
      80           0 :                                         zval_get_long(&ZEND_OP2_LITERAL(opline)) == 0) {
      81             :                                         /* div by 0 */
      82             :                                         break;
      83          12 :                                 } else if ((opline->opcode == ZEND_SL || opline->opcode == ZEND_SR) &&
      84           0 :                                         zval_get_long(&ZEND_OP2_LITERAL(opline)) < 0) {
      85             :                                         /* shift by negative number */
      86             :                                         break;
      87          12 :                                 } else if (zend_binary_op_produces_numeric_string_error(opline->opcode, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline))) {
      88             :                                         /* produces numeric string E_NOTICE/E_WARNING */
      89           0 :                                         break;
      90             :                                 }
      91          12 :                                 er = EG(error_reporting);
      92          12 :                                 EG(error_reporting) = 0;
      93             :                                 /* evaluate constant expression */
      94          12 :                                 if (binary_op(&result, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline)) != SUCCESS) {
      95           0 :                                         EG(error_reporting) = er;
      96           0 :                                         break;
      97             :                                 }
      98          12 :                                 EG(error_reporting) = er;
      99             : 
     100          12 :                                 if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, tv, &result)) {
     101          24 :                                         literal_dtor(&ZEND_OP1_LITERAL(opline));
     102          24 :                                         literal_dtor(&ZEND_OP2_LITERAL(opline));
     103          12 :                                         MAKE_NOP(opline);
     104             :                                 }
     105             :                         }
     106         287 :                         break;
     107             : 
     108           3 :                 case ZEND_CAST:
     109           5 :                         if (ZEND_OP1_TYPE(opline) == IS_CONST &&
     110           4 :                                 opline->extended_value != IS_ARRAY &&
     111           4 :                                 opline->extended_value != IS_OBJECT &&
     112           4 :                                 opline->extended_value != IS_RESOURCE &&
     113           2 :                                 (opline->extended_value != IS_STRING
     114           6 :                                         || Z_TYPE(ZEND_OP1_LITERAL(opline)) != IS_ARRAY)) {
     115             :                                 /* cast of constant operand */
     116           2 :                                 zend_uchar type = opline->result_type;
     117           2 :                                 uint32_t tv = ZEND_RESULT(opline).var;          /* temporary variable */
     118             :                                 zval res;
     119           2 :                                 res = ZEND_OP1_LITERAL(opline);
     120             :                                 zval_copy_ctor(&res);
     121           2 :                                 switch (opline->extended_value) {
     122           0 :                                         case IS_NULL:
     123           0 :                                                 convert_to_null(&res);
     124           0 :                                                 break;
     125           0 :                                         case _IS_BOOL:
     126           0 :                                                 convert_to_boolean(&res);
     127           0 :                                                 break;
     128           0 :                                         case IS_LONG:
     129           0 :                                                 convert_to_long(&res);
     130           0 :                                                 break;
     131           0 :                                         case IS_DOUBLE:
     132           0 :                                                 convert_to_double(&res);
     133           0 :                                                 break;
     134           2 :                                         case IS_STRING:
     135           2 :                                                 convert_to_string(&res);
     136           2 :                                                 break;
     137             :                                 }
     138             : 
     139           2 :                                 if (zend_optimizer_replace_by_const(op_array, opline + 1, type, tv, &res)) {
     140           4 :                                         literal_dtor(&ZEND_OP1_LITERAL(opline));
     141           2 :                                         MAKE_NOP(opline);
     142             :                                 }
     143           1 :                         } else if (opline->extended_value == _IS_BOOL) {
     144             :                                 /* T = CAST(X, IS_BOOL) => T = BOOL(X) */
     145           0 :                                 opline->opcode = ZEND_BOOL;
     146           0 :                                 opline->extended_value = 0;
     147             :                         }
     148           3 :                         break;
     149             : 
     150         313 :                 case ZEND_BW_NOT:
     151             :                 case ZEND_BOOL_NOT:
     152         313 :                         if (ZEND_OP1_TYPE(opline) == IS_CONST) {
     153             :                                 /* unary operation on constant operand */
     154         238 :                                 unary_op_type unary_op = get_unary_op(opline->opcode);
     155             :                                 zval result;
     156         238 :                                 uint32_t tv = ZEND_RESULT(opline).var;          /* temporary variable */
     157             :                                 int er;
     158             : 
     159         238 :                                 er = EG(error_reporting);
     160         238 :                                 EG(error_reporting) = 0;
     161         238 :                                 if (unary_op(&result, &ZEND_OP1_LITERAL(opline)) != SUCCESS) {
     162           0 :                                         EG(error_reporting) = er;
     163           0 :                                         break;
     164             :                                 }
     165         238 :                                 EG(error_reporting) = er;
     166             : 
     167         238 :                                 if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, tv, &result)) {
     168         476 :                                         literal_dtor(&ZEND_OP1_LITERAL(opline));
     169         238 :                                         MAKE_NOP(opline);
     170             :                                 }
     171             :                         }
     172         313 :                         break;
     173             : 
     174             : #if 0
     175             :                 case ZEND_ADD_STRING:
     176             :                 case ZEND_ADD_CHAR:
     177             :                         {
     178             :                                 zend_op *next_op = opline + 1;
     179             :                                 int requires_conversion = (opline->opcode == ZEND_ADD_CHAR? 1 : 0);
     180             :                                 size_t final_length = 0;
     181             :                                 zend_string *str;
     182             :                                 char *ptr;
     183             :                                 zend_op *last_op;
     184             : 
     185             :                                 /* There is always a ZEND_RETURN at the end
     186             :                                 if (next_op>=end) {
     187             :                                         break;
     188             :                                 }
     189             :                                 */
     190             :                                 while (next_op->opcode == ZEND_ADD_STRING || next_op->opcode == ZEND_ADD_CHAR) {
     191             :                                         if (ZEND_RESULT(opline).var != ZEND_RESULT(next_op).var) {
     192             :                                                 break;
     193             :                                         }
     194             :                                         if (next_op->opcode == ZEND_ADD_CHAR) {
     195             :                                                 final_length += 1;
     196             :                                         } else { /* ZEND_ADD_STRING */
     197             :                                                 final_length += Z_STRLEN(ZEND_OP2_LITERAL(next_op));
     198             :                                         }
     199             :                                         next_op++;
     200             :                                 }
     201             :                                 if (final_length == 0) {
     202             :                                         break;
     203             :                                 }
     204             :                                 last_op = next_op;
     205             :                                 final_length += (requires_conversion? 1 : Z_STRLEN(ZEND_OP2_LITERAL(opline)));
     206             :                                 str = zend_string_alloc(final_length, 0);
     207             :                                 str->len = final_length;
     208             :                                 ptr = str->val;
     209             :                                 ptr[final_length] = '\0';
     210             :                                 if (requires_conversion) { /* ZEND_ADD_CHAR */
     211             :                                         char chval = (char)Z_LVAL(ZEND_OP2_LITERAL(opline));
     212             : 
     213             :                                         ZVAL_NEW_STR(&ZEND_OP2_LITERAL(opline), str);
     214             :                                         ptr[0] = chval;
     215             :                                         opline->opcode = ZEND_ADD_STRING;
     216             :                                         ptr++;
     217             :                                 } else { /* ZEND_ADD_STRING */
     218             :                                         memcpy(ptr, Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)));
     219             :                                         ptr += Z_STRLEN(ZEND_OP2_LITERAL(opline));
     220             :                                         zend_string_release(Z_STR(ZEND_OP2_LITERAL(opline)));
     221             :                                         ZVAL_NEW_STR(&ZEND_OP2_LITERAL(opline), str);
     222             :                                 }
     223             :                                 next_op = opline + 1;
     224             :                                 while (next_op < last_op) {
     225             :                                         if (next_op->opcode == ZEND_ADD_STRING) {
     226             :                                                 memcpy(ptr, Z_STRVAL(ZEND_OP2_LITERAL(next_op)), Z_STRLEN(ZEND_OP2_LITERAL(next_op)));
     227             :                                                 ptr += Z_STRLEN(ZEND_OP2_LITERAL(next_op));
     228             :                                                 literal_dtor(&ZEND_OP2_LITERAL(next_op));
     229             :                                         } else { /* ZEND_ADD_CHAR */
     230             :                                                 *ptr = (char)Z_LVAL(ZEND_OP2_LITERAL(next_op));
     231             :                                                 ptr++;
     232             :                                         }
     233             :                                         MAKE_NOP(next_op);
     234             :                                         next_op++;
     235             :                                 }
     236             :                                 if (!((ZEND_OPTIMIZER_PASS_5|ZEND_OPTIMIZER_PASS_10) & OPTIMIZATION_LEVEL)) {
     237             :                                         /* NOP removal is disabled => insert JMP over NOPs */
     238             :                                         if (last_op-opline >= 3) { /* If we have more than 2 NOPS then JMP over them */
     239             :                                                 (opline + 1)->opcode = ZEND_JMP;
     240             :                                                 ZEND_OP1(opline + 1).opline_num = last_op - op_array->opcodes; /* that's OK even for ZE2, since opline_num's are resolved in pass 2 later */
     241             :                                         }
     242             :                                 }
     243             :                         }
     244             :                         break;
     245             : #endif
     246             : 
     247          63 :                 case ZEND_FETCH_CONSTANT:
     248         126 :                         if (ZEND_OP2_TYPE(opline) == IS_CONST &&
     249         189 :                                 Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING &&
     250          63 :                                 Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("__COMPILER_HALT_OFFSET__") - 1 &&
     251           0 :                                 memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)), "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1) == 0) {
     252             :                                 /* substitute __COMPILER_HALT_OFFSET__ constant */
     253           0 :                                 zend_execute_data *orig_execute_data = EG(current_execute_data);
     254             :                                 zend_execute_data fake_execute_data;
     255             :                                 zval *offset;
     256             : 
     257           0 :                                 memset(&fake_execute_data, 0, sizeof(zend_execute_data));
     258           0 :                                 fake_execute_data.func = (zend_function*)op_array;
     259           0 :                                 EG(current_execute_data) = &fake_execute_data;
     260           0 :                                 if ((offset = zend_get_constant_str("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1)) != NULL) {
     261           0 :                                         uint32_t tv = ZEND_RESULT(opline).var;
     262             : 
     263           0 :                                         if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, offset)) {
     264           0 :                                                 literal_dtor(&ZEND_OP2_LITERAL(opline));
     265           0 :                                                 MAKE_NOP(opline);
     266             :                                         }
     267             :                                 }
     268           0 :                                 EG(current_execute_data) = orig_execute_data;
     269           0 :                                 break;
     270             :                         }
     271             : 
     272         126 :                         if (ZEND_OP2_TYPE(opline) == IS_CONST &&
     273         126 :                                 Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) {
     274             :                                 /* substitute persistent constants */
     275          63 :                                 uint32_t tv = ZEND_RESULT(opline).var;
     276             :                                 zval c;
     277             : 
     278          63 :                                 if (!zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP2_LITERAL(opline)), &c, 1)) {
     279          63 :                                         if (!ctx->constants || !zend_optimizer_get_collected_constant(ctx->constants, &ZEND_OP2_LITERAL(opline), &c)) {
     280             :                                                 break;
     281             :                                         }
     282             :                                 }
     283           0 :                                 if (Z_TYPE(c) == IS_CONSTANT_AST) {
     284           0 :                                         break;
     285             :                                 }
     286           0 :                                 if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, &c)) {
     287           0 :                                         literal_dtor(&ZEND_OP2_LITERAL(opline));
     288           0 :                                         MAKE_NOP(opline);
     289             :                                 }
     290             :                         }
     291           0 :                         break;
     292             : 
     293          81 :                 case ZEND_FETCH_CLASS_CONSTANT:
     294         162 :                         if (ZEND_OP2_TYPE(opline) == IS_CONST &&
     295         162 :                                 Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) {
     296             : 
     297          81 :                                 zend_class_entry *ce = NULL;
     298             : 
     299         154 :                                 if (ZEND_OP1_TYPE(opline) == IS_CONST &&
     300         146 :                                 Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING) {
     301             :                                         /* for A::B */
     302         131 :                                         if (op_array->scope &&
     303           2 :                                                 !strncasecmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
     304           2 :                                                 ZSTR_VAL(op_array->scope->name), Z_STRLEN(ZEND_OP1_LITERAL(opline)) + 1)) {
     305           1 :                                                 ce = op_array->scope;
     306             :                                         } else {
     307         144 :                                                 if ((ce = zend_hash_find_ptr(EG(class_table),
     308         128 :                                                                 Z_STR(op_array->literals[opline->op1.constant + 1]))) == NULL ||
     309         112 :                                                                 (ce->type == ZEND_INTERNAL_CLASS &&
     310         112 :                                                                  ce->info.internal.module->type != MODULE_PERSISTENT) ||
     311          56 :                                                                 (ce->type == ZEND_USER_CLASS &&
     312           0 :                                                                  ce->info.user.filename != op_array->filename)) {
     313             :                                                         break;
     314             :                                                 }
     315             :                                         }
     316           8 :                                 } else if (op_array->scope &&
     317           0 :                                         ZEND_OP1_TYPE(opline) == IS_UNUSED &&
     318           0 :                                         (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
     319             :                                         /* for self::B */
     320           0 :                                         ce = op_array->scope;
     321           8 :                                 } else if (op_array->scope &&
     322           0 :                                         ZEND_OP1_TYPE(opline) == IS_VAR &&
     323           0 :                                         (opline - 1)->opcode == ZEND_FETCH_CLASS &&
     324           0 :                                         (ZEND_OP1_TYPE(opline - 1) == IS_UNUSED &&
     325           0 :                                         ((opline - 1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) &&
     326           0 :                                         ZEND_RESULT((opline - 1)).var == ZEND_OP1(opline).var) {
     327             :                                         /* for self::B */
     328           0 :                                         ce = op_array->scope;
     329             :                                 }
     330             : 
     331          65 :                                 if (ce) {
     332          57 :                                         uint32_t tv = ZEND_RESULT(opline).var;
     333             :                                         zend_class_constant *cc;
     334             :                                         zval *c, t;
     335             : 
     336         114 :                                         if ((cc = zend_hash_find_ptr(&ce->constants_table,
     337         114 :                                                         Z_STR(ZEND_OP2_LITERAL(opline)))) != NULL &&
     338          57 :                                                 (Z_ACCESS_FLAGS(cc->value) & ZEND_ACC_PPP_MASK) == ZEND_ACC_PUBLIC) {
     339          57 :                                                 c = &cc->value;
     340          57 :                                                 if (Z_TYPE_P(c) == IS_CONSTANT_AST) {
     341           0 :                                                         break;
     342             :                                                 }
     343          57 :                                                 if (ZEND_IS_CONSTANT_TYPE(Z_TYPE_P(c))) {
     344           0 :                                                         if (!zend_optimizer_get_persistent_constant(Z_STR_P(c), &t, 1) ||
     345           0 :                                                             ZEND_IS_CONSTANT_TYPE(Z_TYPE(t))) {
     346             :                                                                 break;
     347             :                                                         }
     348             :                                                 } else {
     349          57 :                                                         ZVAL_COPY_VALUE(&t, c);
     350             :                                                         zval_copy_ctor(&t);
     351             :                                                 }
     352             : 
     353          57 :                                                 if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, &t)) {
     354          57 :                                                         if (ZEND_OP1_TYPE(opline) == IS_CONST) {
     355         114 :                                                                 literal_dtor(&ZEND_OP1_LITERAL(opline));
     356           0 :                                                         } else if (ZEND_OP1_TYPE(opline) == IS_VAR) {
     357           0 :                                                                 MAKE_NOP((opline - 1));
     358             :                                                         }
     359         114 :                                                         literal_dtor(&ZEND_OP2_LITERAL(opline));
     360          57 :                                                         MAKE_NOP(opline);
     361             :                                                 }
     362             :                                         }
     363             :                                 }
     364             :                         }
     365          65 :                         break;
     366             : 
     367        1429 :                 case ZEND_DO_ICALL: {
     368        1429 :                         zend_op *send1_opline = opline - 1;
     369        1429 :                         zend_op *send2_opline = NULL;
     370        1429 :                         zend_op *init_opline = NULL;
     371             : 
     372        2858 :                         while (send1_opline->opcode == ZEND_NOP) {
     373           0 :                                 send1_opline--;
     374             :                         }
     375        2166 :                         if (send1_opline->opcode != ZEND_SEND_VAL ||
     376         737 :                             ZEND_OP1_TYPE(send1_opline) != IS_CONST) {
     377             :                                 /* don't colllect constants after unknown function call */
     378         786 :                                 collect_constants = 0;
     379         786 :                                 break;
     380             :                         }
     381         643 :                         if (send1_opline->op2.num == 2) {
     382         125 :                                 send2_opline = send1_opline;
     383         125 :                                 send1_opline--;
     384         254 :                                 while (send1_opline->opcode == ZEND_NOP) {
     385           4 :                                         send1_opline--;
     386             :                                 }
     387         217 :                                 if (send1_opline->opcode != ZEND_SEND_VAL ||
     388          92 :                                     ZEND_OP1_TYPE(send1_opline) != IS_CONST) {
     389             :                                         /* don't colllect constants after unknown function call */
     390          38 :                                         collect_constants = 0;
     391          38 :                                         break;
     392             :                                 }
     393             :                         }
     394         605 :                         init_opline = send1_opline - 1;
     395        1221 :                         while (init_opline->opcode == ZEND_NOP) {
     396          11 :                                 init_opline--;
     397             :                         }
     398        1144 :                         if (init_opline->opcode != ZEND_INIT_FCALL ||
     399        1078 :                             ZEND_OP2_TYPE(init_opline) != IS_CONST ||
     400        1078 :                             Z_TYPE(ZEND_OP2_LITERAL(init_opline)) != IS_STRING) {
     401             :                                 /* don't colllect constants after unknown function call */
     402          66 :                                 collect_constants = 0;
     403          66 :                                 break;
     404             :                         }
     405             : 
     406             :                         /* define("name", scalar); */
     407         611 :                         if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("define")-1 &&
     408          72 :                             zend_binary_strcasecmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)), Z_STRLEN(ZEND_OP2_LITERAL(init_opline)), "define", sizeof("define")-1) == 0) {
     409             : 
     410          24 :                                 if (Z_TYPE(ZEND_OP1_LITERAL(send1_opline)) == IS_STRING &&
     411          12 :                                     send2_opline &&
     412          24 :                                     Z_TYPE(ZEND_OP1_LITERAL(send2_opline)) <= IS_STRING) {
     413             : 
     414          12 :                                         if (collect_constants) {
     415           0 :                                                 zend_optimizer_collect_constant(ctx, &ZEND_OP1_LITERAL(send1_opline), &ZEND_OP1_LITERAL(send2_opline));
     416             :                                         }
     417             : 
     418          24 :                                         if (RESULT_UNUSED(opline) &&
     419          24 :                                             !zend_memnstr(Z_STRVAL(ZEND_OP1_LITERAL(send1_opline)), "::", sizeof("::") - 1, Z_STRVAL(ZEND_OP1_LITERAL(send1_opline)) + Z_STRLEN(ZEND_OP1_LITERAL(send1_opline)))) {
     420             : 
     421          12 :                                                 opline->opcode = ZEND_DECLARE_CONST;
     422          12 :                                                 opline->op1_type = IS_CONST;
     423          12 :                                                 opline->op2_type = IS_CONST;
     424          12 :                                                 opline->result_type = IS_UNUSED;
     425          12 :                                                 opline->op1.constant = send1_opline->op1.constant;
     426          12 :                                                 opline->op2.constant = send2_opline->op1.constant;
     427          12 :                                                 opline->result.num = 0;
     428             : 
     429          24 :                                                 literal_dtor(&ZEND_OP2_LITERAL(init_opline));
     430          12 :                                                 MAKE_NOP(init_opline);
     431          12 :                                                 MAKE_NOP(send1_opline);
     432          12 :                                                 MAKE_NOP(send2_opline);
     433             :                                         }
     434          12 :                                         break;
     435             :                                 }
     436             :                         }
     437             : 
     438             :                         /* pre-evaluate constant functions:
     439             :                            defined(x)
     440             :                            constant(x)
     441             :                            function_exists(x)
     442             :                            is_callable(x)
     443             :                            extension_loaded(x)
     444             :                         */
     445         979 :                         if (!send2_opline &&
     446         904 :                             Z_TYPE(ZEND_OP1_LITERAL(send1_opline)) == IS_STRING) {
     447         431 :                                 if ((Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("function_exists")-1 &&
     448           3 :                                         !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)),
     449           3 :                                                 "function_exists", sizeof("function_exists")-1) &&
     450         428 :                                         !zend_optimizer_is_disabled_func("function_exists", sizeof("function_exists") - 1)) ||
     451         428 :                                         (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("is_callable")-1 &&
     452           3 :                                         !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)),
     453           1 :                                                 "is_callable", sizeof("is_callable")) &&
     454           2 :                                         !zend_optimizer_is_disabled_func("is_callable", sizeof("is_callable") - 1))) {
     455             :                                         zend_internal_function *func;
     456           4 :                                         zend_string *lc_name = zend_string_tolower(
     457           4 :                                                         Z_STR(ZEND_OP1_LITERAL(send1_opline)));
     458             : 
     459           8 :                                         if ((func = zend_hash_find_ptr(EG(function_table), lc_name)) != NULL
     460           3 :                                                  && func->type == ZEND_INTERNAL_FUNCTION
     461           3 :                                                  && func->module->type == MODULE_PERSISTENT
     462             : #ifdef ZEND_WIN32
     463             :                                                  && func->module->handle == NULL
     464             : #endif
     465             :                                                 ) {
     466             :                                                 zval t;
     467           5 :                                                 if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("is_callable") - 1 ||
     468           2 :                                                                 func->handler != ZEND_FN(display_disabled_function)) {
     469           3 :                                                         ZVAL_TRUE(&t);
     470             :                                                 } else {
     471           0 :                                                         ZVAL_FALSE(&t);
     472             :                                                 }
     473           3 :                                                 if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, ZEND_RESULT(opline).var, &t)) {
     474           6 :                                                         literal_dtor(&ZEND_OP2_LITERAL(init_opline));
     475           3 :                                                         MAKE_NOP(init_opline);
     476           6 :                                                         literal_dtor(&ZEND_OP1_LITERAL(send1_opline));
     477           3 :                                                         MAKE_NOP(send1_opline);
     478           3 :                                                         MAKE_NOP(opline);
     479             :                                                         zend_string_release(lc_name);
     480           3 :                                                         break;
     481             :                                                 }
     482             :                                         }
     483             :                                         zend_string_release(lc_name);
     484         673 :                                 } else if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("extension_loaded")-1 &&
     485         249 :                                         !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)),
     486         245 :                                                 "extension_loaded", sizeof("extension_loaded")-1) &&
     487         245 :                                         !zend_optimizer_is_disabled_func("extension_loaded", sizeof("extension_loaded") - 1)) {
     488             :                                         zval t;
     489         245 :                                         zend_string *lc_name = zend_string_tolower(
     490         245 :                                                         Z_STR(ZEND_OP1_LITERAL(send1_opline)));
     491         245 :                                         zend_module_entry *m = zend_hash_find_ptr(&module_registry,
     492             :                                                         lc_name);
     493             : 
     494             :                                         zend_string_release(lc_name);
     495         245 :                                         if (!m) {
     496           1 :                                                 if (PG(enable_dl)) {
     497         245 :                                                         break;
     498             :                                                 } else {
     499           1 :                                                         ZVAL_FALSE(&t);
     500             :                                                 }
     501             :                                         } else {
     502         244 :                                                 if (m->type == MODULE_PERSISTENT
     503             : #ifdef ZEND_WIN32
     504             :                                                  && m->handle == NULL
     505             : #endif
     506             :                                                 ) {
     507         244 :                                                         ZVAL_TRUE(&t);
     508             :                                                 } else {
     509           0 :                                                         break;
     510             :                                                 }
     511             :                                         }
     512             : 
     513         245 :                                         if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, ZEND_RESULT(opline).var, &t)) {
     514         490 :                                                 literal_dtor(&ZEND_OP2_LITERAL(init_opline));
     515         245 :                                                 MAKE_NOP(init_opline);
     516         490 :                                                 literal_dtor(&ZEND_OP1_LITERAL(send1_opline));
     517         245 :                                                 MAKE_NOP(send1_opline);
     518         245 :                                                 MAKE_NOP(opline);
     519         245 :                                                 break;
     520             :                                         }
     521         233 :                                 } else if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("defined")-1 &&
     522          54 :                                         !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)),
     523           0 :                                                 "defined", sizeof("defined")-1) &&
     524           0 :                                         !zend_optimizer_is_disabled_func("defined", sizeof("defined") - 1)) {
     525             :                                         zval t;
     526             : 
     527           0 :                                         if (zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(send1_opline)), &t, 0)) {
     528             : 
     529           0 :                                                 ZVAL_TRUE(&t);
     530           0 :                                                 if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, ZEND_RESULT(opline).var, &t)) {
     531           0 :                                                         literal_dtor(&ZEND_OP2_LITERAL(init_opline));
     532           0 :                                                         MAKE_NOP(init_opline);
     533           0 :                                                         literal_dtor(&ZEND_OP1_LITERAL(send1_opline));
     534           0 :                                                         MAKE_NOP(send1_opline);
     535           0 :                                                         MAKE_NOP(opline);
     536           0 :                                                         break;
     537             :                                                 }
     538             :                                         }
     539         221 :                                 } else if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("constant")-1 &&
     540          42 :                                         !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)),
     541           1 :                                                 "constant", sizeof("constant")-1) &&
     542           1 :                                         !zend_optimizer_is_disabled_func("constant", sizeof("constant") - 1)) {
     543             :                                         zval t;
     544             : 
     545           1 :                                         if (zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(send1_opline)), &t, 1)) {
     546           1 :                                                 if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, ZEND_RESULT(opline).var, &t)) {
     547           2 :                                                         literal_dtor(&ZEND_OP2_LITERAL(init_opline));
     548           1 :                                                         MAKE_NOP(init_opline);
     549           2 :                                                         literal_dtor(&ZEND_OP1_LITERAL(send1_opline));
     550           1 :                                                         MAKE_NOP(send1_opline);
     551           1 :                                                         MAKE_NOP(opline);
     552           1 :                                                         break;
     553             :                                                 }
     554             :                                         }
     555         354 :                                 } else if ((CG(compiler_options) & ZEND_COMPILE_NO_BUILTIN_STRLEN) == 0 &&
     556         224 :                                         Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("strlen") - 1 &&
     557          48 :                                         !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)), "strlen", sizeof("strlen") - 1) &&
     558           0 :                                         !zend_optimizer_is_disabled_func("strlen", sizeof("strlen") - 1)) {
     559             :                                         zval t;
     560             : 
     561           0 :                                         ZVAL_LONG(&t, Z_STRLEN(ZEND_OP1_LITERAL(send1_opline)));
     562           0 :                                         if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, ZEND_RESULT(opline).var, &t)) {
     563           0 :                                                 literal_dtor(&ZEND_OP2_LITERAL(init_opline));
     564           0 :                                                 MAKE_NOP(init_opline);
     565           0 :                                                 literal_dtor(&ZEND_OP1_LITERAL(send1_opline));
     566           0 :                                                 MAKE_NOP(send1_opline);
     567           0 :                                                 MAKE_NOP(opline);
     568           0 :                                                 break;
     569             :                                         }
     570             :                                 /* dirname(IS_CONST/IS_STRING) -> IS_CONST/IS_STRING */
     571         232 :                                 } else if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("dirname")-1 &&
     572          54 :                                         !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)),
     573          11 :                                                 "dirname", sizeof("dirname") - 1) &&
     574          22 :                                         !zend_optimizer_is_disabled_func("dirname", sizeof("dirname") - 1) &&
     575          11 :                                         IS_ABSOLUTE_PATH(Z_STRVAL(ZEND_OP1_LITERAL(send1_opline)), Z_STRLEN(ZEND_OP1_LITERAL(send1_opline)))) {
     576          22 :                                         zend_string *dirname = zend_string_init(Z_STRVAL(ZEND_OP1_LITERAL(send1_opline)), Z_STRLEN(ZEND_OP1_LITERAL(send1_opline)), 0);
     577          11 :                                         ZSTR_LEN(dirname) = zend_dirname(ZSTR_VAL(dirname), ZSTR_LEN(dirname));
     578          11 :                                         if (IS_ABSOLUTE_PATH(ZSTR_VAL(dirname), ZSTR_LEN(dirname))) {
     579             :                                                 zval t;
     580             : 
     581          11 :                                                 ZVAL_STR(&t, dirname);
     582          11 :                                                 if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, ZEND_RESULT(opline).var, &t)) {
     583          22 :                                                         literal_dtor(&ZEND_OP2_LITERAL(init_opline));
     584          11 :                                                         MAKE_NOP(init_opline);
     585          22 :                                                         literal_dtor(&ZEND_OP1_LITERAL(send1_opline));
     586          11 :                                                         MAKE_NOP(send1_opline);
     587          11 :                                                         MAKE_NOP(opline);
     588          11 :                                                         break;
     589             :                                                 }
     590             :                                         } else {
     591             :                                                 zend_string_release(dirname);
     592             :                                         }
     593             :                                 }
     594             :                         }
     595             :                         /* don't colllect constants after any other function call */
     596         267 :                         collect_constants = 0;
     597         267 :                         break;
     598             :                 }
     599          13 :                 case ZEND_STRLEN:
     600          13 :                         if (ZEND_OP1_TYPE(opline) == IS_CONST &&
     601           0 :                             Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING) {
     602             :                                 zval t;
     603             : 
     604           0 :                                 ZVAL_LONG(&t, Z_STRLEN(ZEND_OP1_LITERAL(opline)));
     605           0 :                                 if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, ZEND_RESULT(opline).var, &t)) {
     606           0 :                                         literal_dtor(&ZEND_OP1_LITERAL(opline));
     607           0 :                                         MAKE_NOP(opline);
     608             :                                 }
     609             :                         }
     610          13 :                         break;
     611           0 :                 case ZEND_DEFINED:
     612             :                         {
     613             :                                 zval c;
     614           0 :                                 uint32_t tv = ZEND_RESULT(opline).var;
     615           0 :                                 if (!zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(opline)), &c, 0)) {
     616           0 :                                         break;
     617             :                                 }
     618           0 :                                 ZVAL_TRUE(&c);
     619           0 :                                 if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, &c)) {
     620           0 :                                         literal_dtor(&ZEND_OP1_LITERAL(opline));
     621           0 :                                         MAKE_NOP(opline);
     622             :                                 }
     623             :                         }
     624           0 :                         break;
     625           3 :                 case ZEND_DECLARE_CONST:
     626           3 :                         if (collect_constants &&
     627           0 :                             Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING &&
     628           0 :                             Z_TYPE(ZEND_OP2_LITERAL(opline)) <= IS_STRING) {
     629           0 :                                 zend_optimizer_collect_constant(ctx, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline));
     630             :                         }
     631           3 :                         break;
     632             : 
     633        1839 :                 case ZEND_RETURN:
     634             :                 case ZEND_RETURN_BY_REF:
     635             :                 case ZEND_GENERATOR_RETURN:
     636             :                 case ZEND_EXIT:
     637             :                 case ZEND_THROW:
     638             :                 case ZEND_CATCH:
     639             :                 case ZEND_FAST_CALL:
     640             :                 case ZEND_FAST_RET:
     641             :                 case ZEND_JMP:
     642             :                 case ZEND_JMPZNZ:
     643             :                 case ZEND_JMPZ:
     644             :                 case ZEND_JMPNZ:
     645             :                 case ZEND_JMPZ_EX:
     646             :                 case ZEND_JMPNZ_EX:
     647             :                 case ZEND_FE_RESET_R:
     648             :                 case ZEND_FE_RESET_RW:
     649             :                 case ZEND_FE_FETCH_R:
     650             :                 case ZEND_FE_FETCH_RW:
     651             :                 case ZEND_JMP_SET:
     652             :                 case ZEND_COALESCE:
     653             :                 case ZEND_ASSERT_CHECK:
     654        1839 :                         collect_constants = 0;
     655        1839 :                         break;
     656             :                 }
     657       10442 :                 opline++;
     658       10442 :                 i++;
     659             :         }
     660         727 : }

Generated by: LCOV version 1.10

Generated at Tue, 13 Mar 2018 05:00:40 +0000 (68 days ago)

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