]> granicus.if.org Git - php/commitdiff
Use arena allocator for optimizer temporary data structures
authorDmitry Stogov <dmitry@zend.com>
Wed, 18 Jun 2014 13:09:37 +0000 (17:09 +0400)
committerDmitry Stogov <dmitry@zend.com>
Wed, 18 Jun 2014 13:09:37 +0000 (17:09 +0400)
Zend/zend_arena.h
ext/opcache/Optimizer/block_pass.c
ext/opcache/Optimizer/compact_literals.c
ext/opcache/Optimizer/optimize_func_calls.c
ext/opcache/Optimizer/optimize_temp_vars_5.c
ext/opcache/Optimizer/pass1_5.c
ext/opcache/Optimizer/pass5.c
ext/opcache/Optimizer/pass9.c
ext/opcache/Optimizer/zend_optimizer.c
ext/opcache/Optimizer/zend_optimizer_internal.h

index 68fb660bbb275c1966c52648846826db801a4e60..69ac6687ef15341226d1ab92c8ca9660ac7c91d3 100644 (file)
@@ -78,17 +78,35 @@ static zend_always_inline void* zend_arena_alloc(zend_arena **arena_ptr, size_t
        return (void*) ptr;
 }
 
-static zend_always_inline void* zend_arena_calloc(zend_arena **arena_ptr, size_t unit_size, size_t count)
+static zend_always_inline void* zend_arena_calloc(zend_arena **arena_ptr, size_t count, size_t unit_size)
 {
-       size_t size = ZEND_MM_ALIGNED_SIZE(unit_size) * count;
+       size_t size = unit_size * count;
        void *ret;
 
-       ZEND_ASSERT(size > ZEND_MM_ALIGNED_SIZE(unit_size) && size > count);
+       ZEND_ASSERT(size >= unit_size && size >= count);
        ret = zend_arena_alloc(arena_ptr, size);
        memset(ret, 0, size);
        return ret;
 }
 
+static zend_always_inline void* zend_arena_checkpoint(zend_arena *arena)
+{
+       return arena->ptr;
+}
+
+static zend_always_inline void zend_arena_release(zend_arena **arena_ptr, void *checkpoint)
+{
+       zend_arena *arena = *arena_ptr;
+
+       while (UNEXPECTED((char*)checkpoint > arena->end) ||
+              UNEXPECTED((char*)checkpoint < (char*)arena)) {
+               zend_arena *prev = arena->prev;
+               efree(arena);
+               *arena_ptr = arena = prev;
+       }
+       arena->ptr = (char*)checkpoint;
+}
+
 #endif /* _ZEND_ARENA_H_ */
 
 /*
index 20b7a1ae31968992139500bb5d53b4fd4538fb42..7df2764d937e32867b9af51ee1efa9e109606832 100644 (file)
@@ -80,7 +80,7 @@ static inline void print_block(zend_code_block *block, zend_op *opcodes, char *t
 /* find code blocks in op_array
    code block is a set of opcodes with single flow of control, i.e. without jmps,
    branches, etc. */
-static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg)
+static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg, zend_optimizer_ctx *ctx)
 {
        zend_op *opline;
        zend_op *end = op_array->opcodes + op_array->last;
@@ -88,7 +88,7 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg)
        zend_uint opno = 0;
 
        memset(cfg, 0, sizeof(zend_cfg));
-       blocks = cfg->blocks = ecalloc(op_array->last + 2, sizeof(zend_code_block));
+       blocks = cfg->blocks = zend_arena_calloc(&ctx->arena, op_array->last + 2, sizeof(zend_code_block));
        opline = op_array->opcodes;
        blocks[0].start_opline = opline;
        blocks[0].start_opline_no = 0;
@@ -102,7 +102,6 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg)
                                /* would not optimize non-optimized BRK/CONTs - we cannot
                                 really know where it jumps, so these optimizations are
                                too dangerous */
-                               efree(blocks);
                                return 0;
 #if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
                        case ZEND_FAST_CALL:
@@ -169,8 +168,8 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg)
        /* first find block start points */
        if (op_array->last_try_catch) {
                int i;
-               cfg->try = ecalloc(op_array->last_try_catch, sizeof(zend_code_block *));
-               cfg->catch = ecalloc(op_array->last_try_catch, sizeof(zend_code_block *));
+               cfg->try = zend_arena_calloc(&ctx->arena, op_array->last_try_catch, sizeof(zend_code_block *));
+               cfg->catch = zend_arena_calloc(&ctx->arena, op_array->last_try_catch, sizeof(zend_code_block *));
                for (i = 0; i< op_array->last_try_catch; i++) {
                        cfg->try[i] = &blocks[op_array->try_catch_array[i].try_op];
                        cfg->catch[i] = &blocks[op_array->try_catch_array[i].catch_op];
@@ -203,9 +202,9 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg)
                        }
                }
                if (j) {
-                       cfg->loop_start = ecalloc(op_array->last_brk_cont, sizeof(zend_code_block *));
-                       cfg->loop_cont  = ecalloc(op_array->last_brk_cont, sizeof(zend_code_block *));
-                       cfg->loop_brk   = ecalloc(op_array->last_brk_cont, sizeof(zend_code_block *));
+                       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 &&
@@ -317,18 +316,16 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg)
        zend_block_source *__s = tob->sources; \
     while (__s && __s->from != fromb) __s = __s->next; \
        if (__s == NULL) { \
-               zend_block_source *__t = emalloc(sizeof(zend_block_source)); \
+               zend_block_source *__t = zend_arena_alloc(&ctx->arena, sizeof(zend_block_source)); \
                __t->next = tob->sources; \
                tob->sources = __t; \
                __t->from = fromb; \
        } \
 }
 
-#define DEL_SOURCE(cs) { \
-       zend_block_source *__ns = (*cs)->next; \
-       efree(*cs); \
-       *cs = __ns; \
-}
+#define DEL_SOURCE(cs) do { \
+               *(cs) = (*(cs))->next; \
+       } while (0)
 
 
 static inline void replace_source(zend_block_source *list, zend_code_block *old, zend_code_block *new)
@@ -400,7 +397,7 @@ static inline void del_source(zend_code_block *from, zend_code_block *to)
                        /* move 'to'`s references to 'from' */
                        to->start_opline = NULL;
                        to->access = 0;
-                       efree(to->sources);
+//???A                 efree(to->sources);
                        to->sources = NULL;
                        from_block->follow_to = to->follow_to;
                        if (to->op1_to) {
@@ -423,7 +420,7 @@ static inline void del_source(zend_code_block *from, zend_code_block *to)
        }
 }
 
-static void delete_code_block(zend_code_block *block)
+static void delete_code_block(zend_code_block *block, zend_optimizer_ctx *ctx)
 {
        if (block->protected) {
                return;
@@ -455,7 +452,7 @@ static void delete_code_block(zend_code_block *block)
        block->access = 0;
 }
 
-static void zend_access_path(zend_code_block *block)
+static void zend_access_path(zend_code_block *block, zend_optimizer_ctx *ctx)
 {
        if (block->access) {
                return;
@@ -463,25 +460,25 @@ static void zend_access_path(zend_code_block *block)
 
        block->access = 1;
        if (block->op1_to) {
-               zend_access_path(block->op1_to);
+               zend_access_path(block->op1_to, ctx);
                ADD_SOURCE(block, block->op1_to);
        }
        if (block->op2_to) {
-               zend_access_path(block->op2_to);
+               zend_access_path(block->op2_to, ctx);
                ADD_SOURCE(block, block->op2_to);
        }
        if (block->ext_to) {
-               zend_access_path(block->ext_to);
+               zend_access_path(block->ext_to, ctx);
                ADD_SOURCE(block, block->ext_to);
        }
        if (block->follow_to) {
-               zend_access_path(block->follow_to);
+               zend_access_path(block->follow_to, ctx);
                ADD_SOURCE(block, block->follow_to);
        }
 }
 
 /* Traverse CFG, mark reachable basic blocks and build back references */
-static void zend_rebuild_access_path(zend_cfg *cfg, zend_op_array *op_array, int find_start)
+static void zend_rebuild_access_path(zend_cfg *cfg, zend_op_array *op_array, int find_start, zend_optimizer_ctx *ctx)
 {
        zend_code_block *blocks = cfg->blocks;
        zend_code_block *start = find_start? NULL : blocks;
@@ -495,26 +492,26 @@ static void zend_rebuild_access_path(zend_cfg *cfg, zend_op_array *op_array, int
                        start = b;
                }
                b->access = 0;
-               cs = b->sources;
-               while (cs) {
-                       zend_block_source *n = cs->next;
-                       efree(cs);
-                       cs = n;
-               }
+//???A         cs = b->sources;
+//???A         while (cs) {
+//???A                 zend_block_source *n = cs->next;
+//???A                 efree(cs);
+//???A                 cs = n;
+//???A         }
                b->sources = NULL;
                b = b->next;
        }
 
        /* Walk thorough all paths */
-       zend_access_path(start);
+       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]);
-                       zend_access_path(cfg->loop_cont[i]);
-                       zend_access_path(cfg->loop_brk[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);
                }
        }
 
@@ -523,7 +520,7 @@ static void zend_rebuild_access_path(zend_cfg *cfg, zend_op_array *op_array, int
                int i;
                for (i=0; i< op_array->last_try_catch; i++) {
                        if (!cfg->catch[i]->access) {
-                               zend_access_path(cfg->catch[i]);
+                               zend_access_path(cfg->catch[i], ctx);
                        }
                }
        }
@@ -558,7 +555,7 @@ static void zend_rebuild_access_path(zend_cfg *cfg, zend_op_array *op_array, int
                convert_to_string((v)); \
        }
 
-static void strip_nop(zend_code_block *block)
+static void strip_nop(zend_code_block *block, zend_optimizer_ctx *ctx)
 {
        zend_op *opline = block->start_opline;
        zend_op *end, *new_end;
@@ -568,7 +565,7 @@ static void strip_nop(zend_code_block *block)
                if (block->len == 1) {
                        /* this block is all NOPs, join with following block */
                        if (block->follow_to) {
-                               delete_code_block(block);
+                               delete_code_block(block, ctx);
                        }
                        return;
                }
@@ -603,11 +600,11 @@ static void strip_nop(zend_code_block *block)
        block->len = new_end - block->start_opline;
 }
 
-static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, char *used_ext TSRMLS_DC)
+static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, char *used_ext, zend_cfg *cfg, zend_optimizer_ctx *ctx TSRMLS_DC)
 {
        zend_op *opline = block->start_opline;
        zend_op *end, *last_op = NULL;
-       zend_op **Tsource = NULL;
+       zend_op **Tsource = cfg->Tsource;
 
        print_block(block, op_array->opcodes, "Opt ");
 
@@ -616,7 +613,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
                if (block->len == 1) {
                        /* this block is all NOPs, join with following block */
                        if (block->follow_to) {
-                               delete_code_block(block);
+                               delete_code_block(block, ctx);
                        }
                        return;
                }
@@ -626,9 +623,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
        }
 
        /* we track data dependencies only insight a single basic block */
-       if (op_array->T) {
-               Tsource = ecalloc(op_array->last_var + op_array->T, sizeof(zend_op *));
-       }
+       memset(Tsource, 0, (op_array->last_var + op_array->T) * sizeof(zend_op *));
        opline = block->start_opline;
        end = opline + block->len;
        while ((op_array->T) && (opline < end)) {
@@ -1198,11 +1193,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
                opline++;
        }
 
-       strip_nop(block);
-
-       if (op_array->T) {
-               efree(Tsource);
-       }
+       strip_nop(block, ctx);
 }
 
 /* Rebuild plain (optimized) op_array from CFG */
@@ -1277,8 +1268,6 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array)
                        }
                }
                op_array->last_try_catch = j;
-               efree(cfg->try);
-               efree(cfg->catch);
        }
 
        /* adjust loop jump targets */
@@ -1289,9 +1278,6 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array)
                        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;
                }
-               efree(cfg->loop_start);
-               efree(cfg->loop_cont);
-               efree(cfg->loop_brk);
        }
 
     /* adjust jump targets */
@@ -1337,7 +1323,7 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array)
 #endif
 }
 
-static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_array, zend_code_block *blocks TSRMLS_DC)
+static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_array, zend_code_block *blocks, zend_cfg *cfg, zend_optimizer_ctx *ctx TSRMLS_DC)
 {
        /* last_op is the last opcode of the current block */
        zend_op *last_op = (block->start_opline + block->len - 1);
@@ -1364,7 +1350,7 @@ static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_arra
                                        block->len--;
                                        if (block->len == 0) {
                                                /* this block is nothing but NOP now */
-                                               delete_code_block(block);
+                                               delete_code_block(block, ctx);
                                        }
                                        break;
                                }
@@ -1473,7 +1459,7 @@ static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_arra
                                                        block->len--;
                                                        if(block->len == 0) {
                                                                /* this block is nothing but NOP now */
-                                                               delete_code_block(block);
+                                                               delete_code_block(block, ctx);
                                                        }
                                                        break;
                                                }
@@ -1665,10 +1651,8 @@ next_target:
                                if (var_num <= 0) {
                                        return;
                                }
-                               same_t = ecalloc(var_num, sizeof(char));
-                               if (same_t == NULL) {
-                                       return;
-                               }
+                               same_t = cfg->same_t;
+                               memset(same_t, 0, var_num);
                                same_t[VAR_NUM_EX(last_op->op1)] |= ZEND_OP1_TYPE(last_op);
                                same_t[VAR_NUM_EX(last_op->result)] |= ZEND_RESULT_TYPE(last_op);
                                target_block = block->op2_to;
@@ -1742,9 +1726,6 @@ next_target_ex:
                                        }
                                        ADD_SOURCE(block, block->op2_to);
                                }
-                               if (same_t != NULL) {
-                                       efree(same_t);
-                               }
                        }
                        break;
 
@@ -1895,19 +1876,22 @@ next_target_znz:
 
 /* Find a set of variables which are used outside of the block where they are
  * defined. We won't apply some optimization patterns for such variables. */
-static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char *used_ext)
+static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char *used_ext, zend_optimizer_ctx *ctx)
 {
        zend_code_block *next_block = block->next;
        char *usage;
        char *defined_here;
+       void *checkpoint;
 
        if (op_array->T == 0) {
                /* shortcut - if no Ts, nothing to do */
                return;
        }
 
-       usage = ecalloc(op_array->last_var + op_array->T, 1);
-       defined_here = emalloc(op_array->last_var + op_array->T);
+       checkpoint = zend_arena_checkpoint(ctx->arena);
+       usage = zend_arena_alloc(&ctx->arena, op_array->last_var + op_array->T);
+       memset(usage, 0, op_array->last_var + op_array->T);
+       defined_here = zend_arena_alloc(&ctx->arena, op_array->last_var + op_array->T);
 
        while (next_block) {
                zend_op *opline = next_block->start_opline;
@@ -2053,18 +2037,18 @@ static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, char *
                block = block->next;
        } /* end blocks */
 
-       efree(defined_here);
-       efree(usage);
+       zend_arena_release(&ctx->arena, checkpoint);
 }
 
 #define PASSES 3
 
-static void zend_block_optimization(zend_op_array *op_array TSRMLS_DC)
+static void zend_block_optimization(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRMLS_DC)
 {
        zend_cfg cfg;
        zend_code_block *cur_block;
        int pass;
        char *usage;
+       void *checkpoint;
 
 #if DEBUG_BLOCKPASS
        fprintf(stderr, "File %s func %s\n", op_array->filename, op_array->function_name? op_array->function_name : "main");
@@ -2078,24 +2062,34 @@ static void zend_block_optimization(zend_op_array *op_array TSRMLS_DC)
 #endif
 
     /* Build CFG */
-       if (!find_code_blocks(op_array, &cfg)) {
+       checkpoint = zend_arena_checkpoint(ctx->arena);
+       if (!find_code_blocks(op_array, &cfg, ctx)) {
+               zend_arena_release(&ctx->arena, checkpoint);
                return;
        }
 
-       zend_rebuild_access_path(&cfg, op_array, 0);
+       zend_rebuild_access_path(&cfg, op_array, 0, ctx);
        /* full rebuild here to produce correct sources! */
-       usage = emalloc(op_array->last_var + op_array->T);
+       if (op_array->last_var || op_array->T) {
+               cfg.Tsource = zend_arena_calloc(&ctx->arena, op_array->last_var + op_array->T, sizeof(zend_op *));
+               cfg.same_t = zend_arena_alloc(&ctx->arena, op_array->last_var + op_array->T);
+               usage = zend_arena_alloc(&ctx->arena, op_array->last_var + op_array->T);
+       } else {
+               cfg.Tsource = NULL;
+               cfg.same_t = NULL;
+               usage = NULL;
+       }
        for (pass = 0; pass < PASSES; pass++) {
                /* Compute data dependencies */
                memset(usage, 0, op_array->last_var + op_array->T);
-               zend_t_usage(cfg.blocks, op_array, usage);
+               zend_t_usage(cfg.blocks, op_array, usage, ctx);
 
                /* optimize each basic block separately */
                for (cur_block = cfg.blocks; cur_block; cur_block = cur_block->next) {
                        if (!cur_block->access) {
                                continue;
                        }
-                       zend_optimize_block(cur_block, op_array, usage TSRMLS_CC);
+                       zend_optimize_block(cur_block, op_array, usage, &cfg, ctx TSRMLS_CC);
                }
 
                /* Jump optimization for each block */
@@ -2103,19 +2097,19 @@ static void zend_block_optimization(zend_op_array *op_array TSRMLS_DC)
                        if (!cur_block->access) {
                                continue;
                        }
-                       zend_jmp_optimization(cur_block, op_array, cfg.blocks TSRMLS_CC);
+                       zend_jmp_optimization(cur_block, op_array, cfg.blocks, &cfg, ctx TSRMLS_CC);
                }
 
                /* Eliminate unreachable basic blocks */
-               zend_rebuild_access_path(&cfg, op_array, 1);
+               zend_rebuild_access_path(&cfg, op_array, 1, ctx);
        }
 
        memset(usage, 0, op_array->last_var + op_array->T);
-       zend_t_usage(cfg.blocks, op_array, usage);
+       zend_t_usage(cfg.blocks, op_array, usage, ctx);
        assemble_code_blocks(&cfg, op_array);
-       efree(usage);
 
        /* Destroy CFG */
+/* ???A
        for (cur_block = cfg.blocks; cur_block; cur_block = cur_block->next) {
                zend_block_source *cs = cur_block->sources;
                while (cs) {
@@ -2124,5 +2118,6 @@ static void zend_block_optimization(zend_op_array *op_array TSRMLS_DC)
                        cs = n;
                }
        }
-       efree(cfg.blocks);
+*/
+       zend_arena_release(&ctx->arena, checkpoint);
 }
index aad6243e0a31266efc49244fc3bb111c51b95cec..6300d0fcfd204645fce8c73d5a93c845c2098e44 100644 (file)
@@ -87,7 +87,7 @@ static void optimizer_literal_class_info(literal_info   *info,
        }
 }
 
-static void optimizer_compact_literals(zend_op_array *op_array TSRMLS_DC)
+static void optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRMLS_DC)
 {
        zend_op *opline, *end;
        int i, j, n, *map, cache_slots;
@@ -98,9 +98,10 @@ static void optimizer_compact_literals(zend_op_array *op_array TSRMLS_DC)
        int l_true = -1;
        HashTable hash;
        zend_string *key = NULL;
+       void *checkpoint = zend_arena_checkpoint(ctx->arena);
 
        if (op_array->last_literal) {
-               info = (literal_info*)ecalloc(op_array->last_literal, sizeof(literal_info));
+               info = (literal_info*)zend_arena_calloc(&ctx->arena, op_array->last_literal, sizeof(literal_info));
 
            /* Mark literals of specific types */
                opline = op_array->opcodes;
@@ -282,7 +283,9 @@ static void optimizer_compact_literals(zend_op_array *op_array TSRMLS_DC)
                /* Merge equal constants */
                j = 0; cache_slots = 0;
                zend_hash_init(&hash, 16, NULL, NULL, 0);
-               map = (int*)ecalloc(op_array->last_literal, sizeof(int));
+               map = (int*)zend_arena_alloc(&ctx->arena, op_array->last_literal * sizeof(int));
+//???A
+memset(map, 0, op_array->last_literal * sizeof(int));
                for (i = 0; i < op_array->last_literal; i++) {
                        if (!info[i].flags) {
                                /* unsed literal */
@@ -440,8 +443,7 @@ static void optimizer_compact_literals(zend_op_array *op_array TSRMLS_DC)
                        }
                        opline++;
                }
-               efree(map);
-               efree(info);
+               zend_arena_release(&ctx->arena, checkpoint);
 
 #if DEBUG_COMPACT_LITERALS
                {
index f9ae14290f57557fe5e3524efd06024c659892f6..cd27704de5211e6e26987e5ee5b7b9560b48454d 100644 (file)
@@ -8,16 +8,12 @@ typedef struct _optimizer_call_info {
        zend_op       *opline;
 } optimizer_call_info;
 
-static void optimize_func_calls(zend_op_array *op_array, zend_persistent_script *script TSRMLS_DC) {
+static void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx TSRMLS_DC) {
        zend_op *opline = op_array->opcodes;
        zend_op *end = opline + op_array->last;
        int call = 0;
-#if ZEND_EXTENSION_API_NO > PHP_5_4_X_API_NO
-       optimizer_call_info *call_stack = ecalloc(op_array->nested_calls + 1, sizeof(optimizer_call_info));
-#else
-       int stack_size = 4;
-       optimizer_call_info *call_stack = ecalloc(stack_size, sizeof(optimizer_call_info));
-#endif
+       void *checkpoint = zend_arena_checkpoint(ctx->arena); 
+       optimizer_call_info *call_stack = zend_arena_calloc(&ctx->arena, op_array->nested_calls + 1, sizeof(optimizer_call_info));
 
        while (opline < end) {
                switch (opline->opcode) {
@@ -26,7 +22,7 @@ static void optimize_func_calls(zend_op_array *op_array, zend_persistent_script
                                if (ZEND_OP2_TYPE(opline) == IS_CONST) {
                                        zend_function *func;
                                        zval *function_name = &op_array->literals[opline->op2.constant + 1];
-                                       if ((func = zend_hash_find_ptr(&script->function_table,
+                                       if ((func = zend_hash_find_ptr(&ctx->script->function_table,
                                                        Z_STR_P(function_name))) != NULL) {
                                                call_stack[call].func = func;
                                        }
@@ -37,13 +33,6 @@ static void optimize_func_calls(zend_op_array *op_array, zend_persistent_script
                        case ZEND_INIT_STATIC_METHOD_CALL:
                                call_stack[call].opline = opline;
                                call++;
-#if ZEND_EXTENSION_API_NO < PHP_5_5_X_API_NO
-                               if (call == stack_size) {
-                                       stack_size += 4;
-                                       call_stack = erealloc(call_stack, sizeof(optimizer_call_info) * stack_size);
-                                       memset(call_stack + 4, 0, 4 * sizeof(optimizer_call_info));
-                               }
-#endif
                                break;
                        case ZEND_DO_FCALL_BY_NAME:
                                call--;
@@ -137,6 +126,6 @@ static void optimize_func_calls(zend_op_array *op_array, zend_persistent_script
                opline++;
        }
 
-       efree(call_stack);
+       zend_arena_release(&ctx->arena, checkpoint);
 }
 #endif
index 77e07a586e96ef5d3b3528abfb92dbdd3218f8fc..af193802ddae5ff06e473b0e24d45fc103cf7b96 100644 (file)
@@ -70,7 +70,7 @@ static const char op_const_means_class[256]  = {
                max = i;                                \
        }
 
-static void optimize_temporary_variables(zend_op_array *op_array)
+static void optimize_temporary_variables(zend_op_array *op_array, zend_optimizer_ctx *ctx)
 {
        int T = op_array->T;
        int offset = op_array->last_var;
@@ -83,11 +83,12 @@ static void optimize_temporary_variables(zend_op_array *op_array)
        int i;
        int max = -1;
        int var_to_free = -1;
+       void *checkpoint = zend_arena_checkpoint(ctx->arena);
 
-       taken_T = (char *) emalloc(T);
-       start_of_T = (zend_op **) emalloc(T * sizeof(zend_op *));
-       valid_T = (char *) emalloc(T);
-       map_T = (int *) emalloc(T * sizeof(int));
+       taken_T = (char *) zend_arena_alloc(&ctx->arena, T);
+       start_of_T = (zend_op **) zend_arena_alloc(&ctx->arena, T * sizeof(zend_op *));
+       valid_T = (char *) zend_arena_alloc(&ctx->arena, T);
+       map_T = (int *) zend_arena_alloc(&ctx->arena, T * sizeof(int));
 
     end = op_array->opcodes;
     opline = &op_array->opcodes[op_array->last - 1];
@@ -238,9 +239,6 @@ static void optimize_temporary_variables(zend_op_array *op_array)
                opline--;
        }
 
-       efree(taken_T);
-       efree(start_of_T);
-       efree(valid_T);
-       efree(map_T);
+       zend_arena_release(&ctx->arena, checkpoint);
        op_array->T = max + 1;
 }
index ab41fa92f75bc7722050f3ee88b039038d057a6f..73fa0d02f9fc25146a29559effe9130077213826 100644 (file)
@@ -16,7 +16,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
        int i = 0;
        zend_op *opline = op_array->opcodes;
        zend_op *end = opline + op_array->last;
-       zend_bool collect_constants = (op_array == &script->main_op_array);
+       zend_bool collect_constants = (op_array == &ctx->script->main_op_array);
 
        while (opline < end) {
                switch (opline->opcode) {
@@ -245,7 +245,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
                                zval c;
 
                                if (!zend_get_persistent_constant(Z_STR(ZEND_OP2_LITERAL(opline)), &c, 1 TSRMLS_CC)) {
-                                       if (!*constants || !zend_optimizer_get_collected_constant(*constants, &ZEND_OP2_LITERAL(opline), &c)) {
+                                       if (!ctx->constants || !zend_optimizer_get_collected_constant(ctx->constants, &ZEND_OP2_LITERAL(opline), &c)) {
                                                break;
                                        }
                                }
@@ -334,7 +334,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
                            (opline-2)->opcode == ZEND_SEND_VAL &&
                            ZEND_OP1_TYPE(opline-2) == IS_CONST &&
                            Z_TYPE(ZEND_OP1_LITERAL(opline-2)) == IS_STRING) {
-                               zend_optimizer_collect_constant(constants, &ZEND_OP1_LITERAL(opline-2), &ZEND_OP1_LITERAL(opline-1));
+                               zend_optimizer_collect_constant(ctx, &ZEND_OP1_LITERAL(opline-2), &ZEND_OP1_LITERAL(opline-1));
                                break;
                        } else {
                                /* don't colllect constants after any other function call */
@@ -452,7 +452,7 @@ if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
                        if (collect_constants &&
                            Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING &&
                            Z_TYPE(ZEND_OP2_LITERAL(opline)) <= IS_STRING) {
-                               zend_optimizer_collect_constant(constants, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline));
+                               zend_optimizer_collect_constant(ctx, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline));
                        }
                        break;
 #endif
index b0d651a5fcf8e5bff5c35ec17b893fdac7be0825..ba36da5990aed173ad733d2d86ad771117617e8e 100644 (file)
@@ -1,3 +1,3 @@
 if (ZEND_OPTIMIZER_PASS_5 & OPTIMIZATION_LEVEL) {
-       zend_block_optimization(op_array TSRMLS_CC);
+       zend_block_optimization(op_array, ctx TSRMLS_CC);
 }
index 586160c14d10d30911f68203837515b8b5c12b8f..ec54dc6c1dc859f44b0f50b13fb77ec4fd8bd5f5 100644 (file)
@@ -4,5 +4,5 @@
  */
 
 if (ZEND_OPTIMIZER_PASS_9 & OPTIMIZATION_LEVEL) {
-       optimize_temporary_variables(op_array);
+       optimize_temporary_variables(op_array, ctx);
 }
index 029f0846dd5d018fecf7f3f6f2d7248f507e2d86..2ea6544e23ab1b839a670a7382711709bbd1ea8f 100644 (file)
@@ -35,16 +35,16 @@ static void zend_optimizer_zval_dtor_wrapper(zval *zvalue)
        zval_dtor(zvalue);
 }
 
-static void zend_optimizer_collect_constant(HashTable **constants, zval *name, zval* value)
+static void zend_optimizer_collect_constant(zend_optimizer_ctx *ctx, zval *name, zval* value)
 {
        zval val;
 
-       if (!*constants) {
-               *constants = emalloc(sizeof(HashTable));
-               zend_hash_init(*constants, 16, NULL, zend_optimizer_zval_dtor_wrapper, 0);
+       if (!ctx->constants) {
+               ctx->constants = zend_arena_alloc(&ctx->arena, sizeof(HashTable));
+               zend_hash_init(ctx->constants, 16, NULL, zend_optimizer_zval_dtor_wrapper, 0);
        }
        ZVAL_DUP(&val, value);
-       zend_hash_add(*constants, Z_STR_P(name), &val);
+       zend_hash_add(ctx->constants, Z_STR_P(name), &val);
 }
 
 static int zend_optimizer_get_collected_constant(HashTable *constants, zval *name, zval* value)
@@ -425,9 +425,8 @@ static void replace_tmp_by_const(zend_op_array *op_array,
 #include "Optimizer/compact_literals.c"
 #include "Optimizer/optimize_func_calls.c"
 
-static void zend_optimize(zend_op_array           *op_array,
-                          zend_persistent_script  *script,
-                          HashTable              **constants TSRMLS_DC)
+static void zend_optimize(zend_op_array      *op_array,
+                          zend_optimizer_ctx *ctx TSRMLS_DC)
 {
        if (op_array->type == ZEND_EVAL_CODE ||
            (op_array->fn_flags & ZEND_ACC_INTERACTIVE)) {
@@ -462,7 +461,7 @@ static void zend_optimize(zend_op_array           *op_array,
         * - INIT_FCALL_BY_NAME -> DO_FCALL
         */
        if (ZEND_OPTIMIZER_PASS_4 & OPTIMIZATION_LEVEL) {
-               optimize_func_calls(op_array, script TSRMLS_CC);
+               optimize_func_calls(op_array, ctx TSRMLS_CC);
        }
 #endif
 
@@ -486,14 +485,13 @@ static void zend_optimize(zend_op_array           *op_array,
         * - Compact literals table 
         */
        if (ZEND_OPTIMIZER_PASS_11 & OPTIMIZATION_LEVEL) {
-               optimizer_compact_literals(op_array TSRMLS_CC);
+               optimizer_compact_literals(op_array, ctx TSRMLS_CC);
        }
 #endif
 }
 
-static void zend_accel_optimize(zend_op_array           *op_array,
-                                zend_persistent_script  *script,
-                                HashTable              **constants TSRMLS_DC)
+static void zend_accel_optimize(zend_op_array      *op_array,
+                                zend_optimizer_ctx *ctx TSRMLS_DC)
 {
        zend_op *opline, *end;
 
@@ -543,7 +541,7 @@ static void zend_accel_optimize(zend_op_array           *op_array,
        }
 
        /* Do actual optimizations */
-       zend_optimize(op_array, script, constants TSRMLS_CC);   
+       zend_optimize(op_array, ctx TSRMLS_CC); 
        
        /* Redo pass_two() */
        opline = op_array->opcodes;
@@ -596,17 +594,21 @@ int zend_accel_script_optimize(zend_persistent_script *script TSRMLS_DC)
 {
        uint idx, j;
        Bucket *p, *q;
-       HashTable *constants = NULL;
        zend_class_entry *ce;
        zend_op_array *op_array;
+       zend_optimizer_ctx ctx;
 
-       zend_accel_optimize(&script->main_op_array, script, &constants TSRMLS_CC);
+       ctx.arena = zend_arena_create(64 * 1024);
+       ctx.script = script;
+       ctx.constants = NULL;
+
+       zend_accel_optimize(&script->main_op_array, &ctx TSRMLS_CC);
 
        for (idx = 0; idx < script->function_table.nNumUsed; idx++) {
                p = script->function_table.arData + idx;
                if (Z_TYPE(p->val) == IS_UNDEF) continue;
                op_array = (zend_op_array*)Z_PTR(p->val);
-               zend_accel_optimize(op_array, script, &constants TSRMLS_CC);
+               zend_accel_optimize(op_array, &ctx TSRMLS_CC);
        }
 
        for (idx = 0; idx < script->class_table.nNumUsed; idx++) {
@@ -618,7 +620,7 @@ int zend_accel_script_optimize(zend_persistent_script *script TSRMLS_DC)
                        if (Z_TYPE(q->val) == IS_UNDEF) continue;
                        op_array = (zend_op_array*)Z_PTR(q->val);
                        if (op_array->scope == ce) {
-                               zend_accel_optimize(op_array, script, &constants TSRMLS_CC);
+                               zend_accel_optimize(op_array, &ctx TSRMLS_CC);
                        } else if (op_array->type == ZEND_USER_FUNCTION) {
                                zend_op_array *orig_op_array;
                                if ((orig_op_array = zend_hash_find_ptr(&op_array->scope->function_table, q->key)) != NULL) {
@@ -630,10 +632,10 @@ int zend_accel_script_optimize(zend_persistent_script *script TSRMLS_DC)
                }
        }
 
-       if (constants) {
-               zend_hash_destroy(constants);
-               efree(constants);
+       if (ctx.constants) {
+               zend_hash_destroy(ctx.constants);
        }
+       zend_arena_destroy(ctx.arena);
 
        return 1;
 }
index 049036c1f42c9276958f960f7bd10f62ad3a2199..0ae3feb2eefee2bb9a5568cb5503fc01c8509cce 100644 (file)
 # define SAME_VAR(op1, op2)    (((op1.op_type == IS_VAR && op2.op_type == IS_VAR) || (op1.op_type == IS_TMP_VAR && op2.op_type == IS_TMP_VAR)) && op1.u.var == op2.u.var)
 #endif
 
+typedef struct _zend_optimizer_ctx {
+       zend_arena             *arena;
+       zend_persistent_script *script;
+       HashTable              *constants;
+} zend_optimizer_ctx;
+
 typedef struct _zend_code_block zend_code_block;
 typedef struct _zend_block_source zend_block_source;
 
@@ -79,6 +85,8 @@ typedef struct _zend_cfg {
        zend_code_block   **loop_start;
        zend_code_block   **loop_cont;
        zend_code_block   **loop_brk;
+       zend_op           **Tsource;
+       char               *same_t;
 } zend_cfg;
 
 struct _zend_block_source {