diff --git a/ext/opcache/Optimizer/dfa_pass.c b/ext/opcache/Optimizer/dfa_pass.c index c9e3bd90e5910..0a85027e7b82c 100644 --- a/ext/opcache/Optimizer/dfa_pass.c +++ b/ext/opcache/Optimizer/dfa_pass.c @@ -453,7 +453,7 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx zval tmp; if (ZEND_OPTIMIZER_PASS_8 & ctx->optimization_level) { - if (sccp_optimize_op_array(op_array, ssa, call_map)) { + if (sccp_optimize_op_array(ctx, op_array, ssa, call_map)) { remove_nops = 1; } if (ZEND_FUNC_INFO(op_array)) { diff --git a/ext/opcache/Optimizer/sccp.c b/ext/opcache/Optimizer/sccp.c index 11e9b7ce49929..ed75e66900ff8 100644 --- a/ext/opcache/Optimizer/sccp.c +++ b/ext/opcache/Optimizer/sccp.c @@ -1348,57 +1348,57 @@ static int replace_constant_operands(sccp_ctx *ctx) { return removed_ops; } -static void sccp_context_init(sccp_ctx *ctx, +static void sccp_context_init(zend_optimizer_ctx *ctx, sccp_ctx *sccp, zend_ssa *ssa, zend_op_array *op_array, zend_call_info **call_map) { int i; - ctx->call_map = call_map; - ctx->values = emalloc(sizeof(zval) * ssa->vars_count); + sccp->call_map = call_map; + sccp->values = zend_arena_alloc(&ctx->arena, sizeof(zval) * ssa->vars_count); - MAKE_TOP(&ctx->top); - MAKE_BOT(&ctx->bot); + MAKE_TOP(&sccp->top); + MAKE_BOT(&sccp->bot); i = 0; for (; i < op_array->last_var; ++i) { /* These are all undefined variables, which we have to mark BOT. * Otherwise the undefined variable warning might not be preserved. */ - MAKE_BOT(&ctx->values[i]); + MAKE_BOT(&sccp->values[i]); } for (; i < ssa->vars_count; ++i) { if (ssa->vars[i].alias) { - MAKE_BOT(&ctx->values[i]); + MAKE_BOT(&sccp->values[i]); } else { - MAKE_TOP(&ctx->values[i]); + MAKE_TOP(&sccp->values[i]); } } } -static void sccp_context_free(sccp_ctx *ctx) { +static void sccp_context_free(sccp_ctx *sccp) { int i; - for (i = ctx->scdf.op_array->last_var; i < ctx->scdf.ssa->vars_count; ++i) { - zval_ptr_dtor_nogc(&ctx->values[i]); + for (i = sccp->scdf.op_array->last_var; i < sccp->scdf.ssa->vars_count; ++i) { + zval_ptr_dtor_nogc(&sccp->values[i]); } - efree(ctx->values); } -int sccp_optimize_op_array(zend_op_array *op_array, zend_ssa *ssa, zend_call_info **call_map) +int sccp_optimize_op_array(zend_optimizer_ctx *ctx, zend_op_array *op_array, zend_ssa *ssa, zend_call_info **call_map) { - sccp_ctx ctx; + sccp_ctx sccp; int removed_ops = 0; + void *checkpoint = zend_arena_checkpoint(ctx->arena); - sccp_context_init(&ctx, ssa, op_array, call_map); + sccp_context_init(ctx, &sccp, ssa, op_array, call_map); - ctx.scdf.handlers.visit_instr = sccp_visit_instr; - ctx.scdf.handlers.visit_phi = sccp_visit_phi; - ctx.scdf.handlers.mark_feasible_successors = sccp_mark_feasible_successors; + sccp.scdf.handlers.visit_instr = sccp_visit_instr; + sccp.scdf.handlers.visit_phi = sccp_visit_phi; + sccp.scdf.handlers.mark_feasible_successors = sccp_mark_feasible_successors; - scdf_init(&ctx.scdf, op_array, ssa); - scdf_solve(&ctx.scdf, "SCCP"); + scdf_init(ctx, &sccp.scdf, op_array, ssa); + scdf_solve(&sccp.scdf, "SCCP"); - removed_ops += scdf_remove_unreachable_blocks(&ctx.scdf); - removed_ops += replace_constant_operands(&ctx); + removed_ops += scdf_remove_unreachable_blocks(&sccp.scdf); + removed_ops += replace_constant_operands(&sccp); - sccp_context_free(&ctx); - scdf_free(&ctx.scdf); + sccp_context_free(&sccp); + zend_arena_release(&ctx->arena, checkpoint); return removed_ops; } diff --git a/ext/opcache/Optimizer/scdf.c b/ext/opcache/Optimizer/scdf.c index c82e5879eb0c4..77a8d067c4123 100644 --- a/ext/opcache/Optimizer/scdf.c +++ b/ext/opcache/Optimizer/scdf.c @@ -52,35 +52,35 @@ #define DEBUG_PRINT(...) #endif -void scdf_mark_edge_feasible(scdf_ctx *ctx, int from, int to) { - uint32_t edge = scdf_edge(&ctx->ssa->cfg, from, to); +void scdf_mark_edge_feasible(scdf_ctx *scdf, int from, int to) { + uint32_t edge = scdf_edge(&scdf->ssa->cfg, from, to); - if (zend_bitset_in(ctx->feasible_edges, edge)) { + if (zend_bitset_in(scdf->feasible_edges, edge)) { /* We already handled this edge */ return; } DEBUG_PRINT("Marking edge %d->%d feasible\n", from, to); - zend_bitset_incl(ctx->feasible_edges, edge); + zend_bitset_incl(scdf->feasible_edges, edge); - if (!zend_bitset_in(ctx->executable_blocks, to)) { - if (!zend_bitset_in(ctx->block_worklist, to)) { + if (!zend_bitset_in(scdf->executable_blocks, to)) { + if (!zend_bitset_in(scdf->block_worklist, to)) { DEBUG_PRINT("Adding block %d to worklist\n", to); } - zend_bitset_incl(ctx->block_worklist, to); + zend_bitset_incl(scdf->block_worklist, to); } else { /* Block is already executable, only a new edge became feasible. * Reevaluate phi nodes to account for changed source operands. */ - zend_ssa_block *ssa_block = &ctx->ssa->blocks[to]; + zend_ssa_block *ssa_block = &scdf->ssa->blocks[to]; zend_ssa_phi *phi; for (phi = ssa_block->phis; phi; phi = phi->next) { - zend_bitset_excl(ctx->phi_var_worklist, phi->ssa_var); - ctx->handlers.visit_phi(ctx, phi); + zend_bitset_excl(scdf->phi_var_worklist, phi->ssa_var); + scdf->handlers.visit_phi(scdf, phi); } } } -void scdf_init(scdf_ctx *ctx, zend_op_array *op_array, zend_ssa *ssa) { +void scdf_init(zend_optimizer_ctx *ctx, scdf_ctx *scdf, zend_op_array *op_array, zend_ssa *ssa) { uint32_t edges_count = 0; int b; @@ -88,104 +88,100 @@ void scdf_init(scdf_ctx *ctx, zend_op_array *op_array, zend_ssa *ssa) { edges_count += ssa->cfg.blocks[b].predecessors_count; } - ctx->op_array = op_array; - ctx->ssa = ssa; + scdf->op_array = op_array; + scdf->ssa = ssa; - ctx->instr_worklist_len = zend_bitset_len(op_array->last); - ctx->phi_var_worklist_len = zend_bitset_len(ssa->vars_count); - ctx->block_worklist_len = zend_bitset_len(ssa->cfg.blocks_count); + scdf->instr_worklist_len = zend_bitset_len(op_array->last); + scdf->phi_var_worklist_len = zend_bitset_len(ssa->vars_count); + scdf->block_worklist_len = zend_bitset_len(ssa->cfg.blocks_count); - ctx->instr_worklist = ecalloc( - ctx->instr_worklist_len + ctx->phi_var_worklist_len + 2 * ctx->block_worklist_len + zend_bitset_len(edges_count), + scdf->instr_worklist = zend_arena_calloc(&ctx->arena, + scdf->instr_worklist_len + scdf->phi_var_worklist_len + 2 * scdf->block_worklist_len + zend_bitset_len(edges_count), sizeof(zend_ulong)); - ctx->phi_var_worklist = ctx->instr_worklist + ctx->instr_worklist_len; - ctx->block_worklist = ctx->phi_var_worklist + ctx->phi_var_worklist_len; - ctx->executable_blocks = ctx->block_worklist + ctx->block_worklist_len; - ctx->feasible_edges = ctx->executable_blocks + ctx->block_worklist_len; + scdf->phi_var_worklist = scdf->instr_worklist + scdf->instr_worklist_len; + scdf->block_worklist = scdf->phi_var_worklist + scdf->phi_var_worklist_len; + scdf->executable_blocks = scdf->block_worklist + scdf->block_worklist_len; + scdf->feasible_edges = scdf->executable_blocks + scdf->block_worklist_len; - zend_bitset_incl(ctx->block_worklist, 0); - zend_bitset_incl(ctx->executable_blocks, 0); + zend_bitset_incl(scdf->block_worklist, 0); + zend_bitset_incl(scdf->executable_blocks, 0); } -void scdf_free(scdf_ctx *ctx) { - efree(ctx->instr_worklist); -} - -void scdf_solve(scdf_ctx *ctx, const char *name) { - zend_ssa *ssa = ctx->ssa; +void scdf_solve(scdf_ctx *scdf, const char *name) { + zend_ssa *ssa = scdf->ssa; DEBUG_PRINT("Start SCDF solve (%s)\n", name); - while (!zend_bitset_empty(ctx->instr_worklist, ctx->instr_worklist_len) - || !zend_bitset_empty(ctx->phi_var_worklist, ctx->phi_var_worklist_len) - || !zend_bitset_empty(ctx->block_worklist, ctx->block_worklist_len) + while (!zend_bitset_empty(scdf->instr_worklist, scdf->instr_worklist_len) + || !zend_bitset_empty(scdf->phi_var_worklist, scdf->phi_var_worklist_len) + || !zend_bitset_empty(scdf->block_worklist, scdf->block_worklist_len) ) { int i; - while ((i = zend_bitset_pop_first(ctx->phi_var_worklist, ctx->phi_var_worklist_len)) >= 0) { + while ((i = zend_bitset_pop_first(scdf->phi_var_worklist, scdf->phi_var_worklist_len)) >= 0) { zend_ssa_phi *phi = ssa->vars[i].definition_phi; ZEND_ASSERT(phi); - if (zend_bitset_in(ctx->executable_blocks, phi->block)) { - ctx->handlers.visit_phi(ctx, phi); + if (zend_bitset_in(scdf->executable_blocks, phi->block)) { + scdf->handlers.visit_phi(scdf, phi); } } - while ((i = zend_bitset_pop_first(ctx->instr_worklist, ctx->instr_worklist_len)) >= 0) { + while ((i = zend_bitset_pop_first(scdf->instr_worklist, scdf->instr_worklist_len)) >= 0) { int block_num = ssa->cfg.map[i]; - if (zend_bitset_in(ctx->executable_blocks, block_num)) { + if (zend_bitset_in(scdf->executable_blocks, block_num)) { zend_basic_block *block = &ssa->cfg.blocks[block_num]; - zend_op *opline = &ctx->op_array->opcodes[i]; + zend_op *opline = &scdf->op_array->opcodes[i]; zend_ssa_op *ssa_op = &ssa->ops[i]; if (opline->opcode == ZEND_OP_DATA) { opline--; ssa_op--; } - ctx->handlers.visit_instr(ctx, opline, ssa_op); + scdf->handlers.visit_instr(scdf, opline, ssa_op); if (i == block->start + block->len - 1) { if (block->successors_count == 1) { - scdf_mark_edge_feasible(ctx, block_num, block->successors[0]); + scdf_mark_edge_feasible(scdf, block_num, block->successors[0]); } else if (block->successors_count > 1) { - ctx->handlers.mark_feasible_successors(ctx, block_num, block, opline, ssa_op); + scdf->handlers.mark_feasible_successors(scdf, block_num, block, opline, ssa_op); } } } } - while ((i = zend_bitset_pop_first(ctx->block_worklist, ctx->block_worklist_len)) >= 0) { + while ((i = zend_bitset_pop_first(scdf->block_worklist, scdf->block_worklist_len)) >= 0) { /* This block is now live. Interpret phis and instructions in it. */ zend_basic_block *block = &ssa->cfg.blocks[i]; zend_ssa_block *ssa_block = &ssa->blocks[i]; DEBUG_PRINT("Pop block %d from worklist\n", i); - zend_bitset_incl(ctx->executable_blocks, i); + zend_bitset_incl(scdf->executable_blocks, i); { zend_ssa_phi *phi; for (phi = ssa_block->phis; phi; phi = phi->next) { - zend_bitset_excl(ctx->phi_var_worklist, phi->ssa_var); - ctx->handlers.visit_phi(ctx, phi); + zend_bitset_excl(scdf->phi_var_worklist, phi->ssa_var); + scdf->handlers.visit_phi(scdf, phi); } } if (block->len == 0) { /* Zero length blocks don't have a last instruction that would normally do this */ - scdf_mark_edge_feasible(ctx, i, block->successors[0]); + scdf_mark_edge_feasible(scdf, i, block->successors[0]); } else { zend_op *opline; int j, end = block->start + block->len; for (j = block->start; j < end; j++) { - opline = &ctx->op_array->opcodes[j]; - zend_bitset_excl(ctx->instr_worklist, j); + opline = &scdf->op_array->opcodes[j]; + zend_bitset_excl(scdf->instr_worklist, j); if (opline->opcode != ZEND_OP_DATA) { - ctx->handlers.visit_instr(ctx, opline, &ssa->ops[j]); + scdf->handlers.visit_instr(scdf, opline, &ssa->ops[j]); } } if (block->successors_count == 1) { - scdf_mark_edge_feasible(ctx, i, block->successors[0]); + scdf_mark_edge_feasible(scdf, i, block->successors[0]); } else if (block->successors_count > 1) { if (opline->opcode == ZEND_OP_DATA) { opline--; j--; } - ctx->handlers.mark_feasible_successors(ctx, i, block, opline, &ssa->ops[j-1]); + scdf->handlers.mark_feasible_successors(scdf, i, block, opline, &ssa->ops[j-1]); } } } diff --git a/ext/opcache/Optimizer/scdf.h b/ext/opcache/Optimizer/scdf.h index c3d6b575a9e14..6291534286e7b 100644 --- a/ext/opcache/Optimizer/scdf.h +++ b/ext/opcache/Optimizer/scdf.h @@ -46,9 +46,8 @@ typedef struct _scdf_ctx { } handlers; } scdf_ctx; -void scdf_init(scdf_ctx *scdf, zend_op_array *op_array, zend_ssa *ssa); +void scdf_init(zend_optimizer_ctx *ctx, scdf_ctx *scdf, zend_op_array *op_array, zend_ssa *ssa); void scdf_solve(scdf_ctx *scdf, const char *name); -void scdf_free(scdf_ctx *scdf); int scdf_remove_unreachable_blocks(scdf_ctx *scdf); @@ -95,6 +94,6 @@ static inline zend_bool scdf_is_edge_feasible(scdf_ctx *scdf, int from, int to) return zend_bitset_in(scdf->feasible_edges, edge); } -void scdf_mark_edge_feasible(scdf_ctx *ctx, int from, int to); +void scdf_mark_edge_feasible(scdf_ctx *scdf, int from, int to); #endif diff --git a/ext/opcache/Optimizer/zend_optimizer_internal.h b/ext/opcache/Optimizer/zend_optimizer_internal.h index d2b8b08a87d63..71dcf0a274a3f 100644 --- a/ext/opcache/Optimizer/zend_optimizer_internal.h +++ b/ext/opcache/Optimizer/zend_optimizer_internal.h @@ -110,6 +110,6 @@ uint32_t zend_optimizer_classify_function(zend_string *name, uint32_t num_args); void zend_optimizer_migrate_jump(zend_op_array *op_array, zend_op *new_opline, zend_op *opline); void zend_optimizer_shift_jump(zend_op_array *op_array, zend_op *opline, uint32_t *shiftlist); zend_uchar zend_compound_assign_to_binary_op(zend_uchar opcode); -int sccp_optimize_op_array(zend_op_array *op_arrya, zend_ssa *ssa, zend_call_info **call_map); +int sccp_optimize_op_array(zend_optimizer_ctx *ctx, zend_op_array *op_arrya, zend_ssa *ssa, zend_call_info **call_map); #endif