]> granicus.if.org Git - php/commitdiff
Fixed CFG construction for stackless execution (split basic blocks after calls)
authorDmitry Stogov <dmitry@zend.com>
Mon, 22 Aug 2016 13:48:26 +0000 (16:48 +0300)
committerDmitry Stogov <dmitry@zend.com>
Mon, 22 Aug 2016 13:48:26 +0000 (16:48 +0300)
ext/opcache/Optimizer/zend_cfg.c
ext/opcache/Optimizer/zend_cfg.h

index 335ad75827a0540018cf596f05e4890ab9b7fac6..92d648dc23f4e30ac5b52e939b84fff7019b0246 100644 (file)
 #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;
index da908fdbe3750f40edde0d77193397b3529b3eaa..06826290193097f156f9b5ed40e50dee4fd5ed81 100644 (file)
@@ -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 */