root/ext/opcache/Optimizer/pass2.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. zend_optimizer_pass2

   1 /*
   2    +----------------------------------------------------------------------+
   3    | Zend OPcache                                                         |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1998-2016 The PHP Group                                |
   6    +----------------------------------------------------------------------+
   7    | This source file is subject to version 3.01 of the PHP license,      |
   8    | that is bundled with this package in the file LICENSE, and is        |
   9    | available through the world-wide-web at the following url:           |
  10    | http://www.php.net/license/3_01.txt                                  |
  11    | If you did not receive a copy of the PHP license and are unable to   |
  12    | obtain it through the world-wide-web, please send a note to          |
  13    | license@php.net so we can mail you a copy immediately.               |
  14    +----------------------------------------------------------------------+
  15    | Authors: Andi Gutmans <andi@zend.com>                                |
  16    |          Zeev Suraski <zeev@zend.com>                                |
  17    |          Stanislav Malyshev <stas@zend.com>                          |
  18    |          Dmitry Stogov <dmitry@zend.com>                             |
  19    +----------------------------------------------------------------------+
  20 */
  21 
  22 /* pass 2:
  23  * - convert non-numeric constants to numeric constants in numeric operators
  24  * - optimize constant conditional JMPs
  25  * - optimize static BRKs and CONTs
  26  */
  27 
  28 #include "php.h"
  29 #include "Optimizer/zend_optimizer.h"
  30 #include "Optimizer/zend_optimizer_internal.h"
  31 #include "zend_API.h"
  32 #include "zend_constants.h"
  33 #include "zend_execute.h"
  34 #include "zend_vm.h"
  35 
  36 void zend_optimizer_pass2(zend_op_array *op_array)
  37 {
  38         zend_op *opline;
  39         zend_op *end = op_array->opcodes + op_array->last;
  40 
  41         opline = op_array->opcodes;
  42         while (opline < end) {
  43                 switch (opline->opcode) {
  44                         case ZEND_ADD:
  45                         case ZEND_SUB:
  46                         case ZEND_MUL:
  47                         case ZEND_DIV:
  48                         case ZEND_POW:
  49                                 if (ZEND_OP1_TYPE(opline) == IS_CONST) {
  50                                         if (Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING) {
  51                                                 convert_scalar_to_number(&ZEND_OP1_LITERAL(opline));
  52                                         }
  53                                 }
  54                                 /* break missing *intentionally* - the assign_op's may only optimize op2 */
  55                         case ZEND_ASSIGN_ADD:
  56                         case ZEND_ASSIGN_SUB:
  57                         case ZEND_ASSIGN_MUL:
  58                         case ZEND_ASSIGN_DIV:
  59                         case ZEND_ASSIGN_POW:
  60                                 if (opline->extended_value != 0) {
  61                                         /* object tristate op - don't attempt to optimize it! */
  62                                         break;
  63                                 }
  64                                 if (ZEND_OP2_TYPE(opline) == IS_CONST) {
  65                                         if (Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) {
  66                                                 convert_scalar_to_number(&ZEND_OP2_LITERAL(opline));
  67                                         }
  68                                 }
  69                                 break;
  70 
  71                         case ZEND_MOD:
  72                         case ZEND_SL:
  73                         case ZEND_SR:
  74                                 if (ZEND_OP1_TYPE(opline) == IS_CONST) {
  75                                         if (Z_TYPE(ZEND_OP1_LITERAL(opline)) != IS_LONG) {
  76                                                 convert_to_long(&ZEND_OP1_LITERAL(opline));
  77                                         }
  78                                 }
  79                                 /* break missing *intentionally - the assign_op's may only optimize op2 */
  80                         case ZEND_ASSIGN_MOD:
  81                         case ZEND_ASSIGN_SL:
  82                         case ZEND_ASSIGN_SR:
  83                                 if (opline->extended_value != 0) {
  84                                         /* object tristate op - don't attempt to optimize it! */
  85                                         break;
  86                                 }
  87                                 if (ZEND_OP2_TYPE(opline) == IS_CONST) {
  88                                         if (Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_LONG) {
  89                                                 convert_to_long(&ZEND_OP2_LITERAL(opline));
  90                                         }
  91                                 }
  92                                 break;
  93 
  94                         case ZEND_CONCAT:
  95                         case ZEND_FAST_CONCAT:
  96                                 if (ZEND_OP1_TYPE(opline) == IS_CONST) {
  97                                         if (Z_TYPE(ZEND_OP1_LITERAL(opline)) != IS_STRING) {
  98                                                 convert_to_string(&ZEND_OP1_LITERAL(opline));
  99                                         }
 100                                 }
 101                                 /* break missing *intentionally - the assign_op's may only optimize op2 */
 102                         case ZEND_ASSIGN_CONCAT:
 103                                 if (opline->extended_value != 0) {
 104                                         /* object tristate op - don't attempt to optimize it! */
 105                                         break;
 106                                 }
 107                                 if (ZEND_OP2_TYPE(opline) == IS_CONST) {
 108                                         if (Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_STRING) {
 109                                                 convert_to_string(&ZEND_OP2_LITERAL(opline));
 110                                         }
 111                                 }
 112                                 break;
 113 
 114                         case ZEND_JMPZ_EX:
 115                         case ZEND_JMPNZ_EX:
 116                                 /* convert Ti = JMPZ_EX(Ti, L) to JMPZ(Ti, L) */
 117                                 if (0 && /* FIXME: temporary disable unsafe pattern */
 118                                     ZEND_OP1_TYPE(opline) == IS_TMP_VAR &&
 119                                     ZEND_RESULT_TYPE(opline) == IS_TMP_VAR &&
 120                                     ZEND_OP1(opline).var == ZEND_RESULT(opline).var) {
 121                                         opline->opcode -= 3;
 122                                 /* convert Ti = JMPZ_EX(C, L) => Ti = QM_ASSIGN(C)
 123                                    in case we know it wouldn't jump */
 124                                 } else if (ZEND_OP1_TYPE(opline) == IS_CONST) {
 125                                         int should_jmp = zend_is_true(&ZEND_OP1_LITERAL(opline));
 126                                         if (opline->opcode == ZEND_JMPZ_EX) {
 127                                                 should_jmp = !should_jmp;
 128                                         }
 129                                         if (!should_jmp) {
 130                                                 opline->opcode = ZEND_QM_ASSIGN;
 131                                                 SET_UNUSED(opline->op2);
 132                                         }
 133                                 }
 134                                 break;
 135 
 136                         case ZEND_JMPZ:
 137                         case ZEND_JMPNZ:
 138                                 if (ZEND_OP1_TYPE(opline) == IS_CONST) {
 139                                         int should_jmp = zend_is_true(&ZEND_OP1_LITERAL(opline));
 140 
 141                                         if (opline->opcode == ZEND_JMPZ) {
 142                                                 should_jmp = !should_jmp;
 143                                         }
 144                                         literal_dtor(&ZEND_OP1_LITERAL(opline));
 145                                         ZEND_OP1_TYPE(opline) = IS_UNUSED;
 146                                         if (should_jmp) {
 147                                                 opline->opcode = ZEND_JMP;
 148                                                 COPY_NODE(opline->op1, opline->op2);
 149                                         } else {
 150                                                 MAKE_NOP(opline);
 151                                         }
 152                                         break;
 153                                 }
 154                                 if ((opline + 1)->opcode == ZEND_JMP) {
 155                                         /* JMPZ(X, L1), JMP(L2) => JMPZNZ(X, L1, L2) */
 156                                         /* JMPNZ(X, L1), JMP(L2) => JMPZNZ(X, L2, L1) */
 157                                         if (ZEND_OP2(opline).opline_num == ZEND_OP1(opline + 1).opline_num) {
 158                                                 /* JMPZ(X, L1), JMP(L1) => NOP, JMP(L1) */
 159                                                 MAKE_NOP(opline);
 160                                         } else {
 161                                                 if (opline->opcode == ZEND_JMPZ) {
 162                                                         opline->extended_value = ZEND_OP1(opline + 1).opline_num;
 163                                                 } else {
 164                                                         opline->extended_value = ZEND_OP2(opline).opline_num;
 165                                                         COPY_NODE(opline->op2, (opline + 1)->op1);
 166                                                 }
 167                                                 opline->opcode = ZEND_JMPZNZ;
 168                                         }
 169                                 }
 170                                 break;
 171 
 172                         case ZEND_JMPZNZ:
 173                                 if (ZEND_OP1_TYPE(opline) == IS_CONST) {
 174                                         int opline_num;
 175                                         if (zend_is_true(&ZEND_OP1_LITERAL(opline))) {
 176                                                 opline_num = opline->extended_value; /* JMPNZ */
 177                                         } else {
 178                                                 opline_num = ZEND_OP2(opline).opline_num; /* JMPZ */
 179                                         }
 180                                         literal_dtor(&ZEND_OP1_LITERAL(opline));
 181                                         ZEND_OP1(opline).opline_num = opline_num;
 182                                         ZEND_OP1_TYPE(opline) = IS_UNUSED;
 183                                         opline->opcode = ZEND_JMP;
 184                                 }
 185                                 break;
 186                 }
 187                 opline++;
 188         }
 189 }

/* [<][>][^][v][top][bottom][index][help] */