Fixed "delayed" compilation

This commit is contained in:
Dmitry Stogov 2015-02-02 20:44:16 +03:00
parent 37ace4ad89
commit e375ba877a
2 changed files with 56 additions and 18 deletions

View File

@ -0,0 +1,16 @@
--TEST--
$GLOBALS resize
--FILE--
<?php
function foo() {
for ($i = 0; $i < 100; $i++) {
$GLOBALS["A". $i] = 1; //trigger resize
}
return "ops";
}
$GLOBALS[foo()] = "ops";
?>
DONE
--EXPECT--
DONE

View File

@ -1789,8 +1789,16 @@ static inline zend_op *zend_delayed_emit_op(znode *result, zend_uchar opcode, zn
zend_op tmp_opline;
init_op(&tmp_opline);
tmp_opline.opcode = opcode;
SET_NODE(tmp_opline.op1, op1);
SET_NODE(tmp_opline.op2, op2);
if (op1 == NULL) {
SET_UNUSED(tmp_opline.op1);
} else {
SET_NODE(tmp_opline.op1, op1);
}
if (op2 == NULL) {
SET_UNUSED(tmp_opline.op2);
} else {
SET_NODE(tmp_opline.op2, op2);
}
if (result) {
zend_make_var_result(result, &tmp_opline);
}
@ -1984,7 +1992,7 @@ static int zend_try_compile_cv(znode *result, zend_ast *ast) /* {{{ */
}
/* }}} */
static zend_op *zend_compile_simple_var_no_cv(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
static zend_op *zend_compile_simple_var_no_cv(znode *result, zend_ast *ast, uint32_t type, int delayed) /* {{{ */
{
zend_ast *name_ast = ast->child[0];
znode name_node;
@ -2003,7 +2011,11 @@ static zend_op *zend_compile_simple_var_no_cv(znode *result, zend_ast *ast, uint
convert_to_string(&name_node.u.constant);
}
opline = zend_emit_op(result, ZEND_FETCH_R, &name_node, NULL);
if (delayed) {
opline = zend_delayed_emit_op(result, ZEND_FETCH_R, &name_node, NULL);
} else {
opline = zend_emit_op(result, ZEND_FETCH_R, &name_node, NULL);
}
opline->extended_value = ZEND_FETCH_LOCAL;
if (name_node.op_type == IS_CONST) {
@ -2016,10 +2028,10 @@ static zend_op *zend_compile_simple_var_no_cv(znode *result, zend_ast *ast, uint
}
/* }}} */
static void zend_compile_simple_var(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
static void zend_compile_simple_var(znode *result, zend_ast *ast, uint32_t type, int delayed) /* {{{ */
{
if (zend_try_compile_cv(result, ast) == FAILURE) {
zend_op *opline = zend_compile_simple_var_no_cv(result, ast, type);
zend_op *opline = zend_compile_simple_var_no_cv(result, ast, type, delayed);
zend_adjust_for_fetch_type(opline, type);
}
}
@ -2151,7 +2163,7 @@ void zend_compile_prop(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
}
/* }}} */
zend_op *zend_compile_static_prop_common(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
zend_op *zend_compile_static_prop_common(znode *result, zend_ast *ast, uint32_t type, int delayed) /* {{{ */
{
zend_ast *class_ast = ast->child[0];
zend_ast *prop_ast = ast->child[1];
@ -2168,7 +2180,11 @@ zend_op *zend_compile_static_prop_common(znode *result, zend_ast *ast, uint32_t
zend_compile_expr(&prop_node, prop_ast);
opline = zend_emit_op(result, ZEND_FETCH_R, &prop_node, NULL);
if (delayed) {
opline = zend_delayed_emit_op(result, ZEND_FETCH_R, &prop_node, NULL);
} else {
opline = zend_emit_op(result, ZEND_FETCH_R, &prop_node, NULL);
}
if (opline->op1_type == IS_CONST) {
zend_alloc_polymorphic_cache_slot(opline->op1.constant);
}
@ -2185,9 +2201,9 @@ zend_op *zend_compile_static_prop_common(znode *result, zend_ast *ast, uint32_t
}
/* }}} */
void zend_compile_static_prop(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
void zend_compile_static_prop(znode *result, zend_ast *ast, uint32_t type, int delayed) /* {{{ */
{
zend_op *opline = zend_compile_static_prop_common(result, ast, type);
zend_op *opline = zend_compile_static_prop_common(result, ast, type, delayed);
zend_adjust_for_fetch_type(opline, type);
}
/* }}} */
@ -2291,7 +2307,7 @@ void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */
if (zend_is_assign_to_self(var_ast, expr_ast)) {
/* $a[0] = $a should evaluate the right $a first */
zend_compile_simple_var_no_cv(&expr_node, expr_ast, BP_VAR_R);
zend_compile_simple_var_no_cv(&expr_node, expr_ast, BP_VAR_R, 0);
} else {
zend_compile_expr(&expr_node, expr_ast);
}
@ -3088,7 +3104,7 @@ void zend_compile_unset(zend_ast *ast) /* {{{ */
opline = zend_emit_op(NULL, ZEND_UNSET_VAR, &var_node, NULL);
opline->extended_value = ZEND_FETCH_LOCAL | ZEND_QUICK_SET;
} else {
opline = zend_compile_simple_var_no_cv(NULL, var_ast, BP_VAR_UNSET);
opline = zend_compile_simple_var_no_cv(NULL, var_ast, BP_VAR_UNSET, 0);
opline->opcode = ZEND_UNSET_VAR;
}
return;
@ -3101,7 +3117,7 @@ void zend_compile_unset(zend_ast *ast) /* {{{ */
opline->opcode = ZEND_UNSET_OBJ;
return;
case ZEND_AST_STATIC_PROP:
opline = zend_compile_static_prop_common(NULL, var_ast, BP_VAR_UNSET);
opline = zend_compile_static_prop_common(NULL, var_ast, BP_VAR_UNSET, 0);
opline->opcode = ZEND_UNSET_VAR;
return;
EMPTY_SWITCH_DEFAULT_CASE()
@ -5613,7 +5629,7 @@ void zend_compile_isset_or_empty(znode *result, zend_ast *ast) /* {{{ */
opline = zend_emit_op(result, ZEND_ISSET_ISEMPTY_VAR, &var_node, NULL);
opline->extended_value = ZEND_FETCH_LOCAL | ZEND_QUICK_SET;
} else {
opline = zend_compile_simple_var_no_cv(result, var_ast, BP_VAR_IS);
opline = zend_compile_simple_var_no_cv(result, var_ast, BP_VAR_IS, 0);
opline->opcode = ZEND_ISSET_ISEMPTY_VAR;
}
break;
@ -5626,7 +5642,7 @@ void zend_compile_isset_or_empty(znode *result, zend_ast *ast) /* {{{ */
opline->opcode = ZEND_ISSET_ISEMPTY_PROP_OBJ;
break;
case ZEND_AST_STATIC_PROP:
opline = zend_compile_static_prop_common(result, var_ast, BP_VAR_IS);
opline = zend_compile_static_prop_common(result, var_ast, BP_VAR_IS, 0);
opline->opcode = ZEND_ISSET_ISEMPTY_VAR;
break;
EMPTY_SWITCH_DEFAULT_CASE()
@ -5650,7 +5666,7 @@ void zend_compile_silence(znode *result, zend_ast *ast) /* {{{ */
if (expr_ast->kind == ZEND_AST_VAR) {
/* For @$var we need to force a FETCH instruction, otherwise the CV access will
* happen outside the silenced section. */
zend_compile_simple_var_no_cv(result, expr_ast, BP_VAR_R);
zend_compile_simple_var_no_cv(result, expr_ast, BP_VAR_R, 0 );
} else {
zend_compile_expr(result, expr_ast);
}
@ -6406,7 +6422,7 @@ void zend_compile_var(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
{
switch (ast->kind) {
case ZEND_AST_VAR:
zend_compile_simple_var(result, ast, type);
zend_compile_simple_var(result, ast, type, 0);
return;
case ZEND_AST_DIM:
zend_compile_dim(result, ast, type);
@ -6415,7 +6431,7 @@ void zend_compile_var(znode *result, zend_ast *ast, uint32_t type) /* {{{ */
zend_compile_prop(result, ast, type);
return;
case ZEND_AST_STATIC_PROP:
zend_compile_static_prop(result, ast, type);
zend_compile_static_prop(result, ast, type, 0);
return;
case ZEND_AST_CALL:
zend_compile_call(result, ast, type);
@ -6447,6 +6463,9 @@ void zend_delayed_compile_var(znode *result, zend_ast *ast, uint32_t type) /* {{
{
zend_op *opline;
switch (ast->kind) {
case ZEND_AST_VAR:
zend_compile_simple_var(result, ast, type, 1);
return;
case ZEND_AST_DIM:
opline = zend_delayed_compile_dim(result, ast, type);
zend_adjust_for_fetch_type(opline, type);
@ -6455,6 +6474,9 @@ void zend_delayed_compile_var(znode *result, zend_ast *ast, uint32_t type) /* {{
opline = zend_delayed_compile_prop(result, ast, type);
zend_adjust_for_fetch_type(opline, type);
return;
case ZEND_AST_STATIC_PROP:
zend_compile_static_prop(result, ast, type, 1);
return;
default:
zend_compile_var(result, ast, type);
return;