]> granicus.if.org Git - php/commitdiff
Allow optional splitting of basic blocks at RECV/RECV_INIT opcodes.
authorDmitry Stogov <dmitry@zend.com>
Mon, 29 Aug 2016 17:35:17 +0000 (20:35 +0300)
committerDmitry Stogov <dmitry@zend.com>
Mon, 29 Aug 2016 17:35:17 +0000 (20:35 +0300)
ext/opcache/Optimizer/zend_cfg.c
ext/opcache/Optimizer/zend_cfg.h
ext/opcache/Optimizer/zend_dump.c

index 04be6a2e26d9fec62f134c7b50552bd6b85cc1d0..f39f9650aeecd966239863f6ec92de4255c2c398 100644 (file)
@@ -70,6 +70,12 @@ static void zend_mark_reachable(zend_op *opcodes, zend_cfg *cfg, zend_basic_bloc
                                                        b->flags |= ZEND_BB_ENTRY;
                                                }
                                        }
+                                       if (cfg->split_at_recv) {
+                                               if (opcode == ZEND_RECV ||
+                                                   opcode == ZEND_RECV_INIT) {
+                                                       b->flags |= ZEND_BB_RECV_ENTRY;
+                                               }
+                                       }
                                }
                        } else {
                                b = blocks + successor_0;
@@ -283,6 +289,7 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
 
        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->split_at_recv = (build_flags & ZEND_CFG_RECV_ENTRY) != 0 && (op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0;
 
        cfg->map = block_map = zend_arena_calloc(arena, op_array->last, sizeof(uint32_t));
        if (!block_map) {
@@ -294,6 +301,12 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
        for (i = 0; i < op_array->last; i++) {
                zend_op *opline = op_array->opcodes + i;
                switch(opline->opcode) {
+                       case ZEND_RECV:
+                       case ZEND_RECV_INIT:
+                               if (build_flags & ZEND_CFG_RECV_ENTRY) {
+                                       BB_START(i + 1);
+                               }
+                               break;
                        case ZEND_RETURN:
                        case ZEND_RETURN_BY_REF:
                        case ZEND_GENERATOR_RETURN:
index 06826290193097f156f9b5ed40e50dee4fd5ed81..1ffb62add08e154b2baf961c879a11156fef2af2 100644 (file)
 #define ZEND_BB_GEN_VAR          (1<<9)  /* start of live range    */
 #define ZEND_BB_KILL_VAR         (1<<10) /* end of live range      */
 #define ZEND_BB_UNREACHABLE_FREE (1<<11) /* unreachable loop free  */
+#define ZEND_BB_RECV_ENTRY       (1<<12) /* RECV entry             */
 
 #define ZEND_BB_LOOP_HEADER      (1<<16)
 #define ZEND_BB_IRREDUCIBLE_LOOP (1<<17)
 
 #define ZEND_BB_REACHABLE        (1<<31)
 
-#define ZEND_BB_PROTECTED        (ZEND_BB_ENTRY|ZEND_BB_TRY|ZEND_BB_CATCH|ZEND_BB_FINALLY|ZEND_BB_FINALLY_END|ZEND_BB_GEN_VAR|ZEND_BB_KILL_VAR)
+#define ZEND_BB_PROTECTED        (ZEND_BB_ENTRY|ZEND_BB_RECV_ENTRY|ZEND_BB_TRY|ZEND_BB_CATCH|ZEND_BB_FINALLY|ZEND_BB_FINALLY_END|ZEND_BB_GEN_VAR|ZEND_BB_KILL_VAR)
 
 typedef struct _zend_basic_block {
        uint32_t          flags;
@@ -88,6 +89,7 @@ typedef struct _zend_cfg {
        uint32_t         *map;
        unsigned int      split_at_live_ranges : 1;
        unsigned int      split_at_calls : 1;
+       unsigned int      split_at_recv : 1;
 } zend_cfg;
 
 /* Build Flags */
@@ -98,6 +100,7 @@ typedef struct _zend_cfg {
 #define ZEND_SSA_RC_INFERENCE          (1<<27)
 #define ZEND_CFG_SPLIT_AT_LIVE_RANGES  (1<<26)
 #define ZEND_CFG_NO_ENTRY_PREDECESSORS (1<<25)
+#define ZEND_CFG_RECV_ENTRY            (1<<24)
 
 #define CRT_CONSTANT_EX(op_array, node, rt_constants) \
        ((rt_constants) ? \
index a611b55cd5bb83826859eba4a420582125ed6cd5..ed9b6a59d98d11894e815a583a9c4d2ae14ab77a 100644 (file)
@@ -669,7 +669,7 @@ static void zend_dump_block_info(const zend_cfg *cfg, int n, uint32_t dump_flags
        if (b->flags & ZEND_BB_EXIT) {
                fprintf(stderr, " exit");
        }
-       if (b->flags & ZEND_BB_ENTRY) {
+       if (b->flags & (ZEND_BB_ENTRY|ZEND_BB_RECV_ENTRY)) {
                fprintf(stderr, " entry");
        }
        if (b->flags & ZEND_BB_TRY) {