root/ext/opcache/Optimizer/zend_optimizer.c

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

DEFINITIONS

This source file includes following definitions.
  1. zend_optimizer_zval_dtor_wrapper
  2. zend_optimizer_collect_constant
  3. zend_optimizer_get_collected_constant
  4. zend_optimizer_lookup_cv
  5. zend_optimizer_add_literal
  6. update_op1_const
  7. update_op2_const
  8. replace_var_by_const
  9. replace_tmp_by_const
  10. zend_optimize
  11. zend_accel_optimize
  12. zend_accel_script_optimize

   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 #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 #define OPTIMIZATION_LEVEL \
  31         ZCG(accel_directives).optimization_level
  32 
  33 static void zend_optimizer_zval_dtor_wrapper(zval *zvalue)
  34 {
  35         zval_dtor(zvalue);
  36 }
  37 
  38 static void zend_optimizer_collect_constant(HashTable **constants, zval *name, zval* value)
  39 {
  40         zval val;
  41 
  42         if (!*constants) {
  43                 *constants = emalloc(sizeof(HashTable));
  44                 zend_hash_init(*constants, 16, NULL, (void (*)(void *))zend_optimizer_zval_dtor_wrapper, 0);
  45         }
  46         val = *value;
  47         zval_copy_ctor(&val);
  48         zend_hash_add(*constants, Z_STRVAL_P(name), Z_STRLEN_P(name)+1, (void**)&val, sizeof(zval), NULL);
  49 }
  50 
  51 static int zend_optimizer_get_collected_constant(HashTable *constants, zval *name, zval* value)
  52 {
  53         zval *val;
  54 
  55         if (zend_hash_find(constants, Z_STRVAL_P(name), Z_STRLEN_P(name)+1, (void**)&val) == SUCCESS) {
  56                 *value = *val;
  57                 zval_copy_ctor(value);
  58                 return 1;
  59         }
  60         return 0;
  61 }
  62 
  63 #if ZEND_EXTENSION_API_NO >= PHP_5_5_X_API_NO
  64 static int zend_optimizer_lookup_cv(zend_op_array *op_array, char* name, int name_len)
  65 {
  66         int i = 0;
  67         ulong hash_value = zend_inline_hash_func(name, name_len+1);
  68 
  69         while (i < op_array->last_var) {
  70                 if (op_array->vars[i].name == name ||
  71                     (op_array->vars[i].hash_value == hash_value &&
  72                      op_array->vars[i].name_len == name_len &&
  73                      memcmp(op_array->vars[i].name, name, name_len) == 0)) {
  74                         return i;
  75                 }
  76                 i++;
  77         }
  78         i = op_array->last_var;
  79         op_array->last_var++;
  80         op_array->vars = erealloc(op_array->vars, op_array->last_var * sizeof(zend_compiled_variable));
  81         if (IS_INTERNED(name)) {
  82                 op_array->vars[i].name = name;
  83         } else {
  84                 op_array->vars[i].name = estrndup(name, name_len);
  85         }
  86         op_array->vars[i].name_len = name_len;
  87         op_array->vars[i].hash_value = hash_value;
  88         return i;
  89 }
  90 #endif
  91 
  92 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
  93 int zend_optimizer_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC)
  94 {
  95         int i = op_array->last_literal;
  96         op_array->last_literal++;
  97         op_array->literals = (zend_literal*)erealloc(op_array->literals, op_array->last_literal * sizeof(zend_literal));
  98         op_array->literals[i].constant = *zv;
  99         op_array->literals[i].hash_value = 0;
 100         op_array->literals[i].cache_slot = -1;
 101         Z_SET_REFCOUNT(op_array->literals[i].constant, 2);
 102         Z_SET_ISREF(op_array->literals[i].constant);
 103         return i;
 104 }
 105 
 106 # define LITERAL_LONG(op, val) do { \
 107                 zval _c; \
 108                 ZVAL_LONG(&_c, val); \
 109                 op.constant = zend_optimizer_add_literal(op_array, &_c TSRMLS_CC); \
 110         } while (0)
 111 
 112 # define LITERAL_BOOL(op, val) do { \
 113                 zval _c; \
 114                 ZVAL_BOOL(&_c, val); \
 115                 op.constant = zend_optimizer_add_literal(op_array, &_c TSRMLS_CC); \
 116         } while (0)
 117 
 118 # define literal_dtor(zv) do { \
 119                 zval_dtor(zv); \
 120                 Z_TYPE_P(zv) = IS_NULL; \
 121         } while (0)
 122 
 123 #define COPY_NODE(target, src) do { \
 124                 target ## _type = src ## _type; \
 125                 target = src; \
 126         } while (0)
 127 
 128 #else
 129 
 130 # define LITERAL_LONG(op, val) ZVAL_LONG(&op.u.constant, val)
 131 
 132 # define LITERAL_BOOL(op, val) ZVAL_BOOL(&op.u.constant, val)
 133 
 134 # define literal_dtor(zv) zval_dtor(zv)
 135 
 136 #define COPY_NODE(target, src) do { \
 137                 target = src; \
 138         } while (0)
 139 
 140 #endif
 141 
 142 static void update_op1_const(zend_op_array *op_array,
 143                              zend_op       *opline,
 144                              zval          *val TSRMLS_DC)
 145 {
 146         if (opline->opcode == ZEND_FREE) {
 147                 MAKE_NOP(opline);
 148                 zval_dtor(val);
 149         } else {
 150                 ZEND_OP1_TYPE(opline) = IS_CONST;
 151 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
 152                 if (Z_TYPE_P(val) == IS_STRING) {
 153                         switch (opline->opcode) {
 154                                 case ZEND_INIT_STATIC_METHOD_CALL:
 155                                 case ZEND_CATCH:
 156                                 case ZEND_FETCH_CONSTANT:
 157                                         opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
 158                                         Z_HASH_P(&ZEND_OP1_LITERAL(opline)) = zend_hash_func(Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)) + 1);
 159                                         op_array->literals[opline->op1.constant].cache_slot = op_array->last_cache_slot++;
 160                                         zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
 161                                         zend_optimizer_add_literal(op_array, val TSRMLS_CC);
 162                                         op_array->literals[opline->op1.constant+1].hash_value = zend_hash_func(Z_STRVAL(op_array->literals[opline->op1.constant+1].constant), Z_STRLEN(op_array->literals[opline->op1.constant+1].constant) + 1);
 163                                         break;
 164                                 case ZEND_DO_FCALL:
 165                                         zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
 166                                         opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
 167                                         Z_HASH_P(&ZEND_OP1_LITERAL(opline)) = zend_hash_func(Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)) + 1);
 168                                         op_array->literals[opline->op1.constant].cache_slot = op_array->last_cache_slot++;
 169                                         break;
 170                                 default:
 171                                         opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
 172                                         Z_HASH_P(&ZEND_OP1_LITERAL(opline)) = zend_hash_func(Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)) + 1);
 173                                         break;
 174                         }
 175                 } else {
 176                         opline->op1.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
 177                 }
 178 #else
 179                 ZEND_OP1_LITERAL(opline) = *val;
 180 #endif
 181         }
 182 }
 183 
 184 static void update_op2_const(zend_op_array *op_array,
 185                              zend_op       *opline,
 186                              zval          *val TSRMLS_DC)
 187 {
 188         ZEND_OP2_TYPE(opline) = IS_CONST;
 189 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
 190         opline->op2.constant = zend_optimizer_add_literal(op_array, val TSRMLS_CC);
 191         if (Z_TYPE_P(val) == IS_STRING) {
 192                 Z_HASH_P(&ZEND_OP2_LITERAL(opline)) = zend_hash_func(Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)) + 1);
 193                 switch (opline->opcode) {
 194                         case ZEND_FETCH_R:
 195                         case ZEND_FETCH_W:
 196                         case ZEND_FETCH_RW:
 197                         case ZEND_FETCH_IS:
 198                         case ZEND_FETCH_UNSET:
 199                         case ZEND_FETCH_FUNC_ARG:
 200                         case ZEND_FETCH_CLASS:
 201                         case ZEND_INIT_FCALL_BY_NAME:
 202                         /*case ZEND_INIT_NS_FCALL_BY_NAME:*/
 203                         case ZEND_UNSET_VAR:
 204                         case ZEND_ISSET_ISEMPTY_VAR:
 205                         case ZEND_ADD_INTERFACE:
 206                         case ZEND_ADD_TRAIT:
 207                                 op_array->literals[opline->op2.constant].cache_slot = op_array->last_cache_slot++;
 208                                 zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
 209                                 zend_optimizer_add_literal(op_array, val TSRMLS_CC);
 210                                 op_array->literals[opline->op2.constant+1].hash_value = zend_hash_func(Z_STRVAL(op_array->literals[opline->op2.constant+1].constant), Z_STRLEN(op_array->literals[opline->op2.constant+1].constant) + 1);
 211                                 break;
 212                         case ZEND_INIT_METHOD_CALL:
 213                         case ZEND_INIT_STATIC_METHOD_CALL:
 214                                 zend_str_tolower(Z_STRVAL_P(val), Z_STRLEN_P(val));
 215                                 zend_optimizer_add_literal(op_array, val TSRMLS_CC);
 216                                 op_array->literals[opline->op2.constant+1].hash_value = zend_hash_func(Z_STRVAL(op_array->literals[opline->op2.constant+1].constant), Z_STRLEN(op_array->literals[opline->op2.constant+1].constant) + 1);
 217                                 /* break missing intentionally */                                               
 218                         /*case ZEND_FETCH_CONSTANT:*/
 219                         case ZEND_ASSIGN_OBJ:
 220                         case ZEND_FETCH_OBJ_R:
 221                         case ZEND_FETCH_OBJ_W:
 222                         case ZEND_FETCH_OBJ_RW:
 223                         case ZEND_FETCH_OBJ_IS:
 224                         case ZEND_FETCH_OBJ_UNSET:
 225                         case ZEND_FETCH_OBJ_FUNC_ARG:
 226                         case ZEND_UNSET_OBJ:
 227                         case ZEND_PRE_INC_OBJ:
 228                         case ZEND_PRE_DEC_OBJ:
 229                         case ZEND_POST_INC_OBJ:
 230                         case ZEND_POST_DEC_OBJ:
 231                         case ZEND_ISSET_ISEMPTY_PROP_OBJ:
 232                                 op_array->literals[opline->op2.constant].cache_slot = op_array->last_cache_slot;
 233                                 op_array->last_cache_slot += 2;
 234                                 break;
 235                         case ZEND_ASSIGN_ADD:
 236                         case ZEND_ASSIGN_SUB:
 237                         case ZEND_ASSIGN_MUL:
 238                         case ZEND_ASSIGN_DIV:
 239                         case ZEND_ASSIGN_MOD:
 240                         case ZEND_ASSIGN_SL:
 241                         case ZEND_ASSIGN_SR:
 242                         case ZEND_ASSIGN_CONCAT:
 243                         case ZEND_ASSIGN_BW_OR:
 244                         case ZEND_ASSIGN_BW_AND:
 245                         case ZEND_ASSIGN_BW_XOR:
 246                                 if (opline->extended_value == ZEND_ASSIGN_OBJ) {
 247                                         op_array->literals[opline->op2.constant].cache_slot = op_array->last_cache_slot;
 248                                         op_array->last_cache_slot += 2;
 249                                 }
 250                                 break;
 251 #if ZEND_EXTENSION_API_NO >= PHP_5_4_X_API_NO
 252                         case ZEND_OP_DATA:
 253                                 if ((opline-1)->opcode == ZEND_ASSIGN_DIM ||
 254                                     ((opline-1)->extended_value == ZEND_ASSIGN_DIM &&
 255                                      ((opline-1)->opcode == ZEND_ASSIGN_ADD ||
 256                                      (opline-1)->opcode == ZEND_ASSIGN_SUB ||
 257                                      (opline-1)->opcode == ZEND_ASSIGN_MUL ||
 258                                      (opline-1)->opcode == ZEND_ASSIGN_DIV ||
 259                                      (opline-1)->opcode == ZEND_ASSIGN_MOD ||
 260                                      (opline-1)->opcode == ZEND_ASSIGN_SL ||
 261                                      (opline-1)->opcode == ZEND_ASSIGN_SR ||
 262                                      (opline-1)->opcode == ZEND_ASSIGN_CONCAT ||
 263                                      (opline-1)->opcode == ZEND_ASSIGN_BW_OR ||
 264                                      (opline-1)->opcode == ZEND_ASSIGN_BW_AND ||
 265                                      (opline-1)->opcode == ZEND_ASSIGN_BW_XOR))) {
 266                                         goto check_numeric;
 267                                 }
 268                                 break;
 269                         case ZEND_ISSET_ISEMPTY_DIM_OBJ:
 270                         case ZEND_ADD_ARRAY_ELEMENT:
 271                         case ZEND_INIT_ARRAY:
 272                         case ZEND_ASSIGN_DIM:
 273                         case ZEND_UNSET_DIM:
 274                         case ZEND_FETCH_DIM_R:
 275                         case ZEND_FETCH_DIM_W:
 276                         case ZEND_FETCH_DIM_RW:
 277                         case ZEND_FETCH_DIM_IS:
 278                         case ZEND_FETCH_DIM_FUNC_ARG:
 279                         case ZEND_FETCH_DIM_UNSET:
 280                         case ZEND_FETCH_DIM_TMP_VAR:
 281 check_numeric:
 282                                 {
 283                                         ulong index;
 284                                         int numeric = 0;
 285 
 286                                         ZEND_HANDLE_NUMERIC_EX(Z_STRVAL_P(val), Z_STRLEN_P(val)+1, index, numeric = 1);
 287                                         if (numeric) {
 288                                                 zval_dtor(val);
 289                                                 ZVAL_LONG(val, index);
 290                                                 op_array->literals[opline->op2.constant].constant = *val;
 291                                 }
 292                                 }
 293                                 break;
 294 #endif
 295                         default:
 296                                 break;
 297                 }
 298         }
 299 #else
 300         ZEND_OP2_LITERAL(opline) = *val;
 301 #endif
 302 }
 303 
 304 static int replace_var_by_const(zend_op_array *op_array,
 305                                 zend_op       *opline,
 306                                 zend_uint      var,
 307                                 zval          *val TSRMLS_DC)
 308 {
 309         zend_op *end = op_array->opcodes + op_array->last;
 310 
 311         while (opline < end) {
 312                 if (ZEND_OP1_TYPE(opline) == IS_VAR &&
 313                         ZEND_OP1(opline).var == var) {
 314                         switch (opline->opcode) {
 315                                 case ZEND_FETCH_DIM_W:
 316                                 case ZEND_FETCH_DIM_RW:
 317                                 case ZEND_FETCH_DIM_FUNC_ARG:
 318                                 case ZEND_FETCH_DIM_UNSET:
 319                                 case ZEND_ASSIGN_DIM:
 320 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
 321                                 case ZEND_SEPARATE:
 322 #endif
 323                                         return 0;
 324                                 case ZEND_SEND_VAR_NO_REF:
 325                                         if (opline->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) {
 326                                                 if (opline->extended_value & ZEND_ARG_SEND_BY_REF) {
 327                                                         return 0;
 328                                                 }
 329                                                 opline->extended_value = ZEND_DO_FCALL;
 330                                         } else {
 331                                                 opline->extended_value = ZEND_DO_FCALL_BY_NAME;
 332                                         }
 333                                         opline->opcode = ZEND_SEND_VAL;
 334                                         break;
 335                                 case ZEND_SWITCH_FREE:
 336                                 case ZEND_CASE: {
 337                                         zend_op *m, *n;
 338                                         int brk = op_array->last_brk_cont;
 339                                         while (brk--) {
 340                                                 if (op_array->brk_cont_array[brk].start <= (opline - op_array->opcodes) &&
 341                                                                 op_array->brk_cont_array[brk].brk > (opline - op_array->opcodes)) {
 342                                                         break;
 343                                                 }
 344                                         }
 345                                         m = opline;
 346                                         n = op_array->opcodes + op_array->brk_cont_array[brk].brk + 1;
 347                                         while (m < n) {
 348                                                 if (ZEND_OP1_TYPE(m) == IS_VAR &&
 349                                                                 ZEND_OP1(m).var == var) {
 350                                                         if (m->opcode == ZEND_CASE) {
 351                                                                 zval old_val;
 352                                                                 old_val = *val;
 353                                                                 zval_copy_ctor(val);
 354                                                                 update_op1_const(op_array, m, val TSRMLS_CC);
 355                                                                 *val = old_val;
 356                                                         } else if (m->opcode == ZEND_SWITCH_FREE) {
 357                                                                 MAKE_NOP(m);
 358                                                         } else {
 359                                                                 ZEND_ASSERT(0);
 360                                                         }
 361                                                 }
 362                                                 m++;
 363                                         }
 364                                         zval_dtor(val);
 365                                         return 1;
 366                                 }
 367                                 case ZEND_FREE:
 368                                         MAKE_NOP(opline);
 369                                         zval_dtor(val);
 370                                         break;
 371                                 default:
 372                                         break;
 373                         } 
 374                         update_op1_const(op_array, opline, val TSRMLS_CC);
 375                         break;
 376                 }
 377                 
 378                 if (ZEND_OP2_TYPE(opline) == IS_VAR &&
 379                         ZEND_OP2(opline).var == var) {
 380                         switch (opline->opcode) {
 381                                 case ZEND_ASSIGN_REF:
 382                                         return 0;
 383                                 default:
 384                                         break;
 385                         }
 386                         update_op2_const(op_array, opline, val TSRMLS_CC);
 387                         break;
 388                 }
 389                 opline++;
 390         }
 391 
 392         return 1;
 393 }
 394 
 395 static void replace_tmp_by_const(zend_op_array *op_array,
 396                                  zend_op       *opline,
 397                                  zend_uint      var,
 398                                  zval          *val
 399                                  TSRMLS_DC)
 400 {
 401         zend_op *end = op_array->opcodes + op_array->last;
 402 
 403         while (opline < end) {
 404                 if (ZEND_OP1_TYPE(opline) == IS_TMP_VAR &&
 405                         ZEND_OP1(opline).var == var) {
 406 
 407                         /* In most cases IS_TMP_VAR operand may be used only once.
 408                          * The operands are usually destroyed by the opcode handler.
 409                          * ZEND_CASE is an exception, that keeps operand unchanged,
 410                          * and allows its reuse. The number of ZEND_CASE instructions
 411                          * usually terminated by ZEND_FREE that finally kills the value.
 412                          */
 413                         if (opline->opcode == ZEND_CASE || opline->opcode == ZEND_FREE) {
 414                                 zend_op *m, *n;
 415                                 int brk = op_array->last_brk_cont;
 416                                 zend_bool in_switch = 0;
 417                                 while (brk--) {
 418                                         if (op_array->brk_cont_array[brk].start <= (opline - op_array->opcodes) &&
 419                                                         op_array->brk_cont_array[brk].brk > (opline - op_array->opcodes)) {
 420                                                 in_switch = 1;
 421                                                 break;
 422                                         }
 423                                 }
 424 
 425                                 if (!in_switch) {
 426                                         MAKE_NOP(opline);
 427                                         zval_dtor(val);
 428                                         break;
 429                                 }
 430 
 431                                 m = opline;
 432                                 n = op_array->opcodes + op_array->brk_cont_array[brk].brk + 1;
 433                                 while (m < n) {
 434                                         if (ZEND_OP1_TYPE(m) == IS_TMP_VAR &&
 435                                                         ZEND_OP1(m).var == var) {
 436                                                 if (m->opcode == ZEND_CASE) {
 437                                                         zval old_val;
 438                                                         old_val = *val;
 439                                                         zval_copy_ctor(val);
 440                                                         update_op1_const(op_array, m, val TSRMLS_CC);
 441                                                         *val = old_val;
 442                                                 } else if (m->opcode == ZEND_FREE) {
 443                                                         MAKE_NOP(m);
 444                                                 } else {
 445                                                         ZEND_ASSERT(0);
 446                                                 }
 447                                         }
 448                                         m++;
 449                                 }
 450                                 zval_dtor(val);
 451                                 break;
 452                         } else {                                
 453                                 update_op1_const(op_array, opline, val TSRMLS_CC);
 454                                 break;
 455                         }
 456                 }
 457 
 458                 if (ZEND_OP2_TYPE(opline) == IS_TMP_VAR &&
 459                         ZEND_OP2(opline).var == var) {
 460 
 461                         update_op2_const(op_array, opline, val TSRMLS_CC);
 462                         /* TMP_VAR may be used only once */
 463                         break;
 464                 }
 465                 opline++;
 466         }
 467 }
 468 
 469 #include "Optimizer/nop_removal.c"
 470 #include "Optimizer/block_pass.c"
 471 #include "Optimizer/optimize_temp_vars_5.c"
 472 #include "Optimizer/compact_literals.c"
 473 #include "Optimizer/optimize_func_calls.c"
 474 
 475 static void zend_optimize(zend_op_array           *op_array,
 476                           zend_persistent_script  *script,
 477                           HashTable              **constants TSRMLS_DC)
 478 {
 479         if (op_array->type == ZEND_EVAL_CODE ||
 480             (op_array->fn_flags & ZEND_ACC_INTERACTIVE)) {
 481                 return;
 482         }
 483 
 484         /* pass 1
 485          * - substitute persistent constants (true, false, null, etc)
 486          * - perform compile-time evaluation of constant binary and unary operations
 487          * - optimize series of ADD_STRING and/or ADD_CHAR
 488          * - convert CAST(IS_BOOL,x) into BOOL(x)
 489          */
 490 #include "Optimizer/pass1_5.c"
 491 
 492         /* pass 2:
 493          * - convert non-numeric constants to numeric constants in numeric operators
 494          * - optimize constant conditional JMPs
 495          * - optimize static BRKs and CONTs
 496          * - pre-evaluate constant function calls
 497          */
 498 #include "Optimizer/pass2.c"
 499 
 500         /* pass 3:
 501          * - optimize $i = $i+expr to $i+=expr
 502          * - optimize series of JMPs
 503          * - change $i++ to ++$i where possible
 504          */
 505 #include "Optimizer/pass3.c"
 506 
 507 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
 508         /* pass 4:
 509          * - INIT_FCALL_BY_NAME -> DO_FCALL
 510          */
 511         if (ZEND_OPTIMIZER_PASS_4 & OPTIMIZATION_LEVEL) {
 512                 optimize_func_calls(op_array, script TSRMLS_CC);
 513         }
 514 #endif
 515 
 516         /* pass 5:
 517          * - CFG optimization
 518          */
 519 #include "Optimizer/pass5.c"
 520 
 521         /* pass 9:
 522          * - Optimize temp variables usage
 523          */
 524 #include "Optimizer/pass9.c"
 525 
 526         /* pass 10:
 527          * - remove NOPs
 528          */
 529 #include "Optimizer/pass10.c"
 530 
 531 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
 532         /* pass 11:
 533          * - Compact literals table 
 534          */
 535         if (ZEND_OPTIMIZER_PASS_11 & OPTIMIZATION_LEVEL) {
 536                 optimizer_compact_literals(op_array TSRMLS_CC);
 537         }
 538 #endif
 539 }
 540 
 541 static void zend_accel_optimize(zend_op_array           *op_array,
 542                                 zend_persistent_script  *script,
 543                                 HashTable              **constants TSRMLS_DC)
 544 {
 545         zend_op *opline, *end;
 546 
 547         /* Revert pass_two() */
 548         opline = op_array->opcodes;
 549         end = opline + op_array->last;
 550         while (opline < end) {
 551 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
 552                 if (opline->op1_type == IS_CONST) {
 553                         opline->op1.constant = opline->op1.literal - op_array->literals;
 554                 }
 555                 if (opline->op2_type == IS_CONST) {
 556                         opline->op2.constant = opline->op2.literal - op_array->literals;
 557                 }
 558 #endif
 559                 switch (opline->opcode) {
 560                         case ZEND_JMP:
 561 #if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO
 562                         case ZEND_GOTO:
 563 #endif
 564 #if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
 565                         case ZEND_FAST_CALL:
 566 #endif
 567                                 ZEND_OP1(opline).opline_num = ZEND_OP1(opline).jmp_addr - op_array->opcodes;
 568                                 break;
 569                         case ZEND_JMPZ:
 570                         case ZEND_JMPNZ:
 571                         case ZEND_JMPZ_EX:
 572                         case ZEND_JMPNZ_EX:
 573 #if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO
 574                         case ZEND_JMP_SET:
 575 #endif
 576 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
 577                         case ZEND_JMP_SET_VAR:
 578 #endif
 579                                 ZEND_OP2(opline).opline_num = ZEND_OP2(opline).jmp_addr - op_array->opcodes;
 580                                 break;
 581                 }
 582                 opline++;
 583         }
 584 
 585         /* Do actual optimizations */
 586         zend_optimize(op_array, script, constants TSRMLS_CC);   
 587         
 588         /* Redo pass_two() */
 589         opline = op_array->opcodes;
 590         end = opline + op_array->last;
 591         while (opline < end) {
 592 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
 593                 if (opline->op1_type == IS_CONST) {
 594                         opline->op1.zv = &op_array->literals[opline->op1.constant].constant;
 595                 }
 596                 if (opline->op2_type == IS_CONST) {
 597                         opline->op2.zv = &op_array->literals[opline->op2.constant].constant;
 598                 }
 599 #endif
 600                 switch (opline->opcode) {
 601                         case ZEND_JMP:
 602 #if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO
 603                         case ZEND_GOTO:
 604 #endif
 605 #if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
 606                         case ZEND_FAST_CALL:
 607 #endif
 608                                 ZEND_OP1(opline).jmp_addr = &op_array->opcodes[ZEND_OP1(opline).opline_num];
 609                                 break;
 610                         case ZEND_JMPZ:
 611                         case ZEND_JMPNZ:
 612                         case ZEND_JMPZ_EX:
 613                         case ZEND_JMPNZ_EX:
 614 #if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO
 615                         case ZEND_JMP_SET:
 616 #endif
 617 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
 618                         case ZEND_JMP_SET_VAR:
 619 #endif
 620                                 ZEND_OP2(opline).jmp_addr = &op_array->opcodes[ZEND_OP2(opline).opline_num];
 621                                 break;
 622                 }
 623                 ZEND_VM_SET_OPCODE_HANDLER(opline);
 624                 opline++;
 625         }
 626 }
 627 
 628 int zend_accel_script_optimize(zend_persistent_script *script TSRMLS_DC)
 629 {
 630         Bucket *p, *q;
 631         HashTable *constants = NULL;
 632 
 633         zend_accel_optimize(&script->main_op_array, script, &constants TSRMLS_CC);
 634 
 635         p = script->function_table.pListHead;
 636         while (p) {
 637                 zend_op_array *op_array = (zend_op_array*)p->pData;
 638                 zend_accel_optimize(op_array, script, &constants TSRMLS_CC);
 639                 p = p->pListNext;
 640         }
 641 
 642         p = script->class_table.pListHead;
 643         while (p) {
 644                 zend_class_entry *ce = (zend_class_entry*)p->pDataPtr;
 645                 q = ce->function_table.pListHead;
 646                 while (q) {
 647                         zend_op_array *op_array = (zend_op_array*)q->pData;
 648                         if (op_array->scope == ce) {
 649                                 zend_accel_optimize(op_array, script, &constants TSRMLS_CC);
 650                         } else if (op_array->type == ZEND_USER_FUNCTION) {
 651                                 zend_op_array *orig_op_array;
 652                                 if (zend_hash_find(&op_array->scope->function_table, q->arKey, q->nKeyLength, (void**)&orig_op_array) == SUCCESS) {
 653                                         HashTable *ht = op_array->static_variables;
 654                                         *op_array = *orig_op_array;
 655                                         op_array->static_variables = ht;
 656                                 }
 657                         }
 658                         q = q->pListNext;
 659                 }
 660                 p = p->pListNext;
 661         }
 662 
 663         if (constants) {
 664                 zend_hash_destroy(constants);
 665                 efree(constants);
 666         }
 667 
 668         return 1;
 669 }

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