Having ->current_range in struct interval is very error prone.
Instead of that, we maintain a list of expired ranges, which are moved
from range_list and are no longer considered as interval's
ranges. After linear scan expired ranges are restored.

This fixes a crash in trace_var_liveness().

Signed-off-by: Tomek Grabiec <tgrab...@gmail.com>
---
 include/jit/vars.h |   18 ++++++++----------
 jit/interval.c     |   41 +++++++++++++++++++++++------------------
 jit/linear-scan.c  |   15 +++++++++++----
 3 files changed, 42 insertions(+), 32 deletions(-)

diff --git a/include/jit/vars.h b/include/jit/vars.h
index 2471b17..ae48752 100644
--- a/include/jit/vars.h
+++ b/include/jit/vars.h
@@ -65,16 +65,13 @@ struct live_interval {
        struct list_head range_list;
 
        /*
-        * Points to a range from range_list which should be
-        * considered as interval's starting range in operations:
-        * intervals_intersect(), interval_intersection_start(),
-        * interval_range_at(). It's used to speedup register
-        * allocation. Intervals can have a lot of live ranges. Linear
-        * scan algorithm goes through intervals in ascending order by
-        * interval start. We can take advantage of this and don't
-        * browse ranges past current position in some operations.
+        * Contains ranges which were moved from range_list to speedup
+        * some interval oprations. Intervals can have a lot of live
+        * ranges. Linear scan algorithm goes through intervals in
+        * ascending order by interval start. We can take advantage of
+        * this and don't check ranges before current position.
         */
-       struct live_range *current_range;
+       struct list_head expired_range_list;
 
        /* Linked list of child intervals.  */
        struct live_interval *next_child, *prev_child;
@@ -172,7 +169,8 @@ unsigned long interval_intersection_start(struct 
live_interval *, struct live_in
 bool interval_covers(struct live_interval *, unsigned long);
 int interval_add_range(struct live_interval *, unsigned long, unsigned long);
 struct live_range *interval_range_at(struct live_interval *, unsigned long);
-void interval_update_current_range(struct live_interval *, unsigned long);
+void interval_expire_ranges_before(struct live_interval *, unsigned long);
+void interval_restore_expired_ranges(struct live_interval *);
 
 static inline unsigned long first_use_pos(struct live_interval *it)
 {
diff --git a/jit/interval.c b/jit/interval.c
index 8eb7d32..c84de36 100644
--- a/jit/interval.c
+++ b/jit/interval.c
@@ -106,6 +106,7 @@ struct live_interval *alloc_interval(struct var_info *var)
                INIT_LIST_HEAD(&interval->interval_node);
                INIT_LIST_HEAD(&interval->use_positions);
                INIT_LIST_HEAD(&interval->range_list);
+               INIT_LIST_HEAD(&interval->expired_range_list);
        }
        return interval;
 }
@@ -143,8 +144,6 @@ struct live_interval *split_interval_at(struct 
live_interval *interval,
                return NULL;
        }
 
-       new->current_range = interval_first_range(new);
-
        new->fixed_reg = interval->fixed_reg;
        if (new->fixed_reg)
                new->reg = interval->reg;
@@ -210,25 +209,33 @@ struct live_interval *vreg_start_interval(struct 
compilation_unit *cu, unsigned
        return var->interval;
 }
 
-/**
- * Advances @it->current_range to the last range which covers @pos or
- * is before @pos.
- */
-void interval_update_current_range(struct live_interval *it, unsigned long pos)
+void interval_expire_ranges_before(struct live_interval *it, unsigned long pos)
 {
+       struct live_range *range;
+
        if (pos < interval_start(it) || pos >= interval_end(it))
                return;
 
-       assert (pos >= it->current_range->start);
+       range = interval_first_range(it);
 
-       while (!in_range(it->current_range, pos)) {
+       while (!in_range(range, pos)) {
                struct live_range *next;
 
-               next = next_range(&it->range_list, it->current_range);
+               next = next_range(&it->range_list, range);
                if (pos < next->start)
                        break;
 
-               it->current_range = next;
+               list_move(&range->range_list_node, &it->expired_range_list);
+               range = next;
+       }
+}
+
+void interval_restore_expired_ranges(struct live_interval *it)
+{
+       struct live_range *this, *next;
+
+       list_for_each_entry_safe(this, next, &it->expired_range_list, 
range_list_node) {
+               list_move(&this->range_list_node, &it->range_list);
        }
 }
 
@@ -239,9 +246,7 @@ struct live_range *interval_range_at(struct live_interval 
*it, unsigned long pos
        if (pos < interval_start(it) || pos >= interval_end(it))
                return NULL;
 
-       range = it->current_range;
-       if (pos < range->start)
-               range = interval_first_range(it);
+       range = interval_first_range(it);
 
        while (range && pos >= range->start) {
                if (in_range(range, pos))
@@ -281,8 +286,8 @@ bool intervals_intersect(struct live_interval *it1, struct 
live_interval *it2)
        if (interval_is_empty(it1) || interval_is_empty(it2))
                return false;
 
-       r1 = it1->current_range;
-       r2 = it2->current_range;
+       r1 = interval_first_range(it1);
+       r2 = interval_first_range(it2);
 
        while (r1 && r1->end <= r2->start)
                r1 = next_range(&it1->range_list, r1);
@@ -310,8 +315,8 @@ interval_intersection_start(struct live_interval *it1, 
struct live_interval *it2
 
        assert(!interval_is_empty(it1) && !interval_is_empty(it2));
 
-       r1 = it1->current_range;
-       r2 = it2->current_range;
+       r1 = interval_first_range(it1);
+       r2 = interval_first_range(it2);
 
        while (r1 && r1->end <= r2->start)
                r1 = next_range(&it1->range_list, r1);
diff --git a/jit/linear-scan.c b/jit/linear-scan.c
index c824104..05ff33d 100644
--- a/jit/linear-scan.c
+++ b/jit/linear-scan.c
@@ -354,8 +354,6 @@ int allocate_registers(struct compilation_unit *cu)
                if (interval_is_empty(var->interval))
                        continue;
 
-               var->interval->current_range = 
interval_first_range(var->interval);
-
                if (var->interval->fixed_reg) {
                        if (var->interval->reg < NR_REGISTERS)
                                list_add(&var->interval->interval_node, 
&inactive);
@@ -379,7 +377,7 @@ int allocate_registers(struct compilation_unit *cu)
                                continue;
                        }
 
-                       interval_update_current_range(it, position);
+                       interval_expire_ranges_before(it, position);
 
                        if (!interval_covers(it, position))
                                list_move(&it->interval_node, &inactive);
@@ -394,7 +392,7 @@ int allocate_registers(struct compilation_unit *cu)
                                continue;
                        }
 
-                       interval_update_current_range(it, position);
+                       interval_expire_ranges_before(it, position);
 
                        if (interval_covers(it, position))
                                list_move(&it->interval_node, &active);
@@ -415,6 +413,15 @@ int allocate_registers(struct compilation_unit *cu)
        }
        free(registers);
 
+       for_each_variable(var, cu->var_infos) {
+               struct live_interval *it = var->interval;
+
+               while (it) {
+                       interval_restore_expired_ranges(it);
+                       it = it->next_child;
+               }
+       }
+
        cu->is_reg_alloc_done = true;
 
        return 0;
-- 
1.6.3.3


------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day 
trial. Simplify your report design, integration and deployment - and focus on 
what you do best, core application coding. Discover what's new with 
Crystal Reports now.  http://p.sf.net/sfu/bobj-july
_______________________________________________
Jatovm-devel mailing list
Jatovm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jatovm-devel

Reply via email to