diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 1761f9e61ab..d8a086a4ba3 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -210,16 +210,21 @@ void zend_oparray_context_begin(zend_oparray_context *prev_context) /* {{{ */ CG(context).opcodes_size = INITIAL_OP_ARRAY_SIZE; CG(context).vars_size = 0; CG(context).literals_size = 0; - CG(context).current_brk_cont = -1; CG(context).backpatch_count = 0; CG(context).in_finally = 0; CG(context).fast_call_var = -1; + CG(context).current_brk_cont = -1; + CG(context).last_brk_cont = 0; + CG(context).brk_cont_array = NULL; CG(context).labels = NULL; } /* }}} */ void zend_oparray_context_end(zend_oparray_context *prev_context) /* {{{ */ { + if (CG(context).brk_cont_array) { + efree(CG(context).brk_cont_array); + } if (CG(context).labels) { zend_hash_destroy(CG(context).labels); FREE_HASHTABLE(CG(context).labels); @@ -562,7 +567,7 @@ static inline void zend_begin_loop(const znode *loop_var) /* {{{ */ zend_brk_cont_element *brk_cont_element; int parent = CG(context).current_brk_cont; - CG(context).current_brk_cont = CG(active_op_array)->last_brk_cont; + 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; @@ -580,7 +585,7 @@ static inline void zend_begin_loop(const znode *loop_var) /* {{{ */ static inline void zend_end_loop(int cont_addr) /* {{{ */ { zend_brk_cont_element *brk_cont_element - = &CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont]; + = &CG(context).brk_cont_array[CG(context).current_brk_cont]; 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; @@ -914,7 +919,7 @@ void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline, int pass2 } zend_error_noreturn(E_COMPILE_ERROR, "'goto' into loop or switch statement is disallowed"); } - current = op_array->brk_cont_array[current].parent; + current = CG(context).brk_cont_array[current].parent; } if (distance == 0) { @@ -3614,12 +3619,12 @@ void zend_compile_break_continue(zend_ast *ast) /* {{{ */ depth, depth == 1 ? "" : "s"); } - if (nest_level > 1 && CG(active_op_array)->brk_cont_array[array_offset].start >= 0) { + if (nest_level > 1 && CG(context).brk_cont_array[array_offset].start >= 0) { generate_free_loop_var(loop_var); loop_var--; } - array_offset = CG(active_op_array)->brk_cont_array[array_offset].parent; + array_offset = CG(context).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, NULL); diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 96850e31001..80bd4533465 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -109,15 +109,36 @@ typedef struct _zend_declarables { zend_long ticks; } zend_declarables; +typedef struct _zend_brk_cont_element { + int start; + int cont; + int brk; + int parent; +} zend_brk_cont_element; + +typedef struct _zend_label { + int brk_cont; + uint32_t opline_num; +} zend_label; + +typedef struct _zend_try_catch_element { + uint32_t try_op; + uint32_t catch_op; /* ketchup! */ + uint32_t finally_op; + uint32_t finally_end; +} zend_try_catch_element; + /* Compilation context that is different for each op array. */ typedef struct _zend_oparray_context { uint32_t opcodes_size; int vars_size; int literals_size; - int current_brk_cont; int backpatch_count; int in_finally; uint32_t fast_call_var; + int current_brk_cont; + int last_brk_cont; + zend_brk_cont_element *brk_cont_array; HashTable *labels; } zend_oparray_context; @@ -163,26 +184,6 @@ struct _zend_op { zend_uchar result_type; }; - -typedef struct _zend_brk_cont_element { - int start; - int cont; - int brk; - int parent; -} zend_brk_cont_element; - -typedef struct _zend_label { - int brk_cont; - uint32_t opline_num; -} zend_label; - -typedef struct _zend_try_catch_element { - uint32_t try_op; - uint32_t catch_op; /* ketchup! */ - uint32_t finally_op; - uint32_t finally_end; -} zend_try_catch_element; - /* method flags (types) */ #define ZEND_ACC_STATIC 0x01 #define ZEND_ACC_ABSTRACT 0x02 @@ -358,9 +359,8 @@ struct _zend_op_array { zend_string **vars; uint32_t *T_liveliness; - int last_brk_cont; + //TODO: improve layout ??? int last_try_catch; - zend_brk_cont_element *brk_cont_array; zend_try_catch_element *try_catch_array; /* static variables support */ diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index c0f96c88b0a..aed9bc8a137 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -78,9 +78,7 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz op_array->scope = NULL; op_array->prototype = NULL; - op_array->brk_cont_array = NULL; op_array->try_catch_array = NULL; - op_array->last_brk_cont = 0; op_array->static_variables = NULL; op_array->last_try_catch = 0; @@ -384,9 +382,6 @@ ZEND_API void destroy_op_array(zend_op_array *op_array) if (op_array->doc_comment) { zend_string_release(op_array->doc_comment); } - if (op_array->brk_cont_array) { - efree(op_array->brk_cont_array); - } if (op_array->try_catch_array) { efree(op_array->try_catch_array); } @@ -451,9 +446,9 @@ int get_next_op_number(zend_op_array *op_array) zend_brk_cont_element *get_next_brk_cont_element(zend_op_array *op_array) { - op_array->last_brk_cont++; - op_array->brk_cont_array = erealloc(op_array->brk_cont_array, sizeof(zend_brk_cont_element)*op_array->last_brk_cont); - return &op_array->brk_cont_array[op_array->last_brk_cont-1]; + CG(context).last_brk_cont++; + CG(context).brk_cont_array = erealloc(CG(context).brk_cont_array, sizeof(zend_brk_cont_element)*CG(context).last_brk_cont); + return &CG(context).brk_cont_array[CG(context).last_brk_cont-1]; } static void zend_update_extended_info(zend_op_array *op_array) @@ -676,7 +671,7 @@ static uint32_t zend_get_brk_cont_target(const zend_op_array *op_array, const ze int array_offset = opline->op1.num; zend_brk_cont_element *jmp_to; do { - jmp_to = &op_array->brk_cont_array[array_offset]; + jmp_to = &CG(context).brk_cont_array[array_offset]; if (nest_levels > 1) { array_offset = jmp_to->parent; } diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c index 799fec42dc1..75ad47c63c1 100644 --- a/ext/opcache/Optimizer/block_pass.c +++ b/ext/opcache/Optimizer/block_pass.c @@ -197,59 +197,6 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg, zend_optimiz blocks[op_array->try_catch_array[i].try_op].protected = 1; } } - /* Currently, we don't optimize op_arrays with BRK/CONT/GOTO opcodes, - * but, we have to keep brk_cont_array to avoid memory leaks during - * exception handling */ - if (op_array->last_brk_cont) { - int i, j; - - j = 0; - for (i = 0; i< op_array->last_brk_cont; i++) { - if (op_array->brk_cont_array[i].start >= 0 && - (op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_FREE || - op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_FE_FREE)) { - int parent = op_array->brk_cont_array[i].parent; - - while (parent >= 0 && - op_array->brk_cont_array[parent].start < 0 && - (op_array->opcodes[op_array->brk_cont_array[parent].brk].opcode != ZEND_FREE || - op_array->opcodes[op_array->brk_cont_array[parent].brk].opcode != ZEND_FE_FREE)) { - parent = op_array->brk_cont_array[parent].parent; - } - op_array->brk_cont_array[i].parent = parent; - j++; - } - } - if (j) { - cfg->loop_start = zend_arena_calloc(&ctx->arena, op_array->last_brk_cont, sizeof(zend_code_block *)); - cfg->loop_cont = zend_arena_calloc(&ctx->arena, op_array->last_brk_cont, sizeof(zend_code_block *)); - cfg->loop_brk = zend_arena_calloc(&ctx->arena, op_array->last_brk_cont, sizeof(zend_code_block *)); - j = 0; - for (i = 0; i< op_array->last_brk_cont; i++) { - if (op_array->brk_cont_array[i].start >= 0 && - (op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_FREE || - op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_FE_FREE)) { - if (i != j) { - op_array->brk_cont_array[j] = op_array->brk_cont_array[i]; - } - cfg->loop_start[j] = &blocks[op_array->brk_cont_array[j].start]; - cfg->loop_cont[j] = &blocks[op_array->brk_cont_array[j].cont]; - cfg->loop_brk[j] = &blocks[op_array->brk_cont_array[j].brk]; - START_BLOCK_OP(op_array->brk_cont_array[j].start); - START_BLOCK_OP(op_array->brk_cont_array[j].cont); - START_BLOCK_OP(op_array->brk_cont_array[j].brk); - blocks[op_array->brk_cont_array[j].start].protected = 1; - blocks[op_array->brk_cont_array[j].brk].protected = 1; - j++; - } - } - op_array->last_brk_cont = j; - } else { - efree(op_array->brk_cont_array); - op_array->brk_cont_array = NULL; - op_array->last_brk_cont = 0; - } - } /* Build CFG (Control Flow Graph) */ cur_block = blocks; @@ -517,16 +464,6 @@ static void zend_rebuild_access_path(zend_cfg *cfg, zend_op_array *op_array, int /* Walk thorough all paths */ zend_access_path(start, ctx); - /* Add brk/cont paths */ - if (op_array->last_brk_cont) { - int i; - for (i=0; i< op_array->last_brk_cont; i++) { - zend_access_path(cfg->loop_start[i], ctx); - zend_access_path(cfg->loop_cont[i], ctx); - zend_access_path(cfg->loop_brk[i], ctx); - } - } - /* Add exception paths */ if (op_array->last_try_catch) { int i; @@ -1189,16 +1126,6 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array) op_array->last_try_catch = j; } - /* adjust loop jump targets */ - if (op_array->last_brk_cont) { - int i; - for (i = 0; i< op_array->last_brk_cont; i++) { - op_array->brk_cont_array[i].start = cfg->loop_start[i]->start_opline - new_opcodes; - op_array->brk_cont_array[i].cont = cfg->loop_cont[i]->start_opline - new_opcodes; - op_array->brk_cont_array[i].brk = cfg->loop_brk[i]->start_opline - new_opcodes; - } - } - /* adjust jump targets */ for (cur_block = blocks; cur_block; cur_block = cur_block->next) { if (!cur_block->access) { diff --git a/ext/opcache/Optimizer/nop_removal.c b/ext/opcache/Optimizer/nop_removal.c index 20510b41635..0af6c687d8a 100644 --- a/ext/opcache/Optimizer/nop_removal.c +++ b/ext/opcache/Optimizer/nop_removal.c @@ -117,13 +117,6 @@ void zend_optimizer_nop_removal(zend_op_array *op_array) } } - /* update brk/cont array */ - for (j = 0; j < op_array->last_brk_cont; j++) { - op_array->brk_cont_array[j].brk -= shiftlist[op_array->brk_cont_array[j].brk]; - op_array->brk_cont_array[j].cont -= shiftlist[op_array->brk_cont_array[j].cont]; - op_array->brk_cont_array[j].start -= shiftlist[op_array->brk_cont_array[j].start]; - } - /* update try/catch array */ for (j = 0; j < op_array->last_try_catch; j++) { op_array->try_catch_array[j].try_op -= shiftlist[op_array->try_catch_array[j].try_op]; diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c index 44c400ca3fd..ffe23f30afd 100644 --- a/ext/opcache/Optimizer/zend_optimizer.c +++ b/ext/opcache/Optimizer/zend_optimizer.c @@ -340,29 +340,11 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array, */ case ZEND_FREE: case ZEND_CASE: { - zend_op *m, *n; - int brk = op_array->last_brk_cont; - zend_bool in_switch = 0; - while (brk--) { - if (op_array->brk_cont_array[brk].start <= (opline - op_array->opcodes) && - op_array->brk_cont_array[brk].brk > (opline - op_array->opcodes)) { - in_switch = 1; - break; - } - } - - if (!in_switch) { - ZEND_ASSERT(opline->opcode == ZEND_FREE); - MAKE_NOP(opline); - zval_dtor(val); - return 1; - } + zend_op *m = opline; + zend_op *end = op_array->opcodes + op_array->last; - m = opline; - n = op_array->opcodes + op_array->brk_cont_array[brk].brk + 1; - while (m < n) { - if (ZEND_OP1_TYPE(m) == type && - ZEND_OP1(m).var == var) { + while (m < end) { + if (ZEND_OP1_TYPE(m) == type && ZEND_OP1(m).var == var) { if (m->opcode == ZEND_CASE) { zval old_val; ZVAL_COPY_VALUE(&old_val, val); @@ -371,6 +353,7 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array, ZVAL_COPY_VALUE(val, &old_val); } else if (m->opcode == ZEND_FREE) { MAKE_NOP(m); + break; } else { ZEND_ASSERT(0); } diff --git a/ext/opcache/Optimizer/zend_optimizer_internal.h b/ext/opcache/Optimizer/zend_optimizer_internal.h index c2f97ff715a..69288c72283 100644 --- a/ext/opcache/Optimizer/zend_optimizer_internal.h +++ b/ext/opcache/Optimizer/zend_optimizer_internal.h @@ -73,9 +73,6 @@ typedef struct _zend_cfg { zend_code_block *blocks; zend_code_block **try; zend_code_block **catch; - zend_code_block **loop_start; - zend_code_block **loop_cont; - zend_code_block **loop_brk; zend_op **Tsource; char *same_t; } zend_cfg; diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index 084d9b9a9db..67dfd32f4f1 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -459,7 +459,6 @@ static void zend_file_cache_serialize_op_array(zend_op_array *op_arra SERIALIZE_STR(op_array->function_name); SERIALIZE_STR(op_array->filename); - SERIALIZE_PTR(op_array->brk_cont_array); SERIALIZE_PTR(op_array->scope); SERIALIZE_STR(op_array->doc_comment); SERIALIZE_PTR(op_array->try_catch_array); @@ -983,7 +982,6 @@ static void zend_file_cache_unserialize_op_array(zend_op_array *op_arr UNSERIALIZE_STR(op_array->function_name); UNSERIALIZE_STR(op_array->filename); - UNSERIALIZE_PTR(op_array->brk_cont_array); UNSERIALIZE_PTR(op_array->scope); UNSERIALIZE_STR(op_array->doc_comment); UNSERIALIZE_PTR(op_array->try_catch_array); diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index 309d44b80d6..4a9a9a773ca 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -590,10 +590,6 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc op_array->arg_info = arg_info; } - if (op_array->brk_cont_array) { - zend_accel_store(op_array->brk_cont_array, sizeof(zend_brk_cont_element) * op_array->last_brk_cont); - } - if (op_array->scope) { op_array->scope = zend_shared_alloc_get_xlat_entry(op_array->scope); } diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c index 00f613273b4..9265ba5ce9c 100644 --- a/ext/opcache/zend_persist_calc.c +++ b/ext/opcache/zend_persist_calc.c @@ -229,10 +229,6 @@ static void zend_persist_op_array_calc_ex(zend_op_array *op_array) } } - if (op_array->brk_cont_array) { - ADD_DUP_SIZE(op_array->brk_cont_array, sizeof(zend_brk_cont_element) * op_array->last_brk_cont); - } - if (ZCG(accel_directives).save_comments && op_array->doc_comment) { ADD_STRING(op_array->doc_comment); }