]> granicus.if.org Git - php/commitdiff
Eliminate unreachable live ranges
authorDmitry Stogov <dmitry@zend.com>
Wed, 18 Nov 2015 15:04:02 +0000 (18:04 +0300)
committerDmitry Stogov <dmitry@zend.com>
Wed, 18 Nov 2015 15:04:02 +0000 (18:04 +0300)
ext/opcache/Optimizer/block_pass.c
ext/opcache/Optimizer/zend_optimizer.c

index a42aecf2c560cbe9b65754bcf52c67930e637b16..c3508267efb4b644ee601865202afab912132d5f 100644 (file)
@@ -711,31 +711,74 @@ static void zend_rebuild_access_path(zend_cfg *cfg, zend_op_array *op_array, int
        /* Walk thorough all paths */
        zend_access_path(start, ctx);
 
-       /* Add brk/cont paths */
-       if (op_array->last_live_range) {
-               int i;
-               for (i=0; i< op_array->last_live_range; i++) {
-                       zend_access_path(cfg->live_range_start[i], ctx);
-                       zend_access_path(cfg->live_range_end[i], ctx);
-               }
-       }
+       if (op_array->last_live_range || op_array->last_try_catch) {
+               int i, changed;
 
-       /* Add exception paths */
-       if (op_array->last_try_catch) {
-               int changed;
                do {
-                       int i;
-
                        changed = 0;
-                       for (i=0; i< op_array->last_try_catch; i++) {
-                               if (cfg->try[i]->access) {
-                                       if (!cfg->catch[i]->access) {
+                       /* Add brk/cont paths */
+                       for (i = 0; i< op_array->last_live_range; i++) {
+                               if (cfg->live_range_start[i]->access) {
+                                       if (!cfg->live_range_end[i]->access) {
                                                changed = 1;
-                                               zend_access_path(cfg->catch[i], ctx);
+                                               zend_access_path(cfg->live_range_end[i], ctx);
+                                       }
+                               } else {
+                                       ZEND_ASSERT(!cfg->live_range_end[i]->access);
+                               }
+                       }
+
+                       /* Add exception paths */
+                       for (i = 0; i< op_array->last_try_catch; i++) {
+                               if (cfg->try[i]->access) {
+                                       if (op_array->try_catch_array[i].catch_op) {
+                                               if (!cfg->catch[i]->access) {
+                                                       changed = 1;
+                                                       zend_access_path(cfg->catch[i], ctx);
+                                               }
+                                       } else {
+                                               ZEND_ASSERT(!cfg->catch[i]->access);
                                        }
                                }
                        }
                } while (changed);
+
+               /* remove unused live ranges */
+               if (op_array->last_live_range) {
+                       int j = 0;
+                       uint32_t *map;
+                       ALLOCA_FLAG(use_heap);
+
+                       map = (uint32_t *)do_alloca(sizeof(uint32_t) * op_array->last_live_range, use_heap);
+
+                       for (i = 0; i < op_array->last_live_range; i++) {
+                               if (!cfg->live_range_start[i]->access) {
+                                       ZEND_ASSERT(!cfg->live_range_end[i]->access);
+                               } else {
+                                       map[i] = j;
+                                       if (i != j) {
+                                               op_array->live_range[j]  = op_array->live_range[i];
+                                               cfg->live_range_start[j] = cfg->live_range_start[i];
+                                               cfg->live_range_end[j]   = cfg->live_range_end[i];
+                                       }
+                                       j++;
+                               }
+                       }
+
+                       if (i != j) {
+                               zend_op *opline = op_array->opcodes;
+                               zend_op *end = opline + op_array->last;
+
+                               op_array->last_live_range = j;
+                               while (opline != end) {
+                                       if ((opline->opcode == ZEND_FREE || opline->opcode == ZEND_FE_FREE) &&
+                                           opline->extended_value == ZEND_FREE_ON_RETURN) {
+                                               opline->op2.num = map[opline->op2.num];
+                                       }
+                                       opline++;
+                               }
+                       }
+               }
        }
 }
 
index a1cfda5e3f86c43f14d04f8edf48e4a3bf701e1f..bc7e875ed38299568811ab9ff3647d8b942496c8 100644 (file)
@@ -440,8 +440,8 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array,
                                        int brk = op_array->last_live_range;
                                        zend_bool in_switch = 0;
                                        while (brk--) {
-                                               if (op_array->live_range[brk].start <= (opline - op_array->opcodes) &&
-                                                   op_array->live_range[brk].end > (opline - op_array->opcodes)) {
+                                               if (op_array->live_range[brk].start <= (uint32_t)(opline - op_array->opcodes) &&
+                                                   op_array->live_range[brk].end > (uint32_t)(opline - op_array->opcodes)) {
                                                        in_switch = 1;
                                                        break;
                                                }