Browse Source

Remove loop_var_stack

Instead add a loop_var member to brk_cont_element. Now that
brk_cont is compile-time the distinction is no longer necessary.

Also drops brk_cont.start, check the loop_var op_type instead.
pull/1399/head
Nikita Popov 11 years ago
parent
commit
b3a4c05071
  1. 3
      Zend/zend.c
  2. 102
      Zend/zend_compile.c
  3. 2
      Zend/zend_compile.h
  4. 2
      Zend/zend_globals.h

3
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;
}

102
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;
}
/* }}} */

2
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 {

2
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;

Loading…
Cancel
Save