Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "src/compiler/coalesced-live-ranges.h" | |
| 6 #include "test/unittests/test-utils.h" | |
| 7 | |
| 8 namespace v8 { | |
| 9 namespace internal { | |
| 10 namespace compiler { | |
| 11 | |
| 12 | |
| 13 // Utility offering shorthand syntax for building up a range by providing its ID | |
| 14 // and pairs (start, end) specifying intervals. Circumvents current incomplete | |
| 15 // support for C++ features such as instantiation lists, on OS X and Android. | |
| 16 class TestRangeBuilder { | |
| 17 public: | |
| 18 explicit TestRangeBuilder(Zone* zone) : id_(-1), pairs_(), zone_(zone) {} | |
| 19 | |
| 20 TestRangeBuilder& Id(int id) { | |
| 21 id_ = id; | |
| 22 return *this; | |
| 23 } | |
| 24 TestRangeBuilder& operator()(int start, int end) { | |
|
Benedikt Meurer
2015/07/13 05:01:25
Operator overloading is strongly discouraged. Plea
Mircea Trofin
2015/07/13 16:54:07
Done.
| |
| 25 pairs_.push_back({start, end}); | |
| 26 return *this; | |
| 27 } | |
| 28 operator LiveRange*() { | |
|
Benedikt Meurer
2015/07/13 05:01:25
How about a Build method instead?
Mircea Trofin
2015/07/13 16:54:07
Done.
| |
| 29 LiveRange* range = new (zone_) LiveRange(id_, MachineType::kRepTagged); | |
| 30 // Traverse the provided interval specifications backwards, because that is | |
| 31 // what LiveRange expects. | |
| 32 for (int i = static_cast<int>(pairs_.size()) - 1; i >= 0; --i) { | |
| 33 auto pair = pairs_[i]; | |
| 34 LifetimePosition start = LifetimePosition::FromInt(pair.first); | |
| 35 LifetimePosition end = LifetimePosition::FromInt(pair.second); | |
| 36 CHECK(start < end); | |
| 37 range->AddUseInterval(start, end, zone_); | |
| 38 } | |
| 39 | |
| 40 pairs_.clear(); | |
| 41 return range; | |
| 42 } | |
| 43 | |
| 44 private: | |
| 45 typedef std::pair<int, int> Interval; | |
| 46 typedef std::vector<Interval> IntervalList; | |
| 47 int id_; | |
| 48 IntervalList pairs_; | |
| 49 Zone* zone_; | |
| 50 }; | |
| 51 | |
| 52 | |
| 53 typedef std::set<int> LiveRangeIDs; | |
| 54 | |
| 55 | |
| 56 // Utility offering shorthand building of a set of integers. Circumvents current | |
| 57 // incomplete support for C++ features such as instantiation lists, on OS X and | |
| 58 // Android. | |
| 59 class TestSetBuilder { | |
| 60 public: | |
| 61 TestSetBuilder(int count, ...) { | |
| 62 va_list list; | |
| 63 va_start(list, count); | |
| 64 for (int i = 0; i < count; ++i) { | |
| 65 int val = va_arg(list, int); | |
| 66 set_.insert(val); | |
| 67 } | |
| 68 va_end(list); | |
| 69 } | |
| 70 | |
| 71 operator LiveRangeIDs&() { return set_; } | |
| 72 | |
| 73 private: | |
| 74 LiveRangeIDs set_; | |
| 75 }; | |
| 76 | |
| 77 | |
| 78 class CoalescedLiveRangesTest : public TestWithZone { | |
| 79 public: | |
| 80 CoalescedLiveRangesTest() : TestWithZone(), ranges_(zone()) {} | |
| 81 bool CheckConflictsMatch(const LiveRange* range, const LiveRangeIDs& ids); | |
| 82 | |
| 83 CoalescedLiveRanges& ranges() { return ranges_; } | |
| 84 const CoalescedLiveRanges& ranges() const { return ranges_; } | |
| 85 bool AllocationsAreValid() const; | |
| 86 void RemoveConflicts(LiveRange* range); | |
| 87 | |
| 88 private: | |
| 89 CoalescedLiveRanges ranges_; | |
| 90 }; | |
| 91 | |
| 92 | |
| 93 void CoalescedLiveRangesTest::RemoveConflicts(LiveRange* range) { | |
| 94 ranges().RemoveConflicts(range, [](LiveRange* conflict) {}); | |
| 95 } | |
| 96 | |
| 97 | |
| 98 bool CoalescedLiveRangesTest::AllocationsAreValid() const { | |
| 99 return ranges().TestOnlyVerifyAllocationsAreValid(); | |
| 100 } | |
| 101 | |
| 102 | |
| 103 bool CoalescedLiveRangesTest::CheckConflictsMatch(const LiveRange* range, | |
| 104 const LiveRangeIDs& ids) { | |
| 105 LiveRangeIDs found_ids; | |
| 106 | |
| 107 ranges().VisitConflicts(range, [&](const LiveRange* conflict) { | |
| 108 found_ids.insert(conflict->id()); | |
| 109 return true; | |
| 110 }); | |
| 111 return found_ids == ids; | |
| 112 } | |
| 113 | |
| 114 | |
| 115 TEST_F(CoalescedLiveRangesTest, VisitEmptyAllocations) { | |
| 116 LiveRange* range = TestRangeBuilder(zone()).Id(1)(1, 5); | |
| 117 ASSERT_TRUE(ranges().empty()); | |
| 118 ASSERT_TRUE(AllocationsAreValid()); | |
| 119 ASSERT_TRUE(CheckConflictsMatch(range, TestSetBuilder(0))); | |
| 120 } | |
| 121 | |
| 122 | |
| 123 TEST_F(CoalescedLiveRangesTest, CandidateBeforeAfterAllocations) { | |
| 124 LiveRange* range = TestRangeBuilder(zone()).Id(1)(5, 6); | |
| 125 ranges().AllocateRange(range); | |
| 126 ASSERT_FALSE(ranges().empty()); | |
| 127 ASSERT_TRUE(AllocationsAreValid()); | |
| 128 LiveRange* query = TestRangeBuilder(zone()).Id(2)(1, 2); | |
| 129 ASSERT_TRUE(CheckConflictsMatch(query, TestSetBuilder(0))); | |
| 130 query = TestRangeBuilder(zone()).Id(3)(1, 5); | |
| 131 ASSERT_TRUE(CheckConflictsMatch(query, TestSetBuilder(0))); | |
| 132 } | |
| 133 | |
| 134 | |
| 135 TEST_F(CoalescedLiveRangesTest, CandidateBeforeAfterManyAllocations) { | |
| 136 LiveRange* range = TestRangeBuilder(zone()).Id(1)(5, 7)(10, 12); | |
| 137 ranges().AllocateRange(range); | |
| 138 ASSERT_FALSE(ranges().empty()); | |
| 139 ASSERT_TRUE(AllocationsAreValid()); | |
| 140 LiveRange* query = TestRangeBuilder(zone()).Id(2)(1, 2)(13, 15); | |
| 141 ASSERT_TRUE(CheckConflictsMatch(query, TestSetBuilder(0))); | |
| 142 query = TestRangeBuilder(zone()).Id(3)(1, 5)(12, 15); | |
| 143 ASSERT_TRUE(CheckConflictsMatch(query, TestSetBuilder(0))); | |
| 144 } | |
| 145 | |
| 146 | |
| 147 TEST_F(CoalescedLiveRangesTest, SelfConflictsWithSelf) { | |
| 148 LiveRange* range = TestRangeBuilder(zone()).Id(1)(1, 5); | |
| 149 ranges().AllocateRange(range); | |
| 150 ASSERT_FALSE(ranges().empty()); | |
| 151 ASSERT_TRUE(AllocationsAreValid()); | |
| 152 ASSERT_TRUE(CheckConflictsMatch(range, TestSetBuilder(1, 1))); | |
| 153 range = TestRangeBuilder(zone()).Id(2)(8, 10); | |
| 154 ranges().AllocateRange(range); | |
| 155 ASSERT_TRUE(CheckConflictsMatch(range, TestSetBuilder(1, 2))); | |
| 156 } | |
| 157 | |
| 158 | |
| 159 TEST_F(CoalescedLiveRangesTest, QueryStartsBeforeConflict) { | |
| 160 LiveRange* range = TestRangeBuilder(zone()).Id(1)(2, 5); | |
| 161 ranges().AllocateRange(range); | |
| 162 LiveRange* query = TestRangeBuilder(zone()).Id(2)(1, 3); | |
| 163 ASSERT_TRUE(CheckConflictsMatch(query, TestSetBuilder(1, 1))); | |
| 164 range = TestRangeBuilder(zone()).Id(3)(8, 10); | |
| 165 ranges().AllocateRange(range); | |
| 166 query = TestRangeBuilder(zone()).Id(4)(6, 9); | |
| 167 ASSERT_TRUE(CheckConflictsMatch(query, TestSetBuilder(1, 3))); | |
| 168 } | |
| 169 | |
| 170 | |
| 171 TEST_F(CoalescedLiveRangesTest, QueryStartsInConflict) { | |
| 172 LiveRange* range = TestRangeBuilder(zone()).Id(1)(2, 5); | |
| 173 ranges().AllocateRange(range); | |
| 174 LiveRange* query = TestRangeBuilder(zone()).Id(2)(3, 6); | |
| 175 ASSERT_TRUE(CheckConflictsMatch(query, TestSetBuilder(1, 1))); | |
| 176 range = TestRangeBuilder(zone()).Id(3)(8, 10); | |
| 177 ranges().AllocateRange(range); | |
| 178 query = TestRangeBuilder(zone()).Id(4)(9, 11); | |
| 179 ASSERT_TRUE(CheckConflictsMatch(query, TestSetBuilder(1, 3))); | |
| 180 } | |
| 181 | |
| 182 | |
| 183 TEST_F(CoalescedLiveRangesTest, QueryContainedInConflict) { | |
| 184 LiveRange* range = TestRangeBuilder(zone()).Id(1)(1, 5); | |
| 185 ranges().AllocateRange(range); | |
| 186 LiveRange* query = TestRangeBuilder(zone()).Id(2)(2, 3); | |
| 187 ASSERT_TRUE(CheckConflictsMatch(query, TestSetBuilder(1, 1))); | |
| 188 } | |
| 189 | |
| 190 | |
| 191 TEST_F(CoalescedLiveRangesTest, QueryContainsConflict) { | |
| 192 LiveRange* range = TestRangeBuilder(zone()).Id(1)(2, 3); | |
| 193 ranges().AllocateRange(range); | |
| 194 LiveRange* query = TestRangeBuilder(zone()).Id(2)(1, 5); | |
| 195 ASSERT_TRUE(CheckConflictsMatch(query, TestSetBuilder(1, 1))); | |
| 196 } | |
| 197 | |
| 198 | |
| 199 TEST_F(CoalescedLiveRangesTest, QueryCoversManyIntervalsSameRange) { | |
| 200 LiveRange* range = TestRangeBuilder(zone()).Id(1)(1, 5)(7, 9)(20, 25); | |
| 201 ranges().AllocateRange(range); | |
| 202 LiveRange* query = TestRangeBuilder(zone()).Id(2)(2, 8); | |
| 203 ASSERT_TRUE(CheckConflictsMatch(query, TestSetBuilder(1, 1))); | |
| 204 } | |
| 205 | |
| 206 | |
| 207 TEST_F(CoalescedLiveRangesTest, QueryCoversManyIntervalsDifferentRanges) { | |
| 208 LiveRange* range = TestRangeBuilder(zone()).Id(1)(1, 5)(20, 25); | |
| 209 ranges().AllocateRange(range); | |
| 210 range = TestRangeBuilder(zone()).Id(2)(7, 10); | |
| 211 ranges().AllocateRange(range); | |
| 212 LiveRange* query = TestRangeBuilder(zone()).Id(3)(2, 22); | |
| 213 ASSERT_TRUE(CheckConflictsMatch(query, TestSetBuilder(2, 1, 2))); | |
| 214 } | |
| 215 | |
| 216 | |
| 217 TEST_F(CoalescedLiveRangesTest, QueryFitsInGaps) { | |
| 218 LiveRange* range = TestRangeBuilder(zone()).Id(1)(1, 5)(10, 15)(20, 25); | |
| 219 ranges().AllocateRange(range); | |
| 220 LiveRange* query = TestRangeBuilder(zone()).Id(3)(5, 10)(16, 19)(27, 30); | |
| 221 ASSERT_TRUE(CheckConflictsMatch(query, TestSetBuilder(0))); | |
| 222 } | |
| 223 | |
| 224 | |
| 225 TEST_F(CoalescedLiveRangesTest, DeleteConflictBefore) { | |
| 226 LiveRange* range = TestRangeBuilder(zone()).Id(1)(1, 4)(5, 6); | |
| 227 ranges().AllocateRange(range); | |
| 228 range = TestRangeBuilder(zone()).Id(2)(40, 50); | |
| 229 ranges().AllocateRange(range); | |
| 230 LiveRange* query = TestRangeBuilder(zone()).Id(3)(3, 7); | |
| 231 RemoveConflicts(query); | |
| 232 query = TestRangeBuilder(zone()).Id(4)(0, 60); | |
| 233 ASSERT_TRUE(CheckConflictsMatch(query, TestSetBuilder(1, 2))); | |
| 234 } | |
| 235 | |
| 236 | |
| 237 TEST_F(CoalescedLiveRangesTest, DeleteConflictAfter) { | |
| 238 LiveRange* range = TestRangeBuilder(zone()).Id(1)(1, 5); | |
| 239 ranges().AllocateRange(range); | |
| 240 range = TestRangeBuilder(zone()).Id(2)(40, 50)(60, 70); | |
| 241 ranges().AllocateRange(range); | |
| 242 LiveRange* query = TestRangeBuilder(zone()).Id(3)(45, 60); | |
| 243 RemoveConflicts(query); | |
| 244 query = TestRangeBuilder(zone()).Id(4)(0, 60); | |
| 245 ASSERT_TRUE(CheckConflictsMatch(query, TestSetBuilder(1, 1))); | |
| 246 } | |
| 247 | |
| 248 | |
| 249 TEST_F(CoalescedLiveRangesTest, DeleteConflictStraddle) { | |
| 250 LiveRange* range = TestRangeBuilder(zone()).Id(1)(1, 5)(10, 20); | |
| 251 ranges().AllocateRange(range); | |
| 252 range = TestRangeBuilder(zone()).Id(2)(40, 50); | |
| 253 ranges().AllocateRange(range); | |
| 254 LiveRange* query = TestRangeBuilder(zone()).Id(3)(4, 15); | |
| 255 RemoveConflicts(query); | |
| 256 query = TestRangeBuilder(zone()).Id(4)(0, 60); | |
| 257 ASSERT_TRUE(CheckConflictsMatch(query, TestSetBuilder(1, 2))); | |
| 258 } | |
| 259 | |
| 260 | |
| 261 TEST_F(CoalescedLiveRangesTest, DeleteConflictManyOverlapsBefore) { | |
| 262 LiveRange* range = TestRangeBuilder(zone()).Id(1)(1, 5)(6, 10)(10, 20); | |
| 263 ranges().AllocateRange(range); | |
| 264 range = TestRangeBuilder(zone()).Id(2)(40, 50); | |
| 265 ranges().AllocateRange(range); | |
| 266 LiveRange* query = TestRangeBuilder(zone()).Id(3)(4, 15); | |
| 267 RemoveConflicts(query); | |
| 268 query = TestRangeBuilder(zone()).Id(4)(0, 60); | |
| 269 ASSERT_TRUE(CheckConflictsMatch(query, TestSetBuilder(1, 2))); | |
| 270 } | |
| 271 | |
| 272 | |
| 273 } // namespace compiler | |
| 274 } // namespace internal | |
| 275 } // namespace v8 | |
| OLD | NEW |