From caf890b29166c8a1c921b7f9d9fa4e6eec02c0dd Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Mon, 22 Aug 2016 16:48:26 +0300 Subject: [PATCH] Fixed CFG construction for stackless execution (split basic blocks after calls) --- ext/opcache/Optimizer/zend_cfg.c | 22 ++++++++++++---------- ext/opcache/Optimizer/zend_cfg.h | 1 + 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/ext/opcache/Optimizer/zend_cfg.c b/ext/opcache/Optimizer/zend_cfg.c index 335ad75827..92d648dc23 100644 --- a/ext/opcache/Optimizer/zend_cfg.c +++ b/ext/opcache/Optimizer/zend_cfg.c @@ -24,11 +24,12 @@ #include "zend_optimizer.h" #include "zend_optimizer_internal.h" -static void zend_mark_reachable(zend_op *opcodes, zend_basic_block *blocks, zend_basic_block *b) /* {{{ */ +static void zend_mark_reachable(zend_op *opcodes, zend_cfg *cfg, zend_basic_block *b) /* {{{ */ { zend_uchar opcode; zend_basic_block *b0; int successor_0, successor_1; + zend_basic_block *blocks = cfg->blocks; while (1) { b->flags |= ZEND_BB_REACHABLE; @@ -39,7 +40,7 @@ static void zend_mark_reachable(zend_op *opcodes, zend_basic_block *blocks, zend b0 = blocks + successor_0; b0->flags |= ZEND_BB_TARGET; if (!(b0->flags & ZEND_BB_REACHABLE)) { - zend_mark_reachable(opcodes, blocks, b0); + zend_mark_reachable(opcodes, cfg, b0); } ZEND_ASSERT(b->len != 0); @@ -58,8 +59,7 @@ static void zend_mark_reachable(zend_op *opcodes, zend_basic_block *blocks, zend } else { b->flags |= ZEND_BB_FOLLOW; - //TODO: support for stackless CFG??? - if (0/*stackless*/) { + if (cfg->split_at_calls) { if (opcode == ZEND_INCLUDE_OR_EVAL || opcode == ZEND_GENERATOR_CREATE || opcode == ZEND_YIELD || @@ -89,7 +89,7 @@ static void zend_mark_reachable_blocks(const zend_op_array *op_array, zend_cfg * zend_basic_block *blocks = cfg->blocks; blocks[start].flags = ZEND_BB_START; - zend_mark_reachable(op_array->opcodes, blocks, blocks + start); + zend_mark_reachable(op_array->opcodes, cfg, blocks + start); if (op_array->last_live_range || op_array->last_try_catch) { zend_basic_block *b; @@ -123,7 +123,7 @@ static void zend_mark_reachable_blocks(const zend_op_array *op_array, zend_cfg * if (!(b->flags & ZEND_BB_REACHABLE)) { if (cfg->split_at_live_ranges) { changed = 1; - zend_mark_reachable(op_array->opcodes, blocks, b); + zend_mark_reachable(op_array->opcodes, cfg, b); } else { ZEND_ASSERT(!(b->flags & ZEND_BB_UNREACHABLE_FREE)); ZEND_ASSERT(b->start == live_range->end); @@ -161,7 +161,7 @@ static void zend_mark_reachable_blocks(const zend_op_array *op_array, zend_cfg * if (b->flags & ZEND_BB_REACHABLE) { op_array->try_catch_array[j].try_op = op_array->try_catch_array[j].catch_op; changed = 1; - zend_mark_reachable(op_array->opcodes, blocks, blocks + block_map[op_array->try_catch_array[j].try_op]); + zend_mark_reachable(op_array->opcodes, cfg, blocks + block_map[op_array->try_catch_array[j].try_op]); break; } b++; @@ -178,7 +178,7 @@ static void zend_mark_reachable_blocks(const zend_op_array *op_array, zend_cfg * b->flags |= ZEND_BB_CATCH; if (!(b->flags & ZEND_BB_REACHABLE)) { changed = 1; - zend_mark_reachable(op_array->opcodes, blocks, b); + zend_mark_reachable(op_array->opcodes, cfg, b); } } if (op_array->try_catch_array[j].finally_op) { @@ -186,7 +186,7 @@ static void zend_mark_reachable_blocks(const zend_op_array *op_array, zend_cfg * b->flags |= ZEND_BB_FINALLY; if (!(b->flags & ZEND_BB_REACHABLE)) { changed = 1; - zend_mark_reachable(op_array->opcodes, blocks, b); + zend_mark_reachable(op_array->opcodes, cfg, b); } } if (op_array->try_catch_array[j].finally_end) { @@ -194,7 +194,7 @@ static void zend_mark_reachable_blocks(const zend_op_array *op_array, zend_cfg * b->flags |= ZEND_BB_FINALLY_END; if (!(b->flags & ZEND_BB_REACHABLE)) { changed = 1; - zend_mark_reachable(op_array->opcodes, blocks, b); + zend_mark_reachable(op_array->opcodes, cfg, b); } } } else { @@ -273,6 +273,8 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b zend_bool extra_entry_block = 0; cfg->split_at_live_ranges = (build_flags & ZEND_CFG_SPLIT_AT_LIVE_RANGES) != 0; + cfg->split_at_calls = (build_flags & ZEND_CFG_STACKLESS) != 0; + cfg->map = block_map = zend_arena_calloc(arena, op_array->last, sizeof(uint32_t)); if (!block_map) { return FAILURE; diff --git a/ext/opcache/Optimizer/zend_cfg.h b/ext/opcache/Optimizer/zend_cfg.h index da908fdbe3..0682629019 100644 --- a/ext/opcache/Optimizer/zend_cfg.h +++ b/ext/opcache/Optimizer/zend_cfg.h @@ -87,6 +87,7 @@ typedef struct _zend_cfg { int *predecessors; uint32_t *map; unsigned int split_at_live_ranges : 1; + unsigned int split_at_calls : 1; } zend_cfg; /* Build Flags */ -- 2.50.1