root/ext/opcache/Optimizer/nop_removal.c

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

DEFINITIONS

This source file includes following definitions.
  1. zend_optimizer_nop_removal

   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 10:
  23  * - remove NOPs
  24  */
  25 
  26 #include "php.h"
  27 #include "Optimizer/zend_optimizer.h"
  28 #include "Optimizer/zend_optimizer_internal.h"
  29 #include "zend_API.h"
  30 #include "zend_constants.h"
  31 #include "zend_execute.h"
  32 #include "zend_vm.h"
  33 
  34 void zend_optimizer_nop_removal(zend_op_array *op_array)
  35 {
  36         zend_op *end, *opline;
  37         uint32_t new_count, i, shift;
  38         int j;
  39         uint32_t *shiftlist;
  40         ALLOCA_FLAG(use_heap);
  41 
  42         shiftlist = (uint32_t *)DO_ALLOCA(sizeof(uint32_t) * op_array->last);
  43         i = new_count = shift = 0;
  44         end = op_array->opcodes + op_array->last;
  45         for (opline = op_array->opcodes; opline < end; opline++) {
  46 
  47                 /* Kill JMP-over-NOP-s */
  48                 if (opline->opcode == ZEND_JMP && ZEND_OP1(opline).opline_num > i) {
  49                         /* check if there are only NOPs under the branch */
  50                         zend_op *target = op_array->opcodes + ZEND_OP1(opline).opline_num - 1;
  51 
  52                         while (target->opcode == ZEND_NOP) {
  53                                 target--;
  54                         }
  55                         if (target == opline) {
  56                                 /* only NOPs */
  57                                 opline->opcode = ZEND_NOP;
  58                         }
  59                 }
  60 
  61                 shiftlist[i++] = shift;
  62                 if (opline->opcode == ZEND_NOP) {
  63                         shift++;
  64                 } else {
  65                         if (shift) {
  66                                 op_array->opcodes[new_count] = *opline;
  67                         }
  68                         new_count++;
  69                 }
  70         }
  71 
  72         if (shift) {
  73                 op_array->last = new_count;
  74                 end = op_array->opcodes + op_array->last;
  75 
  76                 /* update JMPs */
  77                 for (opline = op_array->opcodes; opline<end; opline++) {
  78                         switch (opline->opcode) {
  79                                 case ZEND_JMP:
  80                                 case ZEND_FAST_CALL:
  81                                 case ZEND_DECLARE_ANON_CLASS:
  82                                 case ZEND_DECLARE_ANON_INHERITED_CLASS:
  83                                         ZEND_OP1(opline).opline_num -= shiftlist[ZEND_OP1(opline).opline_num];
  84                                         break;
  85                                 case ZEND_JMPZ:
  86                                 case ZEND_JMPNZ:
  87                                 case ZEND_JMPZ_EX:
  88                                 case ZEND_JMPNZ_EX:
  89                                 case ZEND_FE_RESET_R:
  90                                 case ZEND_FE_RESET_RW:
  91                                 case ZEND_NEW:
  92                                 case ZEND_JMP_SET:
  93                                 case ZEND_COALESCE:
  94                                 case ZEND_ASSERT_CHECK:
  95                                         ZEND_OP2(opline).opline_num -= shiftlist[ZEND_OP2(opline).opline_num];
  96                                         break;
  97                                 case ZEND_FE_FETCH_R:
  98                                 case ZEND_FE_FETCH_RW:
  99                                         opline->extended_value -= shiftlist[opline->extended_value];
 100                                         break;
 101                                 case ZEND_JMPZNZ:
 102                                         ZEND_OP2(opline).opline_num -= shiftlist[ZEND_OP2(opline).opline_num];
 103                                         opline->extended_value -= shiftlist[opline->extended_value];
 104                                         break;
 105                                 case ZEND_CATCH:
 106                                         opline->extended_value -= shiftlist[opline->extended_value];
 107                                         break;
 108                         }
 109                 }
 110 
 111                 /* update brk/cont array */
 112                 for (j = 0; j < op_array->last_brk_cont; j++) {
 113                         op_array->brk_cont_array[j].brk -= shiftlist[op_array->brk_cont_array[j].brk];
 114                         op_array->brk_cont_array[j].cont -= shiftlist[op_array->brk_cont_array[j].cont];
 115                         op_array->brk_cont_array[j].start -= shiftlist[op_array->brk_cont_array[j].start];
 116                 }
 117 
 118                 /* update try/catch array */
 119                 for (j = 0; j < op_array->last_try_catch; j++) {
 120                         op_array->try_catch_array[j].try_op -= shiftlist[op_array->try_catch_array[j].try_op];
 121                         op_array->try_catch_array[j].catch_op -= shiftlist[op_array->try_catch_array[j].catch_op];
 122                         if (op_array->try_catch_array[j].finally_op) {
 123                                 op_array->try_catch_array[j].finally_op -= shiftlist[op_array->try_catch_array[j].finally_op];
 124                                 op_array->try_catch_array[j].finally_end -= shiftlist[op_array->try_catch_array[j].finally_end];
 125                         }
 126                 }
 127 
 128                 /* update early binding list */
 129                 if (op_array->early_binding != (uint32_t)-1) {
 130                         uint32_t *opline_num = &op_array->early_binding;
 131 
 132                         do {
 133                                 *opline_num -= shiftlist[*opline_num];
 134                                 opline_num = &ZEND_RESULT(&op_array->opcodes[*opline_num]).opline_num;
 135                         } while (*opline_num != (uint32_t)-1);
 136                 }
 137         }
 138         FREE_ALLOCA(shiftlist);
 139 }

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