root/ext/opcache/Optimizer/pass1_5.c

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

DEFINITIONS

This source file includes following definitions.
  1. zend_optimizer_pass1

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

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