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 } 607