summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/zend.c3
-rw-r--r--Zend/zend_compile.c102
-rw-r--r--Zend/zend_compile.h2
-rw-r--r--Zend/zend_globals.h2
4 files changed, 30 insertions, 79 deletions
diff --git a/Zend/zend.c b/Zend/zend.c
index e5fd2e8bee..e200c05b67 100644
--- a/Zend/zend.c
+++ b/Zend/zend.c
@@ -1045,7 +1045,6 @@ static void zend_error_va_list(int type, const char *format, va_list args)
zval orig_user_error_handler;
zend_bool in_compilation;
zend_class_entry *saved_class_entry;
- zend_stack loop_var_stack;
zend_stack delayed_oplines_stack;
zend_array *symbol_table;
@@ -1212,7 +1211,6 @@ static void zend_error_va_list(int type, const char *format, va_list args)
if (in_compilation) {
saved_class_entry = CG(active_class_entry);
CG(active_class_entry) = NULL;
- SAVE_STACK(loop_var_stack);
SAVE_STACK(delayed_oplines_stack);
CG(in_compilation) = 0;
}
@@ -1231,7 +1229,6 @@ static void zend_error_va_list(int type, const char *format, va_list args)
if (in_compilation) {
CG(active_class_entry) = saved_class_entry;
- RESTORE_STACK(loop_var_stack);
RESTORE_STACK(delayed_oplines_stack);
CG(in_compilation) = 1;
}
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 69aecc4108..51eb0bc754 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -289,7 +289,6 @@ void zend_file_context_end(zend_file_context *prev_context) /* {{{ */
void zend_init_compiler_data_structures(void) /* {{{ */
{
- zend_stack_init(&CG(loop_var_stack), sizeof(znode));
zend_stack_init(&CG(delayed_oplines_stack), sizeof(zend_op));
CG(active_class_entry) = NULL;
CG(in_compilation) = 0;
@@ -322,7 +321,6 @@ void init_compiler(void) /* {{{ */
void shutdown_compiler(void) /* {{{ */
{
- zend_stack_destroy(&CG(loop_var_stack));
zend_stack_destroy(&CG(delayed_oplines_stack));
zend_hash_destroy(&CG(filenames_table));
zend_hash_destroy(&CG(const_filenames));
@@ -571,14 +569,10 @@ static inline void zend_begin_loop(const znode *loop_var) /* {{{ */
CG(context).current_brk_cont = CG(context).last_brk_cont;
brk_cont_element = get_next_brk_cont_element(CG(active_op_array));
brk_cont_element->parent = parent;
-
- if (loop_var) {
- zend_stack_push(&CG(loop_var_stack), loop_var);
- brk_cont_element->start = get_next_op_number(CG(active_op_array));
+ if (loop_var && (loop_var->op_type & (IS_TMP_VAR|IS_VAR))) {
+ brk_cont_element->loop_var = *loop_var;
} else {
- /* The start field is used to free temporary variables in case of exceptions.
- * We won't try to free something of we don't have loop variable. */
- brk_cont_element->start = -1;
+ brk_cont_element->loop_var.op_type = IS_UNUSED;
}
}
/* }}} */
@@ -590,10 +584,6 @@ static inline void zend_end_loop(int cont_addr) /* {{{ */
brk_cont_element->cont = cont_addr;
brk_cont_element->brk = get_next_op_number(CG(active_op_array));
CG(context).current_brk_cont = brk_cont_element->parent;
-
- if (brk_cont_element->start >= 0) {
- zend_stack_del_top(&CG(loop_var_stack));
- }
}
/* }}} */
@@ -882,24 +872,15 @@ static void str_dtor(zval *zv) /* {{{ */ {
static zend_bool zend_is_call(zend_ast *ast);
-static int generate_free_loop_var(znode *var) /* {{{ */
+static void generate_free_loop_var(znode *var) /* {{{ */
{
- switch (var->op_type) {
- case IS_UNUSED:
- /* Stack separator on function boundary, stop applying */
- return 1;
- case IS_VAR:
- case IS_TMP_VAR:
- {
- zend_op *opline = get_next_op(CG(active_op_array));
+ if (var->op_type != IS_UNUSED) {
+ zend_op *opline = get_next_op(CG(active_op_array));
- opline->opcode = var->flag ? ZEND_FE_FREE : ZEND_FREE;
- SET_NODE(opline->op1, var);
- SET_UNUSED(opline->op2);
- }
+ opline->opcode = var->flag ? ZEND_FE_FREE : ZEND_FREE;
+ SET_NODE(opline->op1, var);
+ SET_UNUSED(opline->op2);
}
-
- return 0;
}
/* }}} */
@@ -3462,7 +3443,12 @@ void zend_compile_unset(zend_ast *ast) /* {{{ */
static void zend_free_foreach_and_switch_variables(void) /* {{{ */
{
- zend_stack_apply(&CG(loop_var_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element)) generate_free_loop_var);
+ int array_offset = CG(context).current_brk_cont;
+ while (array_offset != -1) {
+ zend_brk_cont_element *brk_cont = &CG(context).brk_cont_array[array_offset];
+ generate_free_loop_var(&brk_cont->loop_var);
+ array_offset = brk_cont->parent;
+ }
}
/* }}} */
@@ -3564,7 +3550,6 @@ void zend_compile_break_continue(zend_ast *ast) /* {{{ */
} else {
int array_offset = CG(context).current_brk_cont;
zend_long nest_level = depth;
- znode *loop_var = zend_stack_top(&CG(loop_var_stack));
do {
if (array_offset == -1) {
@@ -3573,9 +3558,8 @@ void zend_compile_break_continue(zend_ast *ast) /* {{{ */
depth, depth == 1 ? "" : "s");
}
- if (nest_level > 1 && CG(context).brk_cont_array[array_offset].start >= 0) {
- generate_free_loop_var(loop_var);
- loop_var--;
+ if (nest_level > 1) {
+ generate_free_loop_var(&CG(context).brk_cont_array[array_offset].loop_var);
}
array_offset = CG(context).brk_cont_array[array_offset].parent;
@@ -3592,7 +3576,6 @@ void zend_resolve_goto_label(zend_op_array *op_array, znode *label_node, zend_op
zend_label *dest;
int current, distance, free_vars;
zval *label;
- znode *loop_var = NULL;
if (pass2_opline) {
label = RT_CONSTANT(op_array, pass2_opline->op2);
@@ -3613,7 +3596,7 @@ void zend_resolve_goto_label(zend_op_array *op_array, znode *label_node, zend_op
current = CG(context).current_brk_cont;
while (current != -1) {
- if (CG(context).brk_cont_array[current].start >= 0) {
+ if (CG(context).brk_cont_array[current].loop_var.op_type != IS_UNUSED) {
zend_emit_op(NULL, ZEND_NOP, NULL, NULL);
}
current = CG(context).brk_cont_array[current].parent;
@@ -3633,9 +3616,6 @@ void zend_resolve_goto_label(zend_op_array *op_array, znode *label_node, zend_op
} else {
current = CG(context).current_brk_cont;
}
- if (!pass2_opline) {
- loop_var = zend_stack_top(&CG(loop_var_stack));
- }
for (distance = 0, free_vars = 0; current != dest->brk_cont; distance++) {
if (current == -1) {
if (pass2_opline) {
@@ -3645,12 +3625,11 @@ void zend_resolve_goto_label(zend_op_array *op_array, znode *label_node, zend_op
}
zend_error_noreturn(E_COMPILE_ERROR, "'goto' into loop or switch statement is disallowed");
}
- if (CG(context).brk_cont_array[current].start >= 0) {
+ if (CG(context).brk_cont_array[current].loop_var.op_type != IS_UNUSED) {
if (pass2_opline) {
free_vars++;
} else {
- generate_free_loop_var(loop_var);
- loop_var--;
+ generate_free_loop_var(&CG(context).brk_cont_array[current].loop_var);
}
}
current = CG(context).brk_cont_array[current].parent;
@@ -3660,30 +3639,18 @@ void zend_resolve_goto_label(zend_op_array *op_array, znode *label_node, zend_op
if (free_vars) {
current = pass2_opline->extended_value;
while (current != dest->brk_cont) {
- if (CG(context).brk_cont_array[current].start >= 0) {
+ if (CG(context).brk_cont_array[current].loop_var.op_type != IS_UNUSED) {
zend_op *brk_opline = &op_array->opcodes[CG(context).brk_cont_array[current].brk];
- if (brk_opline->opcode == ZEND_FREE) {
- (pass2_opline - free_vars)->opcode = ZEND_FREE;
- (pass2_opline - free_vars)->op1_type = brk_opline->op1_type;
- if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
- (pass2_opline - free_vars)->op1.var = brk_opline->op1.var;
- } else {
- (pass2_opline - free_vars)->op1.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + brk_opline->op1.var);
- ZEND_VM_SET_OPCODE_HANDLER(pass2_opline - free_vars);
- }
- free_vars--;
- } else if (brk_opline->opcode == ZEND_FE_FREE) {
- (pass2_opline - free_vars)->opcode = ZEND_FE_FREE;
- (pass2_opline - free_vars)->op1_type = brk_opline->op1_type;
- if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
- (pass2_opline - free_vars)->op1.var = brk_opline->op1.var;
- } else {
- (pass2_opline - free_vars)->op1.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + brk_opline->op1.var);
- ZEND_VM_SET_OPCODE_HANDLER(pass2_opline - free_vars);
- }
- free_vars--;
+ (pass2_opline - free_vars)->opcode = brk_opline->opcode;
+ (pass2_opline - free_vars)->op1_type = brk_opline->op1_type;
+ if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
+ (pass2_opline - free_vars)->op1.var = brk_opline->op1.var;
+ } else {
+ (pass2_opline - free_vars)->op1.var = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + brk_opline->op1.var);
+ ZEND_VM_SET_OPCODE_HANDLER(pass2_opline - free_vars);
}
+ free_vars--;
}
current = CG(context).brk_cont_array[current].parent;
}
@@ -4801,14 +4768,6 @@ void zend_compile_func_decl(znode *result, zend_ast *ast) /* {{{ */
opline_ext->lineno = decl->start_lineno;
}
- {
- /* Push a separator to the loop variable stack */
- znode dummy_var;
- dummy_var.op_type = IS_UNUSED;
-
- zend_stack_push(&CG(loop_var_stack), (void *) &dummy_var);
- }
-
zend_compile_params(params_ast, return_type_ast);
if (uses_ast) {
zend_compile_closure_uses(uses_ast);
@@ -4826,9 +4785,6 @@ void zend_compile_func_decl(znode *result, zend_ast *ast) /* {{{ */
pass_two(CG(active_op_array));
zend_oparray_context_end(&orig_oparray_context);
- /* Pop the loop variable stack separator */
- zend_stack_del_top(&CG(loop_var_stack));
-
CG(active_op_array) = orig_op_array;
}
/* }}} */
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index 993a19fb6b..3f9c091061 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -110,10 +110,10 @@ typedef struct _zend_declarables {
} zend_declarables;
typedef struct _zend_brk_cont_element {
- int start;
int cont;
int brk;
int parent;
+ znode loop_var;
} zend_brk_cont_element;
typedef struct _zend_label {
diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h
index 28487a2a4a..780007174e 100644
--- a/Zend/zend_globals.h
+++ b/Zend/zend_globals.h
@@ -68,8 +68,6 @@ typedef struct _zend_ini_entry zend_ini_entry;
struct _zend_compiler_globals {
- zend_stack loop_var_stack;
-
zend_class_entry *active_class_entry;
zend_string *compiled_filename;