]> granicus.if.org Git - php/commitdiff
We don't nees zend_op_array->brk_cont_array at run-time anymore.
authorDmitry Stogov <dmitry@zend.com>
Tue, 10 Nov 2015 18:48:03 +0000 (21:48 +0300)
committerDmitry Stogov <dmitry@zend.com>
Tue, 10 Nov 2015 18:48:03 +0000 (21:48 +0300)
Move zend_op_array->brk_cont_array into CG(context).brk_cont_array.
Use more compact zend_op_array->live_range instead of zend_op_array->brk_cont_array.
Semantic is kept unchanged.

12 files changed:
Zend/tests/temporary_cleaning_008.phpt [new file with mode: 0644]
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_execute.c
Zend/zend_opcode.c
ext/opcache/Optimizer/block_pass.c
ext/opcache/Optimizer/nop_removal.c
ext/opcache/Optimizer/zend_optimizer.c
ext/opcache/Optimizer/zend_optimizer_internal.h
ext/opcache/zend_file_cache.c
ext/opcache/zend_persist.c
ext/opcache/zend_persist_calc.c

diff --git a/Zend/tests/temporary_cleaning_008.phpt b/Zend/tests/temporary_cleaning_008.phpt
new file mode 100644 (file)
index 0000000..fabd3b4
--- /dev/null
@@ -0,0 +1,15 @@
+--TEST--
+Optimization of constant switch expression
+--FILE--
+<?php
+try {
+       switch ("1" . (int)2) {
+               case 12:
+                       throw new Exception();
+       }
+} catch (Exception $e) {
+       echo "exception\n";
+} 
+?>
+--EXPECT--
+exception
index 42225638c1b3db4ddbbe3c7f234be70304749e69..4f4701189c7ba88a2b920d05af0a6fa9a5e4c459 100644 (file)
@@ -218,16 +218,22 @@ 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);
+               CG(context).brk_cont_array = NULL;
+       }
        if (CG(context).labels) {
                zend_hash_destroy(CG(context).labels);
                FREE_HASHTABLE(CG(context).labels);
@@ -567,14 +573,28 @@ void zend_stop_lexing(void)
        LANG_SCNG(yy_cursor) = LANG_SCNG(yy_limit);
 }
 
+static void zend_add_live_range(zend_op_array *op_array, uint32_t start, uint32_t end) /* {{{ */
+{
+       zend_live_range *range;
+
+       if (start != end) {
+               op_array->last_live_range++;
+               op_array->live_range = erealloc(op_array->live_range, sizeof(zend_live_range) * op_array->last_live_range);
+               range = op_array->live_range + op_array->last_live_range - 1;
+               range->start = start;
+               range->end = end;
+       }
+}
+/* }}} */
+
 static inline void zend_begin_loop(zend_uchar free_opcode, const znode *loop_var) /* {{{ */
 {
        zend_brk_cont_element *brk_cont_element;
        int parent = CG(context).current_brk_cont;
        zend_loop_var info = {0};
 
-       CG(context).current_brk_cont = CG(active_op_array)->last_brk_cont;
-       brk_cont_element = get_next_brk_cont_element(CG(active_op_array));
+       CG(context).current_brk_cont = CG(context).last_brk_cont;
+       brk_cont_element = get_next_brk_cont_element();
        brk_cont_element->parent = parent;
 
        if (loop_var && (loop_var->op_type & (IS_VAR|IS_TMP_VAR))) {
@@ -597,7 +617,7 @@ static inline void zend_begin_loop(zend_uchar free_opcode, 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;
@@ -3734,14 +3754,14 @@ void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline) /* {{{ */
        ZVAL_NULL(label);
 
        current = opline->extended_value;
-       for (; current != dest->brk_cont; current = op_array->brk_cont_array[current].parent) {
+       for (; current != dest->brk_cont; current = CG(context).brk_cont_array[current].parent) {
                if (current == -1) {
                        CG(in_compilation) = 1;
                        CG(active_op_array) = op_array;
                        CG(zend_lineno) = opline->lineno;
                        zend_error_noreturn(E_COMPILE_ERROR, "'goto' into loop or switch statement is disallowed");
                }
-               if (op_array->brk_cont_array[current].start >= 0) {
+               if (CG(context).brk_cont_array[current].start >= 0) {
                        remove_oplines--;
                }
        }
@@ -3989,7 +4009,9 @@ void zend_compile_foreach(zend_ast *ast) /* {{{ */
 
        zend_end_loop(opnum_fetch);
 
-       zend_emit_op(NULL, ZEND_FE_FREE, &reset_node, NULL);
+       opline = zend_emit_op(NULL, ZEND_FE_FREE, &reset_node, NULL);
+       zend_add_live_range(CG(active_op_array),
+               opnum_fetch,  opline - CG(active_op_array)->opcodes);
 }
 /* }}} */
 
@@ -4046,10 +4068,11 @@ void zend_compile_switch(zend_ast *ast) /* {{{ */
        znode expr_node, case_node;
        zend_op *opline;
        uint32_t *jmpnz_opnums = safe_emalloc(sizeof(uint32_t), cases->children, 0);
-       uint32_t opnum_default_jmp;
+       uint32_t opnum_default_jmp, opnum_start;
 
        zend_compile_expr(&expr_node, expr_ast);
 
+       opnum_start = get_next_op_number(CG(active_op_array));
        zend_begin_loop(ZEND_FREE, &expr_node);
 
        case_node.op_type = IS_TMP_VAR;
@@ -4112,7 +4135,9 @@ void zend_compile_switch(zend_ast *ast) /* {{{ */
        zend_end_loop(get_next_op_number(CG(active_op_array)));
 
        if (expr_node.op_type == IS_VAR || expr_node.op_type == IS_TMP_VAR) {
-               zend_emit_op(NULL, ZEND_FREE, &expr_node, NULL);
+               opline = zend_emit_op(NULL, ZEND_FREE, &expr_node, NULL);
+               zend_add_live_range(CG(active_op_array),
+                       opnum_start, opline - CG(active_op_array)->opcodes);
        } else if (expr_node.op_type == IS_CONST) {
                zval_dtor(&expr_node.u.constant);
        }
@@ -6426,8 +6451,8 @@ void zend_compile_silence(znode *result, zend_ast *ast) /* {{{ */
 {
        zend_ast *expr_ast = ast->child[0];
        znode silence_node;
-       uint32_t begin_opline_num, end_opline_num;
-       zend_brk_cont_element *brk_cont_element;
+       uint32_t begin_opline_num;
+       zend_op *opline;
 
        begin_opline_num = get_next_op_number(CG(active_op_array));
        zend_emit_op_tmp(&silence_node, ZEND_BEGIN_SILENCE, NULL, NULL);
@@ -6440,15 +6465,12 @@ void zend_compile_silence(znode *result, zend_ast *ast) /* {{{ */
                zend_compile_expr(result, expr_ast);
        }
 
-       end_opline_num = get_next_op_number(CG(active_op_array));
-       zend_emit_op(NULL, ZEND_END_SILENCE, &silence_node, NULL);
+       opline = zend_emit_op(NULL, ZEND_END_SILENCE, &silence_node, NULL);
 
        /* Store BEGIN_SILENCE/END_SILENCE pair to restore previous
         * EG(error_reporting) value on exception */
-       brk_cont_element = get_next_brk_cont_element(CG(active_op_array));
-       brk_cont_element->start = begin_opline_num;
-       brk_cont_element->cont = brk_cont_element->brk = end_opline_num;
-       brk_cont_element->parent = -1;
+       zend_add_live_range(CG(active_op_array),
+               begin_opline_num + 1, opline - CG(active_op_array)->opcodes);
 }
 /* }}} */
 
@@ -6768,10 +6790,6 @@ static void zend_compile_encaps_list(znode *result, zend_ast *ast) /* {{{ */
                GET_NODE(result, opline->result);
        } else {
                uint32_t var;
-               zend_brk_cont_element *info = get_next_brk_cont_element(CG(active_op_array));
-               info->start = rope_init_lineno;
-               info->parent = CG(context).current_brk_cont;
-               info->cont = info->brk = opline - CG(active_op_array)->opcodes;
 
                init_opline->extended_value = j;
                opline->opcode = ZEND_ROPE_END;
@@ -6785,6 +6803,10 @@ static void zend_compile_encaps_list(znode *result, zend_ast *ast) /* {{{ */
                        get_temporary_variable(CG(active_op_array));
                        i--;                    
                }
+
+               zend_add_live_range(CG(active_op_array),
+                       rope_init_lineno, opline - CG(active_op_array)->opcodes);
+
                /* Update all the previous opcodes to use the same variable */
                while (opline != init_opline) {
                        opline--;
index b777a0ba8c26672846940e7abf3c4cd9eaa0644b..46838def594f9f00e3facdbb129b75cac01cf320 100644 (file)
@@ -111,18 +111,6 @@ typedef struct _zend_declarables {
        zend_long ticks;
 } zend_declarables;
 
-/* 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;
-       HashTable *labels;
-} zend_oparray_context;
-
 /* Compilation context that is different for each file, but shared between op arrays. */
 typedef struct _zend_file_context {
        zend_declarables declarables;
@@ -185,6 +173,25 @@ typedef struct _zend_try_catch_element {
        uint32_t finally_end;
 } zend_try_catch_element;
 
+typedef struct _zend_live_range {
+       uint32_t start;
+       uint32_t end;
+} zend_live_range;
+
+/* 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        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;
+
 /* method flags (types) */
 #define ZEND_ACC_STATIC                        0x01
 #define ZEND_ACC_ABSTRACT              0x02
@@ -354,9 +361,9 @@ struct _zend_op_array {
        uint32_t T;
        zend_string **vars;
 
-       int last_brk_cont;
+       int last_live_range;
        int last_try_catch;
-       zend_brk_cont_element *brk_cont_array;
+       zend_live_range *live_range;
        zend_try_catch_element *try_catch_array;
 
        /* static variables support */
@@ -755,7 +762,7 @@ zend_op *get_next_op(zend_op_array *op_array);
 void init_op(zend_op *op);
 int get_next_op_number(zend_op_array *op_array);
 ZEND_API int pass_two(zend_op_array *op_array);
-zend_brk_cont_element *get_next_brk_cont_element(zend_op_array *op_array);
+zend_brk_cont_element *get_next_brk_cont_element(void);
 ZEND_API zend_bool zend_is_compiling(void);
 ZEND_API char *zend_make_compiled_string_description(const char *name);
 ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers);
index f851833a2df6feddf98a672380ab65579ae48eca..0fd99e9f736cd75a0704ba95f321d8ebee4475ec 100644 (file)
@@ -2549,30 +2549,33 @@ static void cleanup_live_vars(zend_execute_data *execute_data, uint32_t op_num,
 {
        int i;
 
-       for (i = 0; i < EX(func)->op_array.last_brk_cont; i++) {
-               const zend_brk_cont_element *brk_cont = &EX(func)->op_array.brk_cont_array[i];
-               if (brk_cont->start < 0) {
-                       continue;
-               } else if (brk_cont->start > op_num) {
+       i = EX(func)->op_array.last_live_range;
+       while (i) {
+               const zend_live_range *range;
+
+               i--;
+               range = &EX(func)->op_array.live_range[i];
+               if (range->end <= op_num) {
                        /* further blocks will not be relevant... */
                        break;
-               } else if (op_num < brk_cont->brk) {
-                       if (!catch_op_num || catch_op_num >= brk_cont->brk) {
-                               zend_op *brk_opline = &EX(func)->op_array.opcodes[brk_cont->brk];
-
-                               if (brk_opline->opcode == ZEND_FREE) {
-                                       zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
-                               } else if (brk_opline->opcode == ZEND_FE_FREE) {
-                                       zval *var = EX_VAR(brk_opline->op1.var);
+               } else if (op_num >= range->start) {
+                       if (!catch_op_num || catch_op_num >= range->end) {
+                               zend_op *opline = &EX(func)->op_array.opcodes[range->end];
+                               uint32_t var_num = opline->op1.var;
+                               zval *var = EX_VAR(var_num);
+
+                               if (opline->opcode == ZEND_FREE) {
+                                       zval_ptr_dtor_nogc(var);
+                               } else if (opline->opcode == ZEND_FE_FREE) {
                                        if (Z_TYPE_P(var) != IS_ARRAY && Z_FE_ITER_P(var) != (uint32_t)-1) {
                                                zend_hash_iterator_del(Z_FE_ITER_P(var));
                                        }
                                        zval_ptr_dtor_nogc(var);
-                               } else if (brk_opline->opcode == ZEND_ROPE_END) {
-                                       zend_string **rope = (zend_string **) EX_VAR(brk_opline->op1.var);
+                               } else if (opline->opcode == ZEND_ROPE_END) {
+                                       zend_string **rope = (zend_string **)var;
                                        zend_op *last = EX(func)->op_array.opcodes + op_num;
                                        while ((last->opcode != ZEND_ROPE_ADD && last->opcode != ZEND_ROPE_INIT)
-                                                       || last->result.var != brk_opline->op1.var) {
+                                                       || last->result.var != var_num) {
                                                ZEND_ASSERT(last >= EX(func)->op_array.opcodes);
                                                last--;
                                        }
@@ -2584,10 +2587,10 @@ static void cleanup_live_vars(zend_execute_data *execute_data, uint32_t op_num,
                                                        zend_string_release(rope[j]);
                                                } while (j--);
                                        }
-                               } else if (brk_opline->opcode == ZEND_END_SILENCE) {
+                               } else if (opline->opcode == ZEND_END_SILENCE) {
                                        /* restore previous error_reporting value */
-                                       if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(brk_opline->op1.var)) != 0) {
-                                               EG(error_reporting) = Z_LVAL_P(EX_VAR(brk_opline->op1.var));
+                                       if (!EG(error_reporting) && Z_LVAL_P(var) != 0) {
+                                               EG(error_reporting) = Z_LVAL_P(var);
                                        }
                                }
                        }
index 524eb5cb676d1bb22613c5a1b8eab08474374626..73f3744341402182a9c1f4eb01382199b5c66dca 100644 (file)
@@ -78,9 +78,9 @@ 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->live_range = NULL;
        op_array->try_catch_array = NULL;
-       op_array->last_brk_cont = 0;
+       op_array->last_live_range = 0;
 
        op_array->static_variables = NULL;
        op_array->last_try_catch = 0;
@@ -387,8 +387,8 @@ 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->live_range) {
+               efree(op_array->live_range);
        }
        if (op_array->try_catch_array) {
                efree(op_array->try_catch_array);
@@ -451,11 +451,11 @@ int get_next_op_number(zend_op_array *op_array)
        return op_array->last;
 }
 
-zend_brk_cont_element *get_next_brk_cont_element(zend_op_array *op_array)
+zend_brk_cont_element *get_next_brk_cont_element(void)
 {
-       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)
@@ -570,7 +570,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;
                }
index 4053fe7da470ba3083bf9820faaa0c8b5000daca..1d172b2a5ee3daac079b26a0852c276116f3e393 100644 (file)
@@ -186,60 +186,18 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg, zend_optimiz
        /* 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;
+       if (op_array->last_live_range) {
+               int i;
 
-               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 ||
-                            op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_ROPE_END ||
-                            op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_END_SILENCE)) {
-                               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 ||
-                                            op_array->opcodes[op_array->brk_cont_array[i].brk].opcode != ZEND_ROPE_END ||
-                                       op_array->opcodes[op_array->brk_cont_array[parent].brk].opcode != ZEND_END_SILENCE)) {
-                                       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 ||
-                                    op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_ROPE_END ||
-                                    op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_END_SILENCE)) {
-                                       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;
+               cfg->live_range_start = zend_arena_calloc(&ctx->arena, op_array->last_live_range, sizeof(zend_code_block *));
+               cfg->live_range_end   = zend_arena_calloc(&ctx->arena, op_array->last_live_range, sizeof(zend_code_block *));
+               for (i = 0; i< op_array->last_live_range; i++) {
+                       cfg->live_range_start[i] = &blocks[op_array->live_range[i].start];
+                       cfg->live_range_end[i]   = &blocks[op_array->live_range[i].end];
+                       START_BLOCK_OP(op_array->live_range[i].start);
+                       START_BLOCK_OP(op_array->live_range[i].end);
+                       blocks[op_array->live_range[i].start].protected = 1;
+                       blocks[op_array->live_range[i].end].protected = 1;
                }
        }
 
@@ -505,12 +463,11 @@ static void zend_rebuild_access_path(zend_cfg *cfg, zend_op_array *op_array, int
        zend_access_path(start, ctx);
 
        /* Add brk/cont paths */
-       if (op_array->last_brk_cont) {
+       if (op_array->last_live_range) {
                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);
+               for (i=0; i< op_array->last_live_range; i++) {
+                       zend_access_path(cfg->live_range_start[i], ctx);
+                       zend_access_path(cfg->live_range_end[i], ctx);
                }
        }
 
@@ -628,6 +585,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
                        zval c = ZEND_OP1_LITERAL(src);
                        zval_copy_ctor(&c);
                        if (zend_optimizer_update_op1_const(op_array, opline, &c)) {
+                               zend_optimizer_remove_live_range(op_array, op1.var);
                                VAR_SOURCE(op1) = NULL;
                                literal_dtor(&ZEND_OP1_LITERAL(src));
                                MAKE_NOP(src);
@@ -644,6 +602,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
                        zval c = ZEND_OP1_LITERAL(src);
                        zval_copy_ctor(&c);
                        if (zend_optimizer_update_op2_const(op_array, opline, &c)) {
+                               zend_optimizer_remove_live_range(op_array, op2.var);
                                VAR_SOURCE(op2) = NULL;
                                literal_dtor(&ZEND_OP1_LITERAL(src));
                                MAKE_NOP(src);
@@ -1185,12 +1144,11 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array)
        }
 
        /* adjust loop jump targets */
-       if (op_array->last_brk_cont) {
+       if (op_array->last_live_range) {
                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;
+               for (i = 0; i< op_array->last_live_range; i++) {
+                       op_array->live_range[i].start = cfg->live_range_start[i]->start_opline - new_opcodes;
+                       op_array->live_range[i].end   = cfg->live_range_end[i]->start_opline - new_opcodes;
                }
        }
 
index 0869bc715c695122e1989b66118cdf245d394c67..8a20eb2007d8b2eb4e5075c6e5cac98cd2d5c0d2 100644 (file)
@@ -109,10 +109,9 @@ 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];
+               for (j = 0; j < op_array->last_live_range; j++) {
+                       op_array->live_range[j].start -= shiftlist[op_array->live_range[j].start];
+                       op_array->live_range[j].end   -= shiftlist[op_array->live_range[j].end];
                }
 
                /* update try/catch array */
index 70cf4ccfe102750f2b989fecee0455b4ad082955..20b7a75f56646bc0d0565fc4e470e67594c6f7dd 100644 (file)
@@ -347,6 +347,25 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array,
        return 1;
 }
 
+void zend_optimizer_remove_live_range(zend_op_array *op_array, uint32_t var)
+{
+       if (op_array->last_live_range) {
+               int i = 0;
+               int j = 0;
+
+               do {
+                       if (op_array->opcodes[op_array->live_range[i].end].op1.var != var) {
+                               if (i != j) {
+                                       op_array->live_range[j] = op_array->live_range[i];
+                               }
+                               j++;
+                       }
+                       i++;
+               } while (i < op_array->last_live_range);
+               op_array->last_live_range = j;
+       }
+}
+
 int zend_optimizer_replace_by_const(zend_op_array *op_array,
                                     zend_op       *opline,
                                     zend_uchar     type,
@@ -401,11 +420,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;
+                                       int brk = op_array->last_live_range;
                                        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)) {
+                                               if (op_array->live_range[brk].start <= (opline - op_array->opcodes) &&
+                                                   op_array->live_range[brk].end > (opline - op_array->opcodes)) {
                                                        in_switch = 1;
                                                        break;
                                                }
@@ -419,7 +438,13 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array,
                                        }
 
                                        m = opline;
-                                       n = op_array->opcodes + op_array->brk_cont_array[brk].brk + 1;
+                                       n = op_array->opcodes + op_array->live_range[brk].end;
+                                       if (n->opcode == ZEND_FREE &&
+                                           !(n->extended_value & ZEND_FREE_ON_RETURN)) {
+                                               n++;
+                                       } else {
+                                               n = op_array->opcodes + op_array->last;
+                                       }
                                        while (m < n) {
                                                if (ZEND_OP1_TYPE(m) == type &&
                                                                ZEND_OP1(m).var == var) {
@@ -438,6 +463,7 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array,
                                                m++;
                                        }
                                        zval_dtor(val);
+                                       zend_optimizer_remove_live_range(op_array, var);
                                        return 1;
                                }
                                case ZEND_VERIFY_RETURN_TYPE: {
@@ -451,18 +477,26 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array,
                                                return 0;
                                        }
                                        MAKE_NOP(opline);
-                                       zend_optimizer_update_op1_const(op_array, opline + 1, val);
-                                       return 1;
+                                       opline++;
+                                       break;
                                  }
                                default:
                                        break;
                        }
-                       return zend_optimizer_update_op1_const(op_array, opline, val);
+                       if (zend_optimizer_update_op1_const(op_array, opline, val)) {
+                               zend_optimizer_remove_live_range(op_array, var);
+                               return 1;
+                       }
+                       return 0;
                }
 
                if (ZEND_OP2_TYPE(opline) == type &&
                        ZEND_OP2(opline).var == var) {
-                       return zend_optimizer_update_op2_const(op_array, opline, val);
+                       if (zend_optimizer_update_op2_const(op_array, opline, val)) {
+                               zend_optimizer_remove_live_range(op_array, var);
+                               return 1;
+                       }
+                       return 0;
                }
                opline++;
        }
index 90df3cfadc140b20bab26279ffd0d2eeab09393e..c20634087f8a9eb03bf89f5495bcc8987348be65 100644 (file)
@@ -76,9 +76,8 @@ 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_code_block   **live_range_start;
+       zend_code_block   **live_range_end;
        zend_op           **Tsource;
        char               *same_t;
 } zend_cfg;
@@ -130,6 +129,7 @@ int  zend_optimizer_replace_by_const(zend_op_array *op_array,
                                      uint32_t       var,
                                      zval          *val);
 
+void zend_optimizer_remove_live_range(zend_op_array *op_array, uint32_t var);
 void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx);
 void zend_optimizer_pass2(zend_op_array *op_array);
 void zend_optimizer_pass3(zend_op_array *op_array);
index 7c615e927b4b33a67448f5a812c8903d45ae05c1..3fb3c7be2cb0389c24a27c42776b646ed5d0092e 100644 (file)
@@ -463,7 +463,7 @@ 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->live_range);
                SERIALIZE_PTR(op_array->scope);
                SERIALIZE_STR(op_array->doc_comment);
                SERIALIZE_PTR(op_array->try_catch_array);
@@ -1014,7 +1014,7 @@ 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->live_range);
                UNSERIALIZE_PTR(op_array->scope);
                UNSERIALIZE_STR(op_array->doc_comment);
                UNSERIALIZE_PTR(op_array->try_catch_array);
index 1f5abb46524315dc45fe5a8a63d19534e4dbb7e3..97757142fc68b94ffa8e52526a37e78ac9733492 100644 (file)
@@ -617,8 +617,8 @@ 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->live_range) {
+               zend_accel_store(op_array->live_range, sizeof(zend_live_range) * op_array->last_live_range);
        }
 
        if (op_array->scope) {
index 42d962b7cbfdd5b8549d4643620be343f002145c..51664f28d4f7f81741e8436fc8eb9973a5e3f8c6 100644 (file)
@@ -234,8 +234,8 @@ 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 (op_array->live_range) {
+               ADD_DUP_SIZE(op_array->live_range, sizeof(zend_live_range) * op_array->last_live_range);
        }
 
        if (ZCG(accel_directives).save_comments && op_array->doc_comment) {