int index = 0, *dfs, *root;
zend_worklist_stack stack;
int j;
+ ALLOCA_FLAG(dfs_use_heap);
+ ALLOCA_FLAG(root_use_heap);
+ ALLOCA_FLAG(stack_use_heap);
- dfs = alloca(sizeof(int) * ssa->vars_count);
+ dfs = do_alloca(sizeof(int) * ssa->vars_count, dfs_use_heap);
memset(dfs, -1, sizeof(int) * ssa->vars_count);
- root = alloca(sizeof(int) * ssa->vars_count);
- ZEND_WORKLIST_STACK_ALLOCA(&stack, ssa->vars_count);
+ root = do_alloca(sizeof(int) * ssa->vars_count, root_use_heap);
+ ZEND_WORKLIST_STACK_ALLOCA(&stack, ssa->vars_count, stack_use_heap);
/* Find SCCs */
for (j = 0; j < ssa->vars_count; j++) {
}
}
+ ZEND_WORKLIST_STACK_FREE_ALLOCA(&stack, stack_use_heap);
+ free_alloca(root, root_use_heap);
+ free_alloca(dfs, dfs_use_heap);
+
return SUCCESS;
}
/* }}} */
zend_bitset worklist;
int i, j, use;
zend_ssa_phi *p;
+ ALLOCA_FLAG(use_heap);
- if (!op_array->function_name || !ssa->vars || !ssa->ops)
+ if (!op_array->function_name || !ssa->vars || !ssa->ops) {
return SUCCESS;
+ }
- worklist = alloca(sizeof(zend_ulong) * zend_bitset_len(ssa_vars_count));
+ worklist = do_alloca(sizeof(zend_ulong) * zend_bitset_len(ssa_vars_count), use_heap);
memset(worklist, 0, sizeof(zend_ulong) * zend_bitset_len(ssa_vars_count));
for (i = 0; i < ssa_vars_count; i++) {
}
}
+ free_alloca(worklist, use_heap);
+
return SUCCESS;
}
/* }}} */
static void zend_infer_ranges_warmup(const zend_op_array *op_array, zend_ssa *ssa, int *scc_var, int *next_scc_var, int scc)
{
int worklist_len = zend_bitset_len(ssa->vars_count);
- zend_bitset worklist = alloca(sizeof(zend_ulong) * worklist_len);
- zend_bitset visited = alloca(sizeof(zend_ulong) * worklist_len);
+ zend_bitset worklist;
+ zend_bitset visited;
int j, n;
zend_ssa_range tmp;
#ifdef NEG_RANGE
int has_inner_cycles = 0;
+ ALLOCA_FLAG(use_heap);
+ worklist = do_alloca(sizeof(zend_ulong) * worklist_len * 2, use_heap);
+ visited = worklist + worklist_len;
memset(worklist, 0, sizeof(zend_ulong) * worklist_len);
memset(visited, 0, sizeof(zend_ulong) * worklist_len);
j= scc_var[scc];
}
}
}
+ free_alloca(worklist, use_heap);
}
static int zend_infer_ranges(const zend_op_array *op_array, zend_ssa *ssa) /* {{{ */
{
int worklist_len = zend_bitset_len(ssa->vars_count);
- zend_bitset worklist = alloca(sizeof(zend_ulong) * worklist_len);
- int *next_scc_var = alloca(sizeof(int) * ssa->vars_count);
- int *scc_var = alloca(sizeof(int) * ssa->sccs);
+ zend_bitset worklist;
+ int *next_scc_var;
+ int *scc_var;
zend_ssa_phi *p;
zend_ssa_range tmp;
int scc, j;
+ ALLOCA_FLAG(use_heap);
+
+ worklist = do_alloca(
+ sizeof(zend_ulong) * worklist_len +
+ sizeof(int) * ssa->vars_count +
+ sizeof(int) * ssa->sccs, use_heap);
+ next_scc_var = (int*)(worklist + worklist_len);
+ scc_var = next_scc_var + ssa->vars_count;
#ifdef LOG_SSA_RANGE
fprintf(stderr, "Range Inference\n");
}
}
+ free_alloca(worklist, use_heap);
+
return SUCCESS;
}
/* }}} */
int ssa_vars_count = ssa->vars_count;
int j;
zend_bitset worklist, types;
+ ALLOCA_FLAG(use_heap);
- types = alloca(sizeof(zend_ulong) * op_array->last_var);
+ types = do_alloca(sizeof(zend_ulong) * (op_array->last_var + zend_bitset_len(ssa_vars_count)), use_heap);
memset(types, 0, sizeof(zend_ulong) * op_array->last_var);
- worklist = alloca(sizeof(zend_ulong) * zend_bitset_len(ssa_vars_count));
+ worklist = types + op_array->last_var;
memset(worklist, 0, sizeof(zend_ulong) * zend_bitset_len(ssa_vars_count));
/* Find variables that may be only LONG or DOUBLE */
}
}
if (zend_bitset_empty(worklist, zend_bitset_len(ssa_vars_count))) {
+ free_alloca(types, use_heap);
return SUCCESS;
}
}
}
if (zend_bitset_empty(worklist, zend_bitset_len(ssa_vars_count))) {
+ free_alloca(types, use_heap);
return SUCCESS;
}
}
}
if (zend_bitset_empty(worklist, zend_bitset_len(ssa_vars_count))) {
+ free_alloca(types, use_heap);
return SUCCESS;
}
}
if (zend_infer_types_ex(op_array, script, ssa, worklist) != SUCCESS) {
+ free_alloca(types, use_heap);
return FAILURE;
}
+ free_alloca(types, use_heap);
return SUCCESS;
}
int ssa_vars_count = ssa->vars_count;
int j;
zend_bitset worklist;
+ ALLOCA_FLAG(use_heap);
- worklist = alloca(sizeof(zend_ulong) * zend_bitset_len(ssa_vars_count));
+ worklist = do_alloca(sizeof(zend_ulong) * zend_bitset_len(ssa_vars_count), use_heap);
memset(worklist, 0, sizeof(zend_ulong) * zend_bitset_len(ssa_vars_count));
/* Type Inference */
}
if (zend_infer_types_ex(op_array, script, ssa, worklist) != SUCCESS) {
+ free_alloca(worklist, use_heap);
return FAILURE;
}
zend_func_return_info(op_array, 1, 0, &ZEND_FUNC_INFO(op_array)->return_info);
}
+ free_alloca(worklist, use_heap);
return SUCCESS;
}
zend_call_info *call_info;
zend_bitset worklist;
int worklist_len;
+ ALLOCA_FLAG(use_heap);
if (!info->ssa.var_info || !(info->flags & ZEND_FUNC_RECURSIVE)) {
return;
}
worklist_len = zend_bitset_len(info->ssa.vars_count);
- worklist = alloca(sizeof(zend_ulong) * worklist_len);
+ worklist = do_alloca(sizeof(zend_ulong) * worklist_len, use_heap);
memset(worklist, 0, sizeof(zend_ulong) * worklist_len);
call_info = info->callee_info;
while (call_info) {
add_usages(op_array, &info->ssa, worklist, i);
}
}
+ free_alloca(worklist, use_heap);
}
/*
uint32_t k;
zend_op *opline;
int *tmp = NULL;
+ ALLOCA_FLAG(use_heap);
// FIXME: Can we optimize this copying out in some cases?
if (blocks[n].next_child >= 0) {
- tmp = alloca(sizeof(int) * (op_array->last_var + op_array->T));
+ tmp = do_alloca(sizeof(int) * (op_array->last_var + op_array->T), use_heap);
memcpy(tmp, var, sizeof(int) * (op_array->last_var + op_array->T));
var = tmp;
}
j = blocks[j].next_child;
}
+ if (tmp) {
+ free_alloca(tmp, use_heap);
+ }
+
return SUCCESS;
}
/* }}} */
int *var = NULL;
int i, j, k, changed;
zend_dfg dfg;
+ ALLOCA_FLAG(dfg_use_heap);
+ ALLOCA_FLAG(var_use_heap);
ssa->rt_constants = (build_flags & ZEND_RT_CONSTANTS);
ssa_blocks = zend_arena_calloc(arena, blocks_count, sizeof(zend_ssa_block));
/* Compute Variable Liveness */
dfg.vars = op_array->last_var + op_array->T;
dfg.size = set_size = zend_bitset_len(dfg.vars);
- dfg.tmp = alloca((set_size * sizeof(zend_ulong)) * (blocks_count * 5 + 1));
+ dfg.tmp = do_alloca((set_size * sizeof(zend_ulong)) * (blocks_count * 5 + 1), dfg_use_heap);
memset(dfg.tmp, 0, (set_size * sizeof(zend_ulong)) * (blocks_count * 5 + 1));
dfg.gen = dfg.tmp + set_size;
dfg.def = dfg.gen + set_size * blocks_count;
dfg.out = dfg.in + set_size * blocks_count;
if (zend_build_dfg(op_array, &ssa->cfg, &dfg) != SUCCESS) {
+ free_alloca(dfg.tmp, dfg_use_heap);
return FAILURE;
}
} while (changed);
/* SSA construction, Step 2: Phi placement based on Dominance Frontiers */
- var = alloca(sizeof(int) * (op_array->last_var + op_array->T));
+ var = do_alloca(sizeof(int) * (op_array->last_var + op_array->T), var_use_heap);
if (!var) {
+ free_alloca(dfg.tmp, dfg_use_heap);
return FAILURE;
}
zend_bitset_clear(tmp, set_size);
sizeof(int) * blocks[j].predecessors_count +
sizeof(void*) * blocks[j].predecessors_count);
- if (!phi)
- return FAILURE;
+ if (!phi) {
+ goto failure;
+ }
phi->sources = (int*)(((char*)phi) + sizeof(zend_ssa_phi));
memset(phi->sources, 0xff, sizeof(int) * blocks[j].predecessors_count);
phi->use_chains = (zend_ssa_phi**)(((char*)phi->sources) + sizeof(int) * ssa->cfg.blocks[j].predecessors_count);
if (var1 >= 0) {
if ((opline-1)->opcode == ZEND_IS_EQUAL) {
if (add_pi(arena, op_array, &dfg, ssa, j, bt, var1, var2, var2, val2, val2, 0, 0, 0) != SUCCESS) {
- return FAILURE;
+ goto failure;
}
if (add_pi(arena, op_array, &dfg, ssa, j, bf, var1, var2, var2, val2, val2, 0, 0, 1) != SUCCESS) {
- return FAILURE;
+ goto failure;
}
} else if ((opline-1)->opcode == ZEND_IS_NOT_EQUAL) {
if (add_pi(arena, op_array, &dfg, ssa, j, bf, var1, var2, var2, val2, val2, 0, 0, 0) != SUCCESS) {
- return FAILURE;
+ goto failure;
}
if (add_pi(arena, op_array, &dfg, ssa, j, bt, var1, var2, var2, val2, val2, 0, 0, 1) != SUCCESS) {
- return FAILURE;
+ goto failure;
}
} else if ((opline-1)->opcode == ZEND_IS_SMALLER) {
if (val2 > LONG_MIN) {
if (add_pi(arena, op_array, &dfg, ssa, j, bt, var1, -1, var2, LONG_MIN, val2-1, 1, 0, 0) != SUCCESS) {
- return FAILURE;
+ goto failure;
}
}
if (add_pi(arena, op_array, &dfg, ssa, j, bf, var1, var2, -1, val2, LONG_MAX, 0, 1, 0) != SUCCESS) {
- return FAILURE;
+ goto failure;
}
} else if ((opline-1)->opcode == ZEND_IS_SMALLER_OR_EQUAL) {
if (add_pi(arena, op_array, &dfg, ssa, j, bt, var1, -1, var2, LONG_MIN, val2, 1, 0, 0) != SUCCESS) {
- return FAILURE;
+ goto failure;
}
if (val2 < LONG_MAX) {
if (add_pi(arena, op_array, &dfg, ssa, j, bf, var1, var2, -1, val2+1, LONG_MAX, 0, 1, 0) != SUCCESS) {
- return FAILURE;
+ goto failure;
}
}
}
if (var2 >= 0) {
if((opline-1)->opcode == ZEND_IS_EQUAL) {
if (add_pi(arena, op_array, &dfg, ssa, j, bt, var2, var1, var1, val1, val1, 0, 0, 0) != SUCCESS) {
- return FAILURE;
+ goto failure;
}
if (add_pi(arena, op_array, &dfg, ssa, j, bf, var2, var1, var1, val1, val1, 0, 0, 1) != SUCCESS) {
- return FAILURE;
+ goto failure;
}
} else if ((opline-1)->opcode == ZEND_IS_NOT_EQUAL) {
if (add_pi(arena, op_array, &dfg, ssa, j, bf, var2, var1, var1, val1, val1, 0, 0, 0) != SUCCESS) {
- return FAILURE;
+ goto failure;
}
if (add_pi(arena, op_array, &dfg, ssa, j, bt, var2, var1, var1, val1, val1, 0, 0, 1) != SUCCESS) {
- return FAILURE;
+ goto failure;
}
} else if ((opline-1)->opcode == ZEND_IS_SMALLER) {
if (val1 < LONG_MAX) {
if (add_pi(arena, op_array, &dfg, ssa, j, bt, var2, var1, -1, val1+1, LONG_MAX, 0, 1, 0) != SUCCESS) {
- return FAILURE;
+ goto failure;
}
}
if (add_pi(arena, op_array, &dfg, ssa, j, bf, var2, -1, var1, LONG_MIN, val1, 1, 0, 0) != SUCCESS) {
- return FAILURE;
+ goto failure;
}
} else if ((opline-1)->opcode == ZEND_IS_SMALLER_OR_EQUAL) {
if (add_pi(arena, op_array, &dfg, ssa, j, bt, var2, var1, -1, val1, LONG_MAX, 0 ,1, 0) != SUCCESS) {
- return FAILURE;
+ goto failure;
}
if (val1 > LONG_MIN) {
- if (add_pi(arena, op_array, &dfg, ssa, j, bf, var2, -1, var1, LONG_MIN, val1-1, 1, 0, 0) != SUCCESS) { return FAILURE;
+ if (add_pi(arena, op_array, &dfg, ssa, j, bf, var2, -1, var1, LONG_MIN, val1-1, 1, 0, 0) != SUCCESS) {
+ goto failure;
}
}
}
if ((opline-1)->opcode == ZEND_POST_DEC) {
if (add_pi(arena, op_array, &dfg, ssa, j, bf, var, -1, -1, -1, -1, 0, 0, 0) != SUCCESS) {
- return FAILURE;
+ goto failure;
}
if (add_pi(arena, op_array, &dfg, ssa, j, bt, var, -1, -1, -1, -1, 0, 0, 1) != SUCCESS) {
- return FAILURE;
+ goto failure;
}
} else if ((opline-1)->opcode == ZEND_POST_INC) {
if (add_pi(arena, op_array, &dfg, ssa, j, bf, var, -1, -1, 1, 1, 0, 0, 0) != SUCCESS) {
- return FAILURE;
+ goto failure;
}
if (add_pi(arena, op_array, &dfg, ssa, j, bt, var, -1, -1, 1, 1, 0, 0, 1) != SUCCESS) {
- return FAILURE;
+ goto failure;
}
}
} else if (opline->op1_type == IS_VAR &&
if ((opline-1)->opcode == ZEND_PRE_DEC) {
if (add_pi(arena, op_array, &dfg, ssa, j, bf, var, -1, -1, 0, 0, 0, 0, 0) != SUCCESS) {
- return FAILURE;
+ goto failure;
}
/* speculative */
if (add_pi(arena, op_array, &dfg, ssa, j, bt, var, -1, -1, 0, 0, 0, 0, 1) != SUCCESS) {
- return FAILURE;
+ goto failure;
}
} else if ((opline-1)->opcode == ZEND_PRE_INC) {
if (add_pi(arena, op_array, &dfg, ssa, j, bf, var, -1, -1, 0, 0, 0, 0, 0) != SUCCESS) {
- return FAILURE;
+ goto failure;
}
/* speculative */
if (add_pi(arena, op_array, &dfg, ssa, j, bt, var, -1, -1, 0, 0, 0, 0, 1) != SUCCESS) {
- return FAILURE;
+ goto failure;
}
}
}
sizeof(int) * blocks[j].predecessors_count +
sizeof(void*) * blocks[j].predecessors_count);
- if (!phi)
- return FAILURE;
+ if (!phi) {
+ goto failure;
+ }
phi->sources = (int*)(((char*)phi) + sizeof(zend_ssa_phi));
memset(phi->sources, 0xff, sizeof(int) * blocks[j].predecessors_count);
phi->use_chains = (zend_ssa_phi**)(((char*)phi->sources) + sizeof(int) * ssa->cfg.blocks[j].predecessors_count);
}
ssa->vars_count = op_array->last_var;
if (zend_ssa_rename(op_array, ssa, var, 0) != SUCCESS) {
+failure:
+ free_alloca(var, var_use_heap);
+ free_alloca(dfg.tmp, dfg_use_heap);
return FAILURE;
}
+ free_alloca(var, var_use_heap);
+ free_alloca(dfg.tmp, dfg_use_heap);
+
return SUCCESS;
}
/* }}} */