1 /*
2 +----------------------------------------------------------------------+
3 | Zend OPcache |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 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@php.net> |
16 | Zeev Suraski <zeev@php.net> |
17 | Stanislav Malyshev <stas@zend.com> |
18 | Dmitry Stogov <dmitry@php.net> |
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 * - convert CAST(IS_BOOL,x) into BOOL(x)
26 * - pre-evaluate constant function calls
27 * - eliminate FETCH $GLOBALS followed by FETCH_DIM/UNSET_DIM/ISSET_ISEMPTY_DIM
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
zend_optimizer_pass1(zend_op_array * op_array,zend_optimizer_ctx * ctx)38 void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
39 {
40 int i = 0;
41 zend_op *opline = op_array->opcodes;
42 zend_op *end = opline + op_array->last;
43 zend_bool collect_constants = (ZEND_OPTIMIZER_PASS_15 & ctx->optimization_level)?
44 (op_array == &ctx->script->main_op_array) : 0;
45
46 while (opline < end) {
47 switch (opline->opcode) {
48 case ZEND_ADD:
49 case ZEND_SUB:
50 case ZEND_MUL:
51 case ZEND_DIV:
52 case ZEND_MOD:
53 case ZEND_POW:
54 case ZEND_SL:
55 case ZEND_SR:
56 case ZEND_CONCAT:
57 case ZEND_FAST_CONCAT:
58 case ZEND_IS_EQUAL:
59 case ZEND_IS_NOT_EQUAL:
60 case ZEND_IS_SMALLER:
61 case ZEND_IS_SMALLER_OR_EQUAL:
62 case ZEND_IS_IDENTICAL:
63 case ZEND_IS_NOT_IDENTICAL:
64 case ZEND_BW_OR:
65 case ZEND_BW_AND:
66 case ZEND_BW_XOR:
67 case ZEND_BOOL_XOR:
68 case ZEND_SPACESHIP:
69 case ZEND_CASE:
70 if (opline->op1_type == IS_CONST &&
71 opline->op2_type == IS_CONST) {
72 /* binary operation with constant operands */
73 zval result;
74
75 if (zend_optimizer_eval_binary_op(&result, opline->opcode, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline)) == SUCCESS) {
76 literal_dtor(&ZEND_OP1_LITERAL(opline));
77 literal_dtor(&ZEND_OP2_LITERAL(opline));
78 if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, opline->result.var, &result)) {
79 MAKE_NOP(opline);
80 } else {
81 opline->opcode = ZEND_QM_ASSIGN;
82 SET_UNUSED(opline->op2);
83 zend_optimizer_update_op1_const(op_array, opline, &result);
84 }
85 }
86 }
87 break;
88
89 case ZEND_CAST:
90 if (opline->op1_type == IS_CONST) {
91 /* cast of constant operand */
92 zval result;
93
94 if (zend_optimizer_eval_cast(&result, opline->extended_value, &ZEND_OP1_LITERAL(opline)) == SUCCESS) {
95 literal_dtor(&ZEND_OP1_LITERAL(opline));
96 if (zend_optimizer_replace_by_const(op_array, opline + 1, opline->result_type, opline->result.var, &result)) {
97 MAKE_NOP(opline);
98 } else {
99 opline->opcode = ZEND_QM_ASSIGN;
100 opline->extended_value = 0;
101 zend_optimizer_update_op1_const(op_array, opline, &result);
102 }
103 break;
104 }
105 }
106
107 if (opline->extended_value == _IS_BOOL) {
108 /* T = CAST(X, IS_BOOL) => T = BOOL(X) */
109 opline->opcode = ZEND_BOOL;
110 opline->extended_value = 0;
111 }
112 break;
113
114 case ZEND_BW_NOT:
115 case ZEND_BOOL_NOT:
116 if (opline->op1_type == IS_CONST) {
117 /* unary operation on constant operand */
118 zval result;
119
120 if (zend_optimizer_eval_unary_op(&result, opline->opcode, &ZEND_OP1_LITERAL(opline)) == SUCCESS) {
121 literal_dtor(&ZEND_OP1_LITERAL(opline));
122 if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, opline->result.var, &result)) {
123 MAKE_NOP(opline);
124 } else {
125 opline->opcode = ZEND_QM_ASSIGN;
126 zend_optimizer_update_op1_const(op_array, opline, &result);
127 }
128 }
129 }
130 break;
131
132 case ZEND_FETCH_CONSTANT:
133 if (opline->op2_type == IS_CONST &&
134 Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING &&
135 Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("__COMPILER_HALT_OFFSET__") - 1 &&
136 memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)), "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1) == 0) {
137 /* substitute __COMPILER_HALT_OFFSET__ constant */
138 zend_execute_data *orig_execute_data = EG(current_execute_data);
139 zend_execute_data fake_execute_data;
140 zval *offset;
141
142 memset(&fake_execute_data, 0, sizeof(zend_execute_data));
143 fake_execute_data.func = (zend_function*)op_array;
144 EG(current_execute_data) = &fake_execute_data;
145 if ((offset = zend_get_constant_str("__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1)) != NULL) {
146
147 literal_dtor(&ZEND_OP2_LITERAL(opline));
148 if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, opline->result.var, offset)) {
149 MAKE_NOP(opline);
150 } else {
151 opline->opcode = ZEND_QM_ASSIGN;
152 opline->extended_value = 0;
153 SET_UNUSED(opline->op2);
154 zend_optimizer_update_op1_const(op_array, opline, offset);
155 }
156 }
157 EG(current_execute_data) = orig_execute_data;
158 break;
159 }
160
161 if (opline->op2_type == IS_CONST &&
162 Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) {
163 /* substitute persistent constants */
164 zval c;
165
166 if (!zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP2_LITERAL(opline)), &c, 1)) {
167 if (!ctx->constants || !zend_optimizer_get_collected_constant(ctx->constants, &ZEND_OP2_LITERAL(opline), &c)) {
168 break;
169 }
170 }
171 if (Z_TYPE(c) == IS_CONSTANT_AST) {
172 break;
173 }
174 literal_dtor(&ZEND_OP2_LITERAL(opline));
175 if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, opline->result.var, &c)) {
176 MAKE_NOP(opline);
177 } else {
178 opline->opcode = ZEND_QM_ASSIGN;
179 opline->extended_value = 0;
180 SET_UNUSED(opline->op2);
181 zend_optimizer_update_op1_const(op_array, opline, &c);
182 }
183 }
184 break;
185
186 case ZEND_FETCH_CLASS_CONSTANT:
187 if (opline->op2_type == IS_CONST &&
188 Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) {
189
190 zend_class_entry *ce = NULL;
191
192 if (opline->op1_type == IS_CONST &&
193 Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING) {
194 /* for A::B */
195 if (op_array->scope &&
196 !strncasecmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)),
197 ZSTR_VAL(op_array->scope->name), Z_STRLEN(ZEND_OP1_LITERAL(opline)) + 1)) {
198 ce = op_array->scope;
199 } else {
200 if ((ce = zend_hash_find_ptr(EG(class_table),
201 Z_STR(op_array->literals[opline->op1.constant + 1]))) == NULL ||
202 (ce->type == ZEND_INTERNAL_CLASS &&
203 ce->info.internal.module->type != MODULE_PERSISTENT) ||
204 (ce->type == ZEND_USER_CLASS &&
205 ce->info.user.filename != op_array->filename)) {
206 break;
207 }
208 }
209 } else if (op_array->scope &&
210 opline->op1_type == IS_UNUSED &&
211 (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
212 /* for self::B */
213 ce = op_array->scope;
214 } else if (op_array->scope &&
215 opline->op1_type == IS_VAR &&
216 (opline - 1)->opcode == ZEND_FETCH_CLASS &&
217 ((opline - 1)->op2_type == IS_UNUSED &&
218 ((opline - 1)->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) &&
219 (opline - 1)->result.var == opline->op1.var) {
220 /* for self::B */
221 ce = op_array->scope;
222 }
223
224 if (ce) {
225 zend_class_constant *cc;
226 zval *c, t;
227
228 if ((cc = zend_hash_find_ptr(&ce->constants_table,
229 Z_STR(ZEND_OP2_LITERAL(opline)))) != NULL &&
230 (Z_ACCESS_FLAGS(cc->value) & ZEND_ACC_PPP_MASK) == ZEND_ACC_PUBLIC) {
231 c = &cc->value;
232 if (Z_TYPE_P(c) == IS_CONSTANT_AST) {
233 zend_ast *ast = Z_ASTVAL_P(c);
234 if (ast->kind != ZEND_AST_CONSTANT
235 || !zend_optimizer_get_persistent_constant(zend_ast_get_constant_name(ast), &t, 1)
236 || Z_TYPE(t) == IS_CONSTANT_AST) {
237 break;
238 }
239 } else {
240 ZVAL_COPY_OR_DUP(&t, c);
241 }
242
243 if (opline->op1_type == IS_CONST) {
244 literal_dtor(&ZEND_OP1_LITERAL(opline));
245 } else if (opline->op1_type == IS_VAR) {
246 MAKE_NOP((opline - 1));
247 }
248 literal_dtor(&ZEND_OP2_LITERAL(opline));
249
250 if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, opline->result.var, &t)) {
251 MAKE_NOP(opline);
252 } else {
253 opline->opcode = ZEND_QM_ASSIGN;
254 opline->extended_value = 0;
255 SET_UNUSED(opline->op2);
256 zend_optimizer_update_op1_const(op_array, opline, &t);
257 }
258 }
259 }
260 }
261 break;
262
263 case ZEND_DO_ICALL: {
264 zend_op *send1_opline = opline - 1;
265 zend_op *send2_opline = NULL;
266 zend_op *init_opline = NULL;
267
268 while (send1_opline->opcode == ZEND_NOP) {
269 send1_opline--;
270 }
271 if (send1_opline->opcode != ZEND_SEND_VAL ||
272 send1_opline->op1_type != IS_CONST) {
273 /* don't colllect constants after unknown function call */
274 collect_constants = 0;
275 break;
276 }
277 if (send1_opline->op2.num == 2) {
278 send2_opline = send1_opline;
279 send1_opline--;
280 while (send1_opline->opcode == ZEND_NOP) {
281 send1_opline--;
282 }
283 if (send1_opline->opcode != ZEND_SEND_VAL ||
284 send1_opline->op1_type != IS_CONST) {
285 /* don't colllect constants after unknown function call */
286 collect_constants = 0;
287 break;
288 }
289 }
290 init_opline = send1_opline - 1;
291 while (init_opline->opcode == ZEND_NOP) {
292 init_opline--;
293 }
294 if (init_opline->opcode != ZEND_INIT_FCALL ||
295 init_opline->op2_type != IS_CONST ||
296 Z_TYPE(ZEND_OP2_LITERAL(init_opline)) != IS_STRING) {
297 /* don't colllect constants after unknown function call */
298 collect_constants = 0;
299 break;
300 }
301
302 /* define("name", scalar); */
303 if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("define")-1 &&
304 zend_binary_strcasecmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)), Z_STRLEN(ZEND_OP2_LITERAL(init_opline)), "define", sizeof("define")-1) == 0) {
305
306 if (Z_TYPE(ZEND_OP1_LITERAL(send1_opline)) == IS_STRING &&
307 send2_opline &&
308 Z_TYPE(ZEND_OP1_LITERAL(send2_opline)) <= IS_STRING) {
309
310 if (collect_constants) {
311 zend_optimizer_collect_constant(ctx, &ZEND_OP1_LITERAL(send1_opline), &ZEND_OP1_LITERAL(send2_opline));
312 }
313
314 if (RESULT_UNUSED(opline) &&
315 !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)))) {
316
317 opline->opcode = ZEND_DECLARE_CONST;
318 opline->op1_type = IS_CONST;
319 opline->op2_type = IS_CONST;
320 opline->result_type = IS_UNUSED;
321 opline->op1.constant = send1_opline->op1.constant;
322 opline->op2.constant = send2_opline->op1.constant;
323 opline->result.num = 0;
324
325 literal_dtor(&ZEND_OP2_LITERAL(init_opline));
326 MAKE_NOP(init_opline);
327 MAKE_NOP(send1_opline);
328 MAKE_NOP(send2_opline);
329 }
330 break;
331 }
332 }
333
334 /* pre-evaluate constant functions:
335 constant(x)
336 function_exists(x)
337 is_callable(x)
338 extension_loaded(x)
339 */
340 if (!send2_opline &&
341 Z_TYPE(ZEND_OP1_LITERAL(send1_opline)) == IS_STRING) {
342 if ((Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("function_exists")-1 &&
343 !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)),
344 "function_exists", sizeof("function_exists")-1) &&
345 !zend_optimizer_is_disabled_func("function_exists", sizeof("function_exists") - 1)) ||
346 (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("is_callable")-1 &&
347 !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)),
348 "is_callable", sizeof("is_callable")) &&
349 !zend_optimizer_is_disabled_func("is_callable", sizeof("is_callable") - 1))) {
350 zend_internal_function *func;
351 zend_string *lc_name = zend_string_tolower(
352 Z_STR(ZEND_OP1_LITERAL(send1_opline)));
353
354 if ((func = zend_hash_find_ptr(EG(function_table), lc_name)) != NULL
355 && func->type == ZEND_INTERNAL_FUNCTION
356 && func->module->type == MODULE_PERSISTENT
357 #ifdef ZEND_WIN32
358 && func->module->handle == NULL
359 #endif
360 ) {
361 zval t;
362 if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("is_callable") - 1 ||
363 func->handler != ZEND_FN(display_disabled_function)) {
364 ZVAL_TRUE(&t);
365 } else {
366 ZVAL_FALSE(&t);
367 }
368 literal_dtor(&ZEND_OP2_LITERAL(init_opline));
369 MAKE_NOP(init_opline);
370 literal_dtor(&ZEND_OP1_LITERAL(send1_opline));
371 MAKE_NOP(send1_opline);
372 if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, opline->result.var, &t)) {
373 MAKE_NOP(opline);
374 } else {
375 opline->opcode = ZEND_QM_ASSIGN;
376 opline->extended_value = 0;
377 SET_UNUSED(opline->op2);
378 zend_optimizer_update_op1_const(op_array, opline, &t);
379 }
380 }
381 zend_string_release_ex(lc_name, 0);
382 break;
383 } else if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("extension_loaded")-1 &&
384 !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)),
385 "extension_loaded", sizeof("extension_loaded")-1) &&
386 !zend_optimizer_is_disabled_func("extension_loaded", sizeof("extension_loaded") - 1)) {
387 zval t;
388 zend_string *lc_name = zend_string_tolower(
389 Z_STR(ZEND_OP1_LITERAL(send1_opline)));
390 zend_module_entry *m = zend_hash_find_ptr(&module_registry,
391 lc_name);
392
393 zend_string_release_ex(lc_name, 0);
394 if (!m) {
395 if (PG(enable_dl)) {
396 break;
397 } else {
398 ZVAL_FALSE(&t);
399 }
400 } else {
401 if (m->type == MODULE_PERSISTENT
402 #ifdef ZEND_WIN32
403 && m->handle == NULL
404 #endif
405 ) {
406 ZVAL_TRUE(&t);
407 } else {
408 break;
409 }
410 }
411
412 literal_dtor(&ZEND_OP2_LITERAL(init_opline));
413 MAKE_NOP(init_opline);
414 literal_dtor(&ZEND_OP1_LITERAL(send1_opline));
415 MAKE_NOP(send1_opline);
416 if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, opline->result.var, &t)) {
417 MAKE_NOP(opline);
418 } else {
419 opline->opcode = ZEND_QM_ASSIGN;
420 opline->extended_value = 0;
421 SET_UNUSED(opline->op2);
422 zend_optimizer_update_op1_const(op_array, opline, &t);
423 }
424 break;
425 } else if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("constant")-1 &&
426 !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)),
427 "constant", sizeof("constant")-1) &&
428 !zend_optimizer_is_disabled_func("constant", sizeof("constant") - 1)) {
429 zval t;
430
431 if (zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(send1_opline)), &t, 1)) {
432 literal_dtor(&ZEND_OP2_LITERAL(init_opline));
433 MAKE_NOP(init_opline);
434 literal_dtor(&ZEND_OP1_LITERAL(send1_opline));
435 MAKE_NOP(send1_opline);
436 if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, opline->result.var, &t)) {
437 MAKE_NOP(opline);
438 } else {
439 opline->opcode = ZEND_QM_ASSIGN;
440 opline->extended_value = 0;
441 SET_UNUSED(opline->op2);
442 zend_optimizer_update_op1_const(op_array, opline, &t);
443 }
444 }
445 break;
446 /* dirname(IS_CONST/IS_STRING) -> IS_CONST/IS_STRING */
447 } else if (Z_STRLEN(ZEND_OP2_LITERAL(init_opline)) == sizeof("dirname")-1 &&
448 !memcmp(Z_STRVAL(ZEND_OP2_LITERAL(init_opline)),
449 "dirname", sizeof("dirname") - 1) &&
450 !zend_optimizer_is_disabled_func("dirname", sizeof("dirname") - 1) &&
451 IS_ABSOLUTE_PATH(Z_STRVAL(ZEND_OP1_LITERAL(send1_opline)), Z_STRLEN(ZEND_OP1_LITERAL(send1_opline)))) {
452 zend_string *dirname = zend_string_init(Z_STRVAL(ZEND_OP1_LITERAL(send1_opline)), Z_STRLEN(ZEND_OP1_LITERAL(send1_opline)), 0);
453 ZSTR_LEN(dirname) = zend_dirname(ZSTR_VAL(dirname), ZSTR_LEN(dirname));
454 if (IS_ABSOLUTE_PATH(ZSTR_VAL(dirname), ZSTR_LEN(dirname))) {
455 zval t;
456
457 ZVAL_STR(&t, dirname);
458 literal_dtor(&ZEND_OP2_LITERAL(init_opline));
459 MAKE_NOP(init_opline);
460 literal_dtor(&ZEND_OP1_LITERAL(send1_opline));
461 MAKE_NOP(send1_opline);
462 if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_VAR, opline->result.var, &t)) {
463 MAKE_NOP(opline);
464 } else {
465 opline->opcode = ZEND_QM_ASSIGN;
466 opline->extended_value = 0;
467 SET_UNUSED(opline->op2);
468 zend_optimizer_update_op1_const(op_array, opline, &t);
469 }
470 } else {
471 zend_string_release_ex(dirname, 0);
472 }
473 break;
474 }
475 }
476 /* don't colllect constants after any other function call */
477 collect_constants = 0;
478 break;
479 }
480 case ZEND_STRLEN:
481 if (opline->op1_type == IS_CONST) {
482 zval t;
483
484 if (zend_optimizer_eval_strlen(&t, &ZEND_OP1_LITERAL(opline)) == SUCCESS) {
485 literal_dtor(&ZEND_OP1_LITERAL(opline));
486 if (zend_optimizer_replace_by_const(op_array, opline + 1, IS_TMP_VAR, opline->result.var, &t)) {
487 MAKE_NOP(opline);
488 } else {
489 opline->opcode = ZEND_QM_ASSIGN;
490 zend_optimizer_update_op1_const(op_array, opline, &t);
491 }
492 }
493 }
494 break;
495 case ZEND_DEFINED:
496 {
497 zval c;
498 if (!zend_optimizer_get_persistent_constant(Z_STR(ZEND_OP1_LITERAL(opline)), &c, 0)) {
499 break;
500 }
501 ZVAL_TRUE(&c);
502 literal_dtor(&ZEND_OP1_LITERAL(opline));
503 if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, opline->result.var, &c)) {
504 MAKE_NOP(opline);
505 } else {
506 opline->opcode = ZEND_QM_ASSIGN;
507 zend_optimizer_update_op1_const(op_array, opline, &c);
508 }
509 }
510 break;
511 case ZEND_DECLARE_CONST:
512 if (collect_constants &&
513 Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING &&
514 Z_TYPE(ZEND_OP2_LITERAL(opline)) <= IS_STRING) {
515 zend_optimizer_collect_constant(ctx, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline));
516 }
517 break;
518 #if 0
519 /* see ext/opcache/tests/bug78961.phpt */
520 // case ZEND_FETCH_R:
521 case ZEND_FETCH_W:
522 // case ZEND_FETCH_RW:
523 case ZEND_FETCH_IS:
524 // case ZEND_FETCH_FUNC_ARG:
525 case ZEND_FETCH_UNSET:
526 /* convert FETCH $GLOBALS (global), FETCH_DIM $x into FETCH $x (global) */
527 if ((opline->extended_value & ZEND_FETCH_GLOBAL) != 0 &&
528 opline->op1_type == IS_CONST &&
529 Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING &&
530 zend_string_equals_literal(Z_STR(ZEND_OP1_LITERAL(opline)), "GLOBALS") &&
531 ((opline + 1)->opcode == opline->opcode + 1 ||
532 ((opline + 1)->opcode == ZEND_UNSET_DIM &&
533 opline->opcode == ZEND_FETCH_UNSET) ||
534 ((opline + 1)->opcode == ZEND_ISSET_ISEMPTY_DIM_OBJ &&
535 opline->opcode == ZEND_FETCH_IS)) &&
536 (opline + 1)->op1_type == opline->result_type &&
537 (opline + 1)->op1.var == opline->result.var &&
538 ((opline + 1)->op2_type != IS_CONST ||
539 Z_TYPE(ZEND_OP2_LITERAL(opline + 1)) < IS_ARRAY)) {
540
541 if ((opline + 1)->opcode == ZEND_UNSET_DIM) {
542 (opline + 1)->opcode = ZEND_UNSET_VAR;
543 (opline + 1)->extended_value = ZEND_FETCH_GLOBAL;
544 } else if ((opline + 1)->opcode == ZEND_ISSET_ISEMPTY_DIM_OBJ) {
545 (opline + 1)->opcode = ZEND_ISSET_ISEMPTY_VAR;
546 (opline + 1)->extended_value |= ZEND_FETCH_GLOBAL;
547 } else {
548 (opline + 1)->opcode = opline->opcode;
549 (opline + 1)->extended_value = ZEND_FETCH_GLOBAL;
550 }
551 (opline + 1)->op1_type = (opline + 1)->op2_type;
552 (opline + 1)->op1 = (opline + 1)->op2;
553 if ((opline + 1)->op1_type == IS_CONST &&
554 Z_TYPE(ZEND_OP1_LITERAL(opline + 1)) != IS_STRING) {
555
556 convert_to_string(&ZEND_OP1_LITERAL(opline + 1));
557 zend_string_hash_val(Z_STR(ZEND_OP1_LITERAL(opline + 1)));
558 }
559 SET_UNUSED((opline + 1)->op2);
560 MAKE_NOP(opline);
561 }
562 break;
563 #endif
564
565 case ZEND_RETURN:
566 case ZEND_RETURN_BY_REF:
567 case ZEND_GENERATOR_RETURN:
568 case ZEND_EXIT:
569 case ZEND_THROW:
570 case ZEND_CATCH:
571 case ZEND_FAST_CALL:
572 case ZEND_FAST_RET:
573 case ZEND_JMP:
574 case ZEND_JMPZNZ:
575 case ZEND_JMPZ:
576 case ZEND_JMPNZ:
577 case ZEND_JMPZ_EX:
578 case ZEND_JMPNZ_EX:
579 case ZEND_FE_RESET_R:
580 case ZEND_FE_RESET_RW:
581 case ZEND_FE_FETCH_R:
582 case ZEND_FE_FETCH_RW:
583 case ZEND_JMP_SET:
584 case ZEND_COALESCE:
585 case ZEND_ASSERT_CHECK:
586 collect_constants = 0;
587 break;
588 }
589 opline++;
590 i++;
591 }
592 }
593