From: Nikita Popov Date: Tue, 7 Jul 2015 17:46:29 +0000 (+0200) Subject: Remove loop_var_stack X-Git-Tag: php-7.0.0beta1~12^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b3a4c05071c3786e27e1326fa1b4d5acad62fccd;p=php 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. --- 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;