summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikic@php.net>2015-05-22 22:08:44 +0200
committerNikita Popov <nikic@php.net>2015-05-23 10:51:33 +0200
commit9325ada7253efb330e4fd79579d6e6fc0334d7b2 (patch)
tree1d4782f080f89f4d781942919f8bcd4a79005aa9
parent3cbe3903faa8f02b6828d9d496816d3334ea2b00 (diff)
downloadphp-git-9325ada7253efb330e4fd79579d6e6fc0334d7b2.tar.gz
Embed break/continue depth into opline
Previously a separate lval literal was used - this is probably a leftover from the time where the break level could still be specified dynamically.
-rw-r--r--Zend/zend_compile.c23
-rw-r--r--Zend/zend_opcode.c6
-rw-r--r--Zend/zend_vm_def.h8
-rw-r--r--Zend/zend_vm_execute.h144
-rw-r--r--ext/opcache/Optimizer/pass2.c10
5 files changed, 93 insertions, 98 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index fb75643681..2ea4451b09 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -3528,26 +3528,27 @@ void zend_compile_break_continue(zend_ast *ast) /* {{{ */
{
zend_ast *depth_ast = ast->child[0];
- znode depth_node;
zend_op *opline;
+ int depth;
ZEND_ASSERT(ast->kind == ZEND_AST_BREAK || ast->kind == ZEND_AST_CONTINUE);
if (depth_ast) {
+ zval *depth_zv;
if (depth_ast->kind != ZEND_AST_ZVAL) {
zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator with non-constant operand "
"is no longer supported", ast->kind == ZEND_AST_BREAK ? "break" : "continue");
}
- zend_compile_expr(&depth_node, depth_ast);
-
- if (Z_TYPE(depth_node.u.constant) != IS_LONG || Z_LVAL(depth_node.u.constant) < 1) {
+ depth_zv = zend_ast_get_zval(depth_ast);
+ if (Z_TYPE_P(depth_zv) != IS_LONG || Z_LVAL_P(depth_zv) < 1) {
zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator accepts only positive numbers",
ast->kind == ZEND_AST_BREAK ? "break" : "continue");
}
+
+ depth = Z_LVAL_P(depth_zv);
} else {
- depth_node.op_type = IS_CONST;
- ZVAL_LONG(&depth_node.u.constant, 1);
+ depth = 1;
}
if (CG(context).current_brk_cont == -1) {
@@ -3555,20 +3556,20 @@ void zend_compile_break_continue(zend_ast *ast) /* {{{ */
ast->kind == ZEND_AST_BREAK ? "break" : "continue");
} else {
int array_offset = CG(context).current_brk_cont;
- zend_long nest_level = Z_LVAL(depth_node.u.constant);
+ zend_long nest_level = depth;
do {
if (array_offset == -1) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot '%s' %d level%s",
ast->kind == ZEND_AST_BREAK ? "break" : "continue",
- Z_LVAL(depth_node.u.constant), (Z_LVAL(depth_node.u.constant) == 1) ? "" : "s");
+ depth, depth == 1 ? "" : "s");
}
array_offset = CG(active_op_array)->brk_cont_array[array_offset].parent;
} while (--nest_level > 0);
}
- opline = zend_emit_op(NULL, ast->kind == ZEND_AST_BREAK ? ZEND_BRK : ZEND_CONT,
- NULL, &depth_node);
- opline->op1.opline_num = CG(context).current_brk_cont;
+ opline = zend_emit_op(NULL, ast->kind == ZEND_AST_BREAK ? ZEND_BRK : ZEND_CONT, NULL, NULL);
+ opline->op1.num = CG(context).current_brk_cont;
+ opline->op2.num = depth;
}
/* }}} */
diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c
index f24fc9f193..933c75a706 100644
--- a/Zend/zend_opcode.c
+++ b/Zend/zend_opcode.c
@@ -682,11 +682,11 @@ static void zend_resolve_finally_calls(zend_op_array *op_array)
case ZEND_BRK:
case ZEND_CONT:
{
- int nest_levels, array_offset;
+ int nest_levels = opline->op2.num;
+ int array_offset = opline->op1.num;
zend_brk_cont_element *jmp_to;
- nest_levels = Z_LVAL(op_array->literals[opline->op2.constant]);
- if ((array_offset = opline->op1.opline_num) != -1) {
+ if (array_offset != -1) {
do {
jmp_to = &op_array->brk_cont_array[array_offset];
if (nest_levels > 1) {
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index d3e7dfece1..f63a41e515 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -4816,24 +4816,24 @@ ZEND_VM_HANDLER(52, ZEND_BOOL, CONST|TMPVAR|CV, ANY)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(50, ZEND_BRK, ANY, CONST)
+ZEND_VM_HANDLER(50, ZEND_BRK, ANY, ANY)
{
USE_OPLINE
zend_brk_cont_element *el;
SAVE_OPLINE();
- el = zend_brk_cont(Z_LVAL_P(EX_CONSTANT(opline->op2)), opline->op1.opline_num,
+ el = zend_brk_cont(opline->op2.num, opline->op1.num,
&EX(func)->op_array, execute_data);
ZEND_VM_JMP(EX(func)->op_array.opcodes + el->brk);
}
-ZEND_VM_HANDLER(51, ZEND_CONT, ANY, CONST)
+ZEND_VM_HANDLER(51, ZEND_CONT, ANY, ANY)
{
USE_OPLINE
zend_brk_cont_element *el;
SAVE_OPLINE();
- el = zend_brk_cont(Z_LVAL_P(EX_CONSTANT(opline->op2)), opline->op1.opline_num,
+ el = zend_brk_cont(opline->op2.num, opline->op1.num,
&EX(func)->op_array, execute_data);
ZEND_VM_JMP(EX(func)->op_array.opcodes + el->cont);
}
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 2fa1079f27..aa3b7f3658 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -1248,6 +1248,28 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_VARIADIC_SPEC_HANDLER(ZEN
ZEND_VM_NEXT_OPCODE();
}
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BRK_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_brk_cont_element *el;
+
+ SAVE_OPLINE();
+ el = zend_brk_cont(opline->op2.num, opline->op1.num,
+ &EX(func)->op_array, execute_data);
+ ZEND_VM_JMP(EX(func)->op_array.opcodes + el->brk);
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONT_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_brk_cont_element *el;
+
+ SAVE_OPLINE();
+ el = zend_brk_cont(opline->op2.num, opline->op1.num,
+ &EX(func)->op_array, execute_data);
+ ZEND_VM_JMP(EX(func)->op_array.opcodes + el->cont);
+}
+
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -2348,28 +2370,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CONST_HANDLER(Z
ZEND_VM_NEXT_OPCODE();
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BRK_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- USE_OPLINE
- zend_brk_cont_element *el;
-
- SAVE_OPLINE();
- el = zend_brk_cont(Z_LVAL_P(EX_CONSTANT(opline->op2)), opline->op1.opline_num,
- &EX(func)->op_array, execute_data);
- ZEND_VM_JMP(EX(func)->op_array.opcodes + el->brk);
-}
-
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- USE_OPLINE
- zend_brk_cont_element *el;
-
- SAVE_OPLINE();
- el = zend_brk_cont(Z_LVAL_P(EX_CONSTANT(opline->op2)), opline->op1.opline_num,
- &EX(func)->op_array, execute_data);
- ZEND_VM_JMP(EX(func)->op_array.opcodes + el->cont);
-}
-
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GOTO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -46678,56 +46678,56 @@ void zend_init_opcodes_handlers(void)
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_BRK_SPEC_CONST_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_BRK_SPEC_CONST_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_BRK_SPEC_CONST_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_BRK_SPEC_CONST_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_BRK_SPEC_CONST_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_CONT_SPEC_CONST_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_CONT_SPEC_CONST_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_CONT_SPEC_CONST_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_CONT_SPEC_CONST_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_CONT_SPEC_CONST_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
+ ZEND_BRK_SPEC_HANDLER,
+ ZEND_BRK_SPEC_HANDLER,
+ ZEND_BRK_SPEC_HANDLER,
+ ZEND_BRK_SPEC_HANDLER,
+ ZEND_BRK_SPEC_HANDLER,
+ ZEND_BRK_SPEC_HANDLER,
+ ZEND_BRK_SPEC_HANDLER,
+ ZEND_BRK_SPEC_HANDLER,
+ ZEND_BRK_SPEC_HANDLER,
+ ZEND_BRK_SPEC_HANDLER,
+ ZEND_BRK_SPEC_HANDLER,
+ ZEND_BRK_SPEC_HANDLER,
+ ZEND_BRK_SPEC_HANDLER,
+ ZEND_BRK_SPEC_HANDLER,
+ ZEND_BRK_SPEC_HANDLER,
+ ZEND_BRK_SPEC_HANDLER,
+ ZEND_BRK_SPEC_HANDLER,
+ ZEND_BRK_SPEC_HANDLER,
+ ZEND_BRK_SPEC_HANDLER,
+ ZEND_BRK_SPEC_HANDLER,
+ ZEND_BRK_SPEC_HANDLER,
+ ZEND_BRK_SPEC_HANDLER,
+ ZEND_BRK_SPEC_HANDLER,
+ ZEND_BRK_SPEC_HANDLER,
+ ZEND_BRK_SPEC_HANDLER,
+ ZEND_CONT_SPEC_HANDLER,
+ ZEND_CONT_SPEC_HANDLER,
+ ZEND_CONT_SPEC_HANDLER,
+ ZEND_CONT_SPEC_HANDLER,
+ ZEND_CONT_SPEC_HANDLER,
+ ZEND_CONT_SPEC_HANDLER,
+ ZEND_CONT_SPEC_HANDLER,
+ ZEND_CONT_SPEC_HANDLER,
+ ZEND_CONT_SPEC_HANDLER,
+ ZEND_CONT_SPEC_HANDLER,
+ ZEND_CONT_SPEC_HANDLER,
+ ZEND_CONT_SPEC_HANDLER,
+ ZEND_CONT_SPEC_HANDLER,
+ ZEND_CONT_SPEC_HANDLER,
+ ZEND_CONT_SPEC_HANDLER,
+ ZEND_CONT_SPEC_HANDLER,
+ ZEND_CONT_SPEC_HANDLER,
+ ZEND_CONT_SPEC_HANDLER,
+ ZEND_CONT_SPEC_HANDLER,
+ ZEND_CONT_SPEC_HANDLER,
+ ZEND_CONT_SPEC_HANDLER,
+ ZEND_CONT_SPEC_HANDLER,
+ ZEND_CONT_SPEC_HANDLER,
+ ZEND_CONT_SPEC_HANDLER,
+ ZEND_CONT_SPEC_HANDLER,
ZEND_BOOL_SPEC_CONST_HANDLER,
ZEND_BOOL_SPEC_CONST_HANDLER,
ZEND_BOOL_SPEC_CONST_HANDLER,
diff --git a/ext/opcache/Optimizer/pass2.c b/ext/opcache/Optimizer/pass2.c
index c0832a1cbf..3991a41e0f 100644
--- a/ext/opcache/Optimizer/pass2.c
+++ b/ext/opcache/Optimizer/pass2.c
@@ -186,16 +186,10 @@ void zend_optimizer_pass2(zend_op_array *op_array)
case ZEND_CONT:
{
zend_brk_cont_element *jmp_to;
- int array_offset;
- int nest_levels;
+ int array_offset = ZEND_OP1(opline).num;
+ int nest_levels = ZEND_OP2(opline).num;
int dont_optimize = 0;
- ZEND_ASSERT(ZEND_OP2_TYPE(opline) == IS_CONST);
- ZEND_ASSERT(Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_LONG);
-
- nest_levels = Z_LVAL(ZEND_OP2_LITERAL(opline));
-
- array_offset = ZEND_OP1(opline).opline_num;
while (1) {
if (array_offset == -1) {
dont_optimize = 1; /* don't optimize this bogus break/continue, let the executor shout */