]> granicus.if.org Git - php/commitdiff
Reintroduce use of FETCH_GLOBAL_LOCK
authorNikita Popov <nikic@php.net>
Thu, 10 Dec 2015 17:51:03 +0000 (18:51 +0100)
committerNikita Popov <nikic@php.net>
Thu, 10 Dec 2015 18:04:59 +0000 (19:04 +0100)
Just found this old AST todo...

It no longer makes sense as an optimization due to the introduction
of BIND_GLOBAL, however it ensures that the global variable name is
not evaluated twice, which is presumably something we wish to
guarantee.

Zend/zend_compile.c

index 363319e37b3d361c73c5687390d38eddd5176c35..f59228a2a4e77481c47bc81c844d2df82d7afae6 100644 (file)
@@ -3642,12 +3642,16 @@ void zend_compile_global_var(zend_ast *ast) /* {{{ */
                zend_op *opline = zend_emit_op(NULL, ZEND_BIND_GLOBAL, &result, &name_node);
                zend_alloc_cache_slot(opline->op2.constant);
        } else {
-               zend_emit_op(&result, ZEND_FETCH_W, &name_node, NULL);
-
-               // TODO.AST Avoid double fetch
-               //opline->extended_value = ZEND_FETCH_GLOBAL_LOCK;
-
-               zend_emit_assign_ref_znode(var_ast, &result);
+               /* name_ast should be evaluated only. FETCH_GLOBAL_LOCK instructs FETCH_W
+                * to not free the name_node operand, so it can be reused in the following
+                * ASSIGN_REF, which then frees it. */
+               zend_op *opline = zend_emit_op(&result, ZEND_FETCH_W, &name_node, NULL);
+               opline->extended_value = ZEND_FETCH_GLOBAL_LOCK;
+
+               zend_emit_assign_ref_znode(
+                       zend_ast_create(ZEND_AST_VAR, zend_ast_create_znode(&name_node)),
+                       &result
+               );
        }
 }
 /* }}} */