root/ext/opcache/Optimizer/pass1_5.c

/* [<][>][^][v][top][bottom][index][help] */
   1 /* pass 1
   2  * - substitute persistent constants (true, false, null, etc)
   3  * - perform compile-time evaluation of constant binary and unary operations
   4  * - optimize series of ADD_STRING and/or ADD_CHAR
   5  * - convert CAST(IS_BOOL,x) into BOOL(x)
   6  * - pre-evaluate constant function calls
   7  */
   8 
   9 #if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO
  10 # define ZEND_IS_CONSTANT_TYPE(t)       (((t) & IS_CONSTANT_TYPE_MASK) == IS_CONSTANT)
  11 #else
  12 # define ZEND_IS_CONSTANT_TYPE(t)       ((t) == IS_CONSTANT)
  13 #endif
  14 
  15 if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
  16         int i = 0;
  17         zend_op *opline = op_array->opcodes;
  18         zend_op *end = opline + op_array->last;
  19         zend_bool collect_constants = (ZEND_OPTIMIZER_PASS_15 & OPTIMIZATION_LEVEL)?
  20                 (op_array == &script->main_op_array) : 0;
  21 
  22         while (opline < end) {
  23                 switch (opline->opcode) {
  24                 case ZEND_ADD:
  25                 case ZEND_SUB:
  26                 case ZEND_MUL:
  27                 case ZEND_DIV:
  28                 case ZEND_MOD:
  29 #if ZEND_EXTENSION_API_NO >= PHP_5_6_X_API_NO
  30                 case ZEND_POW:
  31 #endif
  32                 case ZEND_SL:
  33                 case ZEND_SR:
  34                 case ZEND_CONCAT:
  35                 case ZEND_IS_EQUAL:
  36                 case ZEND_IS_NOT_EQUAL:
  37                 case ZEND_IS_SMALLER:
  38                 case ZEND_IS_SMALLER_OR_EQUAL:
  39                 case ZEND_IS_IDENTICAL:
  40                 case ZEND_IS_NOT_IDENTICAL:
  41                 case ZEND_BW_OR:
  42                 case ZEND_BW_AND:
  43                 case ZEND_BW_XOR:
  44                 case ZEND_BOOL_XOR:
  45                         if (ZEND_OP1_TYPE(opline) == IS_CONST &&
  46                                 ZEND_OP2_TYPE(opline) == IS_CONST) {
  47                                 /* binary operation with constant operands */
  48                                 int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC) = get_binary_op(opline->opcode);
  49                                 zend_uint tv = ZEND_RESULT(opline).var;         /* temporary variable */
  50                                 zval result;
  51                                 int er;
  52 
  53                                 if (opline->opcode == ZEND_DIV &&
  54                                         Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_LONG &&
  55                                         Z_LVAL(ZEND_OP2_LITERAL(opline)) == 0) {
  56                                         /* div by 0 */
  57                                         break;
  58                                 }
  59                                 er = EG(error_reporting);
  60                                 EG(error_reporting) = 0;
  61                                 /* evaluate constant expression */
  62                                 if (binary_op(&result, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline) TSRMLS_CC) != SUCCESS) {
  63                                         EG(error_reporting) = er;
  64                                         break;
  65                                 }
  66                                 EG(error_reporting) = er;
  67                                 PZ_SET_REFCOUNT_P(&result, 1);
  68                                 PZ_UNSET_ISREF_P(&result);
  69 
  70                                 literal_dtor(&ZEND_OP1_LITERAL(opline));
  71                                 literal_dtor(&ZEND_OP2_LITERAL(opline));
  72                                 MAKE_NOP(opline);
  73 
  74                                 replace_tmp_by_const(op_array, opline + 1, tv, &result TSRMLS_CC);
  75                         }
  76                         break;
  77 
  78                 case ZEND_CAST:
  79                         if (ZEND_OP1_TYPE(opline) == IS_CONST &&
  80                                 opline->extended_value != IS_ARRAY &&
  81                                 opline->extended_value != IS_OBJECT &&
  82                                 opline->extended_value != IS_RESOURCE) {
  83                                 /* cast of constant operand */
  84                                 zend_uint tv = ZEND_RESULT(opline).var;         /* temporary variable */
  85                                 zval res;
  86                                 res = ZEND_OP1_LITERAL(opline);
  87                                 zval_copy_ctor(&res);
  88                                 switch (opline->extended_value) {
  89                                         case IS_NULL:
  90                                                 convert_to_null(&res);
  91                                                 break;
  92                                         case IS_BOOL:
  93                                                 convert_to_boolean(&res);
  94                                                 break;
  95                                         case IS_LONG:
  96                                                 convert_to_long(&res);
  97                                                 break;
  98                                         case IS_DOUBLE:
  99                                                 convert_to_double(&res);
 100                                                 break;
 101                                         case IS_STRING:
 102                                                 convert_to_string(&res);
 103                                                 break;
 104                                 }
 105 
 106                                 literal_dtor(&ZEND_OP1_LITERAL(opline));
 107                                 MAKE_NOP(opline);
 108 
 109                                 replace_tmp_by_const(op_array, opline + 1, tv, &res TSRMLS_CC);
 110                         } else if (opline->extended_value == IS_BOOL) {
 111                                 /* T = CAST(X, IS_BOOL) => T = BOOL(X) */
 112                                 opline->opcode = ZEND_BOOL;
 113                                 opline->extended_value = 0;
 114                         }
 115                         break;
 116 
 117                 case ZEND_BW_NOT:
 118                 case ZEND_BOOL_NOT:
 119                         if (ZEND_OP1_TYPE(opline) == IS_CONST) {
 120                                 /* unary operation on constant operand */
 121                                 unary_op_type unary_op = get_unary_op(opline->opcode);
 122                                 zval result;
 123                                 zend_uint tv = ZEND_RESULT(opline).var;         /* temporary variable */
 124                                 int er;
 125 
 126                                 er = EG(error_reporting);
 127                                 EG(error_reporting) = 0;
 128 #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
 129                                 if (unary_op(&result, &ZEND_OP1_LITERAL(opline)) != SUCCESS) {
 130 #else
 131                                 if (unary_op(&result, &ZEND_OP1_LITERAL(opline) TSRMLS_CC) != SUCCESS) {
 132 #endif
 133                                         EG(error_reporting) = er;
 134                                         break;
 135                                 }
 136                                 EG(error_reporting) = er;
 137                                 PZ_SET_REFCOUNT_P(&result, 1);
 138                                 PZ_UNSET_ISREF_P(&result);
 139 
 140                                 literal_dtor(&ZEND_OP1_LITERAL(opline));
 141                                 MAKE_NOP(opline);
 142 
 143                                 replace_tmp_by_const(op_array, opline + 1, tv, &result TSRMLS_CC);
 144                         }
 145                         break;
 146 
 147                 case ZEND_ADD_STRING:
 148                 case ZEND_ADD_CHAR:
 149                         {
 150                                 zend_op *next_op = opline + 1;
 151                                 int requires_conversion = (opline->opcode == ZEND_ADD_CHAR? 1 : 0);
 152                                 size_t final_length = 0;
 153                                 char *ptr;
 154                                 zend_op *last_op;
 155 
 156                                 /* There is always a ZEND_RETURN at the end
 157                                 if (next_op>=end) {
 158                                         break;
 159                                 }
 160                                 */
 161                                 while (next_op->opcode == ZEND_ADD_STRING || next_op->opcode == ZEND_ADD_CHAR) {
 162                                         if (ZEND_RESULT(opline).var != ZEND_RESULT(next_op).var) {
 163                                                 break;
 164                                         }
 165                                         if (next_op->opcode == ZEND_ADD_CHAR) {
 166                                                 final_length += 1;
 167                                         } else { /* ZEND_ADD_STRING */
 168                                                 final_length += ZEND_OP2_LITERAL(next_op).value.str.len;
 169                                         }
 170                                         next_op++;
 171                                 }
 172                                 if (final_length == 0) {
 173                                         break;
 174                                 }
 175                                 last_op = next_op;
 176                                 final_length += (requires_conversion? 1 : ZEND_OP2_LITERAL(opline).value.str.len);
 177                                 ptr = (char *)emalloc(final_length + 1);
 178                                 ptr[final_length] = '\0';
 179                                 if (requires_conversion) { /* ZEND_ADD_CHAR */
 180                                         char chval = (char)ZEND_OP2_LITERAL(opline).value.lval;
 181 
 182                                         ZEND_OP2_LITERAL(opline).value.str.val = ptr;
 183                                         ptr[0] = chval;
 184                                         ZEND_OP2_LITERAL(opline).type = IS_STRING;
 185                                         opline->opcode = ZEND_ADD_STRING;
 186                                         ptr++;
 187                                 } else { /* ZEND_ADD_STRING */
 188                                         memcpy(ptr, Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)));
 189                                         if (!IS_INTERNED(Z_STRVAL(ZEND_OP2_LITERAL(opline)))) {
 190                                                 efree(Z_STRVAL(ZEND_OP2_LITERAL(opline)));
 191                                         }
 192                                         Z_STRVAL(ZEND_OP2_LITERAL(opline)) = ptr;
 193                                         ptr += Z_STRLEN(ZEND_OP2_LITERAL(opline));
 194                                 }
 195                                 ZEND_OP2_LITERAL(opline).value.str.len = final_length;
 196                                 next_op = opline + 1;
 197                                 while (next_op < last_op) {
 198                                         if (next_op->opcode == ZEND_ADD_STRING) {
 199                                                 memcpy(ptr, ZEND_OP2_LITERAL(next_op).value.str.val, ZEND_OP2_LITERAL(next_op).value.str.len);
 200                                                 ptr += ZEND_OP2_LITERAL(next_op).value.str.len;
 201                                                 literal_dtor(&ZEND_OP2_LITERAL(next_op));
 202                                         } else { /* ZEND_ADD_CHAR */
 203                                                 *ptr = (char)ZEND_OP2_LITERAL(next_op).value.lval;
 204                                                 ptr++;
 205                                         }
 206                                         MAKE_NOP(next_op);
 207                                         next_op++;
 208                                 }
 209                                 if (!((ZEND_OPTIMIZER_PASS_5|ZEND_OPTIMIZER_PASS_10) & OPTIMIZATION_LEVEL)) {
 210                                         /* NOP removal is disabled => insert JMP over NOPs */
 211                                         if (last_op-opline >= 3) { /* If we have more than 2 NOPS then JMP over them */
 212                                                 (opline + 1)->opcode = ZEND_JMP;
 213                                                 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 */
 214                                         }
 215                                 }
 216                         }
 217                         break;
 218 
 219                 case ZEND_FETCH_CONSTANT:
 220                         if (ZEND_OP1_TYPE(opline) == IS_UNUSED &&
 221                                 ZEND_OP2_TYPE(opline) == IS_CONST &&
 222                                 Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING &&
 223                                 Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("__COMPILER_HALT_OFFSET__") - 1 &&
 224                                 memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)), "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1) == 0) {
 225                                 /* substitute __COMPILER_HALT_OFFSET__ constant */
 226                                 zend_bool orig_in_execution = EG(in_execution);
 227                                 zend_op_array *orig_op_array = EG(active_op_array);
 228                                 zval offset;
 229 
 230                                 EG(in_execution) = 1;
 231                                 EG(active_op_array) = op_array;
 232                                 if (zend_get_constant("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1, &offset TSRMLS_CC)) {
 233                                         zend_uint tv = ZEND_RESULT(opline).var;
 234 
 235                                         literal_dtor(&ZEND_OP2_LITERAL(opline));
 236                                         MAKE_NOP(opline);
 237                                         replace_tmp_by_const(op_array, opline, tv, &offset TSRMLS_CC);
 238                                 }
 239                                 EG(active_op_array) = orig_op_array;
 240                                 EG(in_execution) = orig_in_execution;
 241                                 break;
 242                         }
 243 
 244                         if (ZEND_OP1_TYPE(opline) == IS_UNUSED &&
 245                                 ZEND_OP2_TYPE(opline) == IS_CONST &&
 246                                 ZEND_OP2_LITERAL(opline).type == IS_STRING) {
 247                                 /* substitute persistent constants */
 248                                 zend_uint tv = ZEND_RESULT(opline).var;
 249                                 zval c;
 250 
 251                                 if (!zend_get_persistent_constant(Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)), &c, 1 TSRMLS_CC)) {
 252                                         if (!*constants || !zend_optimizer_get_collected_constant(*constants, &ZEND_OP2_LITERAL(opline), &c)) {
 253                                                 break;
 254                                         }
 255                                 }
 256                                 if (Z_TYPE(c) == IS_CONSTANT_AST) {
 257                                         break;
 258                                 }
 259                                 literal_dtor(&ZEND_OP2_LITERAL(opline));
 260                                 MAKE_NOP(opline);
 261                                 replace_tmp_by_const(op_array, opline, tv, &c TSRMLS_CC);
 262                         }
 263 
 264 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
 265                         /* class constant */
 266                         if (ZEND_OP1_TYPE(opline) != IS_UNUSED &&
 267                             ZEND_OP2_TYPE(opline) == IS_CONST &&
 268                                 ZEND_OP2_LITERAL(opline).type == IS_STRING) {
 269 
 270                                 zend_class_entry **pce = NULL;
 271 
 272                                 if (ZEND_OP1_TYPE(opline) == IS_CONST &&
 273                                 ZEND_OP1_LITERAL(opline).type == IS_STRING) {
 274                                         /* for A::B */
 275                                         if (op_array->scope && 
 276                                                 !strncasecmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
 277                                                 op_array->scope->name, Z_STRLEN(ZEND_OP1_LITERAL(opline)) + 1)) {
 278                                                 pce = &op_array->scope;
 279                                         } else { 
 280                                                 if (zend_hash_quick_find(EG(class_table), 
 281                                                                 Z_STRVAL(op_array->literals[opline->op1.constant + 1].constant), 
 282                                                                 Z_STRLEN(op_array->literals[opline->op1.constant].constant) + 1, 
 283                                                                 Z_HASH_P(&op_array->literals[opline->op1.constant + 1].constant),
 284                                                                 (void **)&pce) == FAILURE ||
 285                                                                 ((*pce)->type == ZEND_INTERNAL_CLASS &&
 286                                                                  (*pce)->info.internal.module->type != MODULE_PERSISTENT) ||
 287                                                                 ((*pce)->type == ZEND_USER_CLASS &&
 288                                                                  ZEND_CE_FILENAME(*pce) != op_array->filename)) {
 289                                                         break;
 290                                                 }
 291                                         }
 292                                 } else if (op_array->scope &&
 293                                         ZEND_OP1_TYPE(opline) == IS_VAR &&
 294                                         (opline - 1)->opcode == ZEND_FETCH_CLASS && 
 295                                         (ZEND_OP1_TYPE(opline - 1) == IS_UNUSED &&
 296                                         ((opline - 1)->extended_value & ~ZEND_FETCH_CLASS_NO_AUTOLOAD) == ZEND_FETCH_CLASS_SELF) &&
 297                                         ZEND_RESULT((opline - 1)).var == ZEND_OP1(opline).var) {
 298                                         /* for self::B */
 299                                         pce = &op_array->scope;
 300                                 }
 301 
 302                                 if (pce) {
 303                                         zend_uint tv = ZEND_RESULT(opline).var;
 304                                         zval **c, t;
 305 
 306                                         if (zend_hash_find(&(*pce)->constants_table,
 307                                                         Z_STRVAL(ZEND_OP2_LITERAL(opline)),
 308                                                         Z_STRLEN(ZEND_OP2_LITERAL(opline)) + 1,
 309                                                         (void **) &c) == SUCCESS) {
 310                                                 if (Z_TYPE_PP(c) == IS_CONSTANT_AST) {
 311                                                         break;
 312                                                 }
 313                                                 if (ZEND_IS_CONSTANT_TYPE(Z_TYPE_PP(c))) { 
 314                                                         if (!zend_get_persistent_constant(Z_STRVAL_PP(c), Z_STRLEN_PP(c), &t, 1 TSRMLS_CC) ||
 315                                                             ZEND_IS_CONSTANT_TYPE(Z_TYPE(t))) {
 316                                                                 break;
 317                                                         }
 318                                                 } else if (Z_TYPE_PP(c) <= IS_BOOL || Z_TYPE_PP(c) == IS_STRING) {
 319                                                         t = **c;
 320                                                         zval_copy_ctor(&t);
 321                                                 } else {
 322                                                         break;
 323                                                 }
 324 
 325                                                 if (ZEND_OP1_TYPE(opline) == IS_CONST) {
 326                                                         literal_dtor(&ZEND_OP1_LITERAL(opline));
 327                                                 } else {
 328                                                         MAKE_NOP((opline - 1));
 329                                                 }
 330                                                 literal_dtor(&ZEND_OP2_LITERAL(opline));
 331                                                 MAKE_NOP(opline);
 332                                                 replace_tmp_by_const(op_array, opline, tv, &t TSRMLS_CC);
 333                                         }
 334                                 }
 335                         }
 336 #endif
 337                         break;
 338 
 339                 case ZEND_DO_FCALL:
 340                         /* define("name", scalar); */
 341                         if (collect_constants &&
 342                             opline->extended_value == 2 &&
 343                             ZEND_OP1_TYPE(opline) == IS_CONST &&
 344                             Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING &&
 345                             Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("define")-1 &&
 346                             zend_binary_strcasecmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)), "define", sizeof("define")-1) == 0 &&
 347                             (opline-1)->opcode == ZEND_SEND_VAL &&
 348                             ZEND_OP1_TYPE(opline-1) == IS_CONST &&
 349                             (Z_TYPE(ZEND_OP1_LITERAL(opline-1)) <= IS_BOOL ||
 350                              Z_TYPE(ZEND_OP1_LITERAL(opline-1)) == IS_STRING) &&
 351                             (opline-2)->opcode == ZEND_SEND_VAL &&
 352                             ZEND_OP1_TYPE(opline-2) == IS_CONST &&
 353                             Z_TYPE(ZEND_OP1_LITERAL(opline-2)) == IS_STRING) {
 354                                 zend_optimizer_collect_constant(constants, &ZEND_OP1_LITERAL(opline-2), &ZEND_OP1_LITERAL(opline-1));
 355                                 break;
 356                         } else {
 357                                 /* don't colllect constants after any other function call */
 358                                 collect_constants = 0;
 359                         }
 360 
 361                         /* pre-evaluate constant functions:
 362                            defined(x)
 363                            constant(x)
 364                            function_exists(x)
 365                            is_callable(x)
 366                            extension_loaded(x)
 367                         */
 368                         if (opline->extended_value == 1 && (opline - 1)->opcode == ZEND_SEND_VAL &&
 369                                 ZEND_OP1_TYPE(opline - 1) == IS_CONST && ZEND_OP1_LITERAL(opline - 1).type == IS_STRING &&
 370                                 ZEND_OP1_TYPE(opline) == IS_CONST && ZEND_OP1_LITERAL(opline).type == IS_STRING) {
 371                                 if ((Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("function_exists")-1 &&
 372                                         !memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
 373                                                 "function_exists", sizeof("function_exists")-1)) ||
 374                                         (Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("is_callable")-1 &&
 375                                         !memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
 376                                                 "is_callable", sizeof("is_callable")))) {
 377                                         zend_internal_function *func;
 378                                         char *lc_name = zend_str_tolower_dup(
 379                                                         Z_STRVAL(ZEND_OP1_LITERAL(opline - 1)), Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)));
 380                                         
 381                                         if (zend_hash_find(EG(function_table), lc_name, Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)) + 1,
 382                                                                 (void *)&func) == SUCCESS
 383                                                  && func->type == ZEND_INTERNAL_FUNCTION
 384                                                  && func->module->type == MODULE_PERSISTENT
 385 #ifdef ZEND_WIN32
 386                                                  && func->module->handle == NULL
 387 #endif
 388                                                 ) {
 389                                                 zval t;
 390                                                 if (Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("is_callable") - 1 ||
 391                                                            func->handler != ZEND_FN(display_disabled_function)) {
 392                                                         ZVAL_BOOL(&t, 1);
 393                                                 } else {
 394                                                         ZVAL_BOOL(&t, 0);
 395                                                 }
 396                                                 if (replace_var_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC)) {
 397                                                         literal_dtor(&ZEND_OP1_LITERAL(opline - 1));
 398                                                         MAKE_NOP((opline - 1));
 399                                                         literal_dtor(&ZEND_OP1_LITERAL(opline));
 400                                                         MAKE_NOP(opline);
 401                                                 }
 402                                         }
 403                                         efree(lc_name);
 404                                 } else if (Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("extension_loaded")-1 &&
 405                                         !memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
 406                                                 "extension_loaded", sizeof("extension_loaded")-1)) {
 407                                         zval t;
 408                                         zend_module_entry *m;
 409                                         char *lc_name = zend_str_tolower_dup(
 410                                                         Z_STRVAL(ZEND_OP1_LITERAL(opline - 1)), Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)));
 411                                         int found = zend_hash_find(&module_registry,
 412                                                         lc_name, Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)) + 1, (void *)&m) == SUCCESS;
 413 
 414                                         efree(lc_name);
 415                                         if (!found) {
 416                                                 if (!PG(enable_dl)) {
 417                                                         break;
 418                                                 } else {
 419                                                         ZVAL_BOOL(&t, 0);
 420                                                 }
 421                                         } else {
 422                                                 if (m->type == MODULE_PERSISTENT
 423 #ifdef ZEND_WIN32
 424                                                  && m->handle == NULL
 425 #endif
 426                                                 ) {
 427                                                         ZVAL_BOOL(&t, 1);
 428                                                 } else {
 429                                                         break;
 430                                                 }
 431                                         } 
 432 
 433                                         if (replace_var_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC)) {
 434                                                 literal_dtor(&ZEND_OP1_LITERAL(opline - 1));
 435                                                 MAKE_NOP((opline - 1));
 436                                                 literal_dtor(&ZEND_OP1_LITERAL(opline));
 437                                                 MAKE_NOP(opline);
 438                                         }
 439                                 } else if (Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("defined")-1 &&
 440                                         !memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
 441                                                 "defined", sizeof("defined")-1)) {
 442                                         zval t;
 443 
 444                                         if (zend_get_persistent_constant(Z_STRVAL(ZEND_OP1_LITERAL(opline - 1)),
 445                                                 Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)), &t, 0 TSRMLS_CC)) {
 446 
 447                                                 ZVAL_BOOL(&t, 1);
 448                                                 if (replace_var_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC)) {
 449                                                         literal_dtor(&ZEND_OP1_LITERAL(opline - 1));
 450                                                         MAKE_NOP((opline - 1));
 451                                                         literal_dtor(&ZEND_OP1_LITERAL(opline));
 452                                                         MAKE_NOP(opline);
 453                                                 }
 454                                         }
 455                                 } else if (Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("constant")-1 &&
 456                                         !memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
 457                                                 "constant", sizeof("constant")-1)) {
 458                                         zval t;
 459                                         
 460                                         if (zend_get_persistent_constant(Z_STRVAL(ZEND_OP1_LITERAL(opline - 1)),
 461                                                 Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)), &t, 1 TSRMLS_CC)) {
 462                                                 if (replace_var_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC)) {
 463                                                         literal_dtor(&ZEND_OP1_LITERAL(opline - 1));
 464                                                         MAKE_NOP((opline - 1));
 465                                                         literal_dtor(&ZEND_OP1_LITERAL(opline));
 466                                                         MAKE_NOP(opline);
 467                                                 }
 468                                         }
 469                                 } else if ((!zend_hash_exists(&module_registry, "mbstring", sizeof("mbstring")) ||
 470                                                         zend_ini_long("mbstring.func_overload",
 471                                                                 sizeof("mbstring.func_overload"), 0) < 2 /* MB_OVERLOAD_STRING */) &&
 472                                                 Z_STRLEN(ZEND_OP1_LITERAL(opline)) == sizeof("strlen") - 1 &&
 473                                                 !memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)), "strlen", sizeof("strlen") - 1)) {
 474                                         zval t;
 475 
 476                                         ZVAL_LONG(&t, Z_STRLEN(ZEND_OP1_LITERAL(opline - 1)));
 477                                         if (replace_var_by_const(op_array, opline + 1, ZEND_RESULT(opline).var, &t TSRMLS_CC)) {
 478                                                 literal_dtor(&ZEND_OP1_LITERAL(opline - 1));
 479                                                 MAKE_NOP((opline - 1));
 480                                                 literal_dtor(&ZEND_OP1_LITERAL(opline));
 481                                                 MAKE_NOP(opline);
 482                                         }
 483                                 }
 484                         }                       
 485                         break;
 486 #if ZEND_EXTENSION_API_NO > PHP_5_2_X_API_NO
 487                 case ZEND_DECLARE_CONST:
 488                         if (collect_constants &&
 489                             Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING &&
 490                             (Z_TYPE(ZEND_OP2_LITERAL(opline)) <= IS_BOOL ||
 491                              Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING)) {
 492                                 zend_optimizer_collect_constant(constants, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline));
 493                         }
 494                         break;
 495 #endif
 496 
 497                 case ZEND_RETURN:
 498 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
 499                 case ZEND_RETURN_BY_REF:
 500 #endif
 501 #if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
 502                 case ZEND_GENERATOR_RETURN:
 503 #endif
 504                 case ZEND_EXIT:
 505                 case ZEND_THROW:
 506                 case ZEND_CATCH:
 507                 case ZEND_BRK:
 508                 case ZEND_CONT:
 509 #if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
 510                 case ZEND_GOTO:
 511 #endif
 512 #if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
 513                 case ZEND_FAST_CALL:
 514                 case ZEND_FAST_RET:
 515 #endif
 516                 case ZEND_JMP:
 517                 case ZEND_JMPZNZ:
 518                 case ZEND_JMPZ:
 519                 case ZEND_JMPNZ:
 520                 case ZEND_JMPZ_EX:
 521                 case ZEND_JMPNZ_EX:
 522                 case ZEND_FE_RESET:
 523                 case ZEND_FE_FETCH:
 524                 case ZEND_NEW:
 525                 case ZEND_DO_FCALL_BY_NAME:
 526 #if ZEND_EXTENSION_API_NO >= PHP_5_3_X_API_NO
 527                 case ZEND_JMP_SET:
 528 #endif
 529 #if ZEND_EXTENSION_API_NO > PHP_5_3_X_API_NO
 530                 case ZEND_JMP_SET_VAR:
 531 #endif
 532                         collect_constants = 0;
 533                         break;
 534 
 535 #if ZEND_EXTENSION_API_NO >= PHP_5_5_X_API_NO
 536                 case ZEND_FETCH_R:
 537                 case ZEND_FETCH_W:
 538                 case ZEND_FETCH_RW:
 539                 case ZEND_FETCH_FUNC_ARG:
 540                 case ZEND_FETCH_IS:
 541                 case ZEND_FETCH_UNSET:
 542                         if (opline != op_array->opcodes &&
 543                             (opline-1)->opcode == ZEND_BEGIN_SILENCE &&
 544                             (opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_LOCAL &&
 545                                 opline->op1_type == IS_CONST &&
 546                             opline->op2_type == IS_UNUSED &&
 547                             Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING &&
 548                             (Z_STRLEN(ZEND_OP1_LITERAL(opline)) != sizeof("this")-1 ||
 549                              memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)), "this", sizeof("this") - 1) != 0)) {
 550 
 551                             int var = opline->result.var;
 552                             int level = 0;
 553                                 zend_op *op = opline + 1;
 554                                 zend_op *use = NULL;
 555 
 556                                 while (op < end) {
 557                                         if (op->opcode == ZEND_BEGIN_SILENCE) {
 558                                                 level++;
 559                                         } else if (op->opcode == ZEND_END_SILENCE) {
 560                                                 if (level == 0) {
 561                                                         break;
 562                                                 } else {
 563                                                         level--;
 564                                                 }
 565                                         }
 566                                         if (op->op1_type == IS_VAR && op->op1.var == var) {
 567                                                 if (use) {
 568                                                         /* used more than once */
 569                                                         use = NULL;
 570                                                         break;
 571                                                 }
 572                                                 use = op;
 573                                         } else if (op->op2_type == IS_VAR && op->op2.var == var) {
 574                                                 if (use) {
 575                                                         /* used more than once */
 576                                                         use = NULL;
 577                                                         break;
 578                                                 }
 579                                                 use = op;
 580                                         }
 581                                         op++;
 582                                 }
 583                                 if (use) {
 584                                         if (use->op1_type == IS_VAR && use->op1.var == var) {
 585                                                 use->op1_type = IS_CV;
 586                                                 use->op1.var = zend_optimizer_lookup_cv(op_array,
 587                                                         Z_STRVAL(ZEND_OP1_LITERAL(opline)),
 588                                                         Z_STRLEN(ZEND_OP1_LITERAL(opline)));
 589                                                 MAKE_NOP(opline);
 590                                         } else if (use->op2_type == IS_VAR && use->op2.var == var) {
 591                                                 use->op2_type = IS_CV;
 592                                                 use->op2.var = zend_optimizer_lookup_cv(op_array,
 593                                                         Z_STRVAL(ZEND_OP1_LITERAL(opline)),
 594                                                         Z_STRLEN(ZEND_OP1_LITERAL(opline)));
 595                                                 MAKE_NOP(opline);
 596                                         }
 597                                 }
 598                         }
 599                         break;
 600 #endif
 601                 
 602                 }
 603                 opline++;
 604                 i++;
 605         }
 606 }

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