summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
Diffstat (limited to 'ext')
-rw-r--r--ext/opcache/Optimizer/block_pass.c149
-rw-r--r--ext/opcache/Optimizer/compact_literals.c12
-rw-r--r--ext/opcache/Optimizer/optimize_func_calls.c21
-rw-r--r--ext/opcache/Optimizer/optimize_temp_vars_5.c16
-rw-r--r--ext/opcache/Optimizer/pass1_5.c8
-rw-r--r--ext/opcache/Optimizer/pass5.c2
-rw-r--r--ext/opcache/Optimizer/pass9.c2
-rw-r--r--ext/opcache/Optimizer/zend_optimizer.c44
-rw-r--r--ext/opcache/Optimizer/zend_optimizer_internal.h8
9 files changed, 128 insertions, 134 deletions
diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c
index 20b7a1ae31..7df2764d93 100644
--- a/ext/opcache/Optimizer/block_pass.c
+++ b/ext/opcache/Optimizer/block_pass.c
@@ -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);
}
diff --git a/ext/opcache/Optimizer/compact_literals.c b/ext/opcache/Optimizer/compact_literals.c
index aad6243e0a..6300d0fcfd 100644
--- a/ext/opcache/Optimizer/compact_literals.c
+++ b/ext/opcache/Optimizer/compact_literals.c
@@ -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
{
diff --git a/ext/opcache/Optimizer/optimize_func_calls.c b/ext/opcache/Optimizer/optimize_func_calls.c
index f9ae14290f..cd27704de5 100644
--- a/ext/opcache/Optimizer/optimize_func_calls.c
+++ b/ext/opcache/Optimizer/optimize_func_calls.c
@@ -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
diff --git a/ext/opcache/Optimizer/optimize_temp_vars_5.c b/ext/opcache/Optimizer/optimize_temp_vars_5.c
index 77e07a586e..af193802dd 100644
--- a/ext/opcache/Optimizer/optimize_temp_vars_5.c
+++ b/ext/opcache/Optimizer/optimize_temp_vars_5.c
@@ -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;
}
diff --git a/ext/opcache/Optimizer/pass1_5.c b/ext/opcache/Optimizer/pass1_5.c
index ab41fa92f7..73fa0d02f9 100644
--- a/ext/opcache/Optimizer/pass1_5.c
+++ b/ext/opcache/Optimizer/pass1_5.c
@@ -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
diff --git a/ext/opcache/Optimizer/pass5.c b/ext/opcache/Optimizer/pass5.c
index b0d651a5fc..ba36da5990 100644
--- a/ext/opcache/Optimizer/pass5.c
+++ b/ext/opcache/Optimizer/pass5.c
@@ -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);
}
diff --git a/ext/opcache/Optimizer/pass9.c b/ext/opcache/Optimizer/pass9.c
index 586160c14d..ec54dc6c1d 100644
--- a/ext/opcache/Optimizer/pass9.c
+++ b/ext/opcache/Optimizer/pass9.c
@@ -4,5 +4,5 @@
*/
if (ZEND_OPTIMIZER_PASS_9 & OPTIMIZATION_LEVEL) {
- optimize_temporary_variables(op_array);
+ optimize_temporary_variables(op_array, ctx);
}
diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c
index 029f0846dd..2ea6544e23 100644
--- a/ext/opcache/Optimizer/zend_optimizer.c
+++ b/ext/opcache/Optimizer/zend_optimizer.c
@@ -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;
}
diff --git a/ext/opcache/Optimizer/zend_optimizer_internal.h b/ext/opcache/Optimizer/zend_optimizer_internal.h
index 049036c1f4..0ae3feb2ee 100644
--- a/ext/opcache/Optimizer/zend_optimizer_internal.h
+++ b/ext/opcache/Optimizer/zend_optimizer_internal.h
@@ -55,6 +55,12 @@
# 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 {