Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef VM_FLOW_GRAPH_RANGE_ANALYSIS_H_ | 5 #ifndef VM_FLOW_GRAPH_RANGE_ANALYSIS_H_ |
| 6 #define VM_FLOW_GRAPH_RANGE_ANALYSIS_H_ | 6 #define VM_FLOW_GRAPH_RANGE_ANALYSIS_H_ |
| 7 | 7 |
| 8 #include "vm/flow_graph.h" | 8 #include "vm/flow_graph.h" |
| 9 #include "vm/intermediate_language.h" | 9 #include "vm/intermediate_language.h" |
| 10 | 10 |
| 11 namespace dart { | 11 namespace dart { |
| 12 | 12 |
| 13 class RangeBoundary : public ValueObject { | 13 class RangeBoundary : public ValueObject { |
| 14 public: | 14 public: |
| 15 enum Kind { | 15 enum Kind { |
| 16 kUnknown, | 16 kUnknown, |
| 17 kNegativeInfinity, | 17 kNegativeInfinity, |
| 18 kPositiveInfinity, | 18 kPositiveInfinity, |
| 19 kSymbol, | 19 kSymbol, |
| 20 kConstant, | 20 kConstant, |
| 21 }; | 21 }; |
| 22 | 22 |
| 23 enum RangeSize { | 23 enum RangeSize { |
| 24 kRangeBoundarySmi, | 24 kRangeBoundarySmi, |
| 25 kRangeBoundaryInt32, | |
| 25 kRangeBoundaryInt64, | 26 kRangeBoundaryInt64, |
| 26 }; | 27 }; |
| 27 | 28 |
| 28 RangeBoundary() : kind_(kUnknown), value_(0), offset_(0) { } | 29 RangeBoundary() : kind_(kUnknown), value_(0), offset_(0) { } |
| 29 | 30 |
| 30 RangeBoundary(const RangeBoundary& other) | 31 RangeBoundary(const RangeBoundary& other) |
| 31 : ValueObject(), | 32 : ValueObject(), |
| 32 kind_(other.kind_), | 33 kind_(other.kind_), |
| 33 value_(other.value_), | 34 value_(other.value_), |
| 34 offset_(other.offset_) { } | 35 offset_(other.offset_) { } |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 67 // Construct a RangeBoundary for the constant MinSmi value. | 68 // Construct a RangeBoundary for the constant MinSmi value. |
| 68 static RangeBoundary MinSmi() { | 69 static RangeBoundary MinSmi() { |
| 69 return FromConstant(Smi::kMinValue); | 70 return FromConstant(Smi::kMinValue); |
| 70 } | 71 } |
| 71 | 72 |
| 72 // Construct a RangeBoundary for the constant MaxSmi value. | 73 // Construct a RangeBoundary for the constant MaxSmi value. |
| 73 static RangeBoundary MaxSmi() { | 74 static RangeBoundary MaxSmi() { |
| 74 return FromConstant(Smi::kMaxValue); | 75 return FromConstant(Smi::kMaxValue); |
| 75 } | 76 } |
| 76 | 77 |
| 77 // Construct a RangeBoundary for the constant kMin value. | 78 // Construct a RangeBoundary for the constant kMin value. |
| 78 static RangeBoundary MinConstant() { | 79 static RangeBoundary MinConstant() { |
| 79 return FromConstant(kMin); | 80 return FromConstant(kMin); |
| 80 } | 81 } |
| 81 | 82 |
| 82 // Construct a RangeBoundary for the constant kMax value. | 83 // Construct a RangeBoundary for the constant kMax value. |
| 83 static RangeBoundary MaxConstant() { | 84 static RangeBoundary MaxConstant() { |
| 84 return FromConstant(kMax); | 85 return FromConstant(kMax); |
| 85 } | 86 } |
| 86 | 87 |
| 88 // Construct a RangeBoundary for the constant kMin value. | |
| 89 static RangeBoundary MinConstant(RangeSize size) { | |
| 90 switch (size) { | |
| 91 case kRangeBoundarySmi: | |
| 92 return FromConstant(Smi::kMinValue); | |
| 93 case kRangeBoundaryInt32: | |
| 94 return FromConstant(kMinInt32); | |
| 95 case kRangeBoundaryInt64: | |
| 96 return FromConstant(kMinInt64); | |
| 97 } | |
| 98 UNREACHABLE(); | |
| 99 return FromConstant(kMinInt64); | |
| 100 } | |
| 101 | |
| 102 static RangeBoundary MaxConstant(RangeSize size) { | |
| 103 switch (size) { | |
| 104 case kRangeBoundarySmi: | |
| 105 return FromConstant(Smi::kMaxValue); | |
| 106 case kRangeBoundaryInt32: | |
| 107 return FromConstant(kMaxInt32); | |
| 108 case kRangeBoundaryInt64: | |
| 109 return FromConstant(kMaxInt64); | |
| 110 } | |
| 111 UNREACHABLE(); | |
| 112 return FromConstant(kMaxInt64); | |
| 113 } | |
| 114 | |
| 115 | |
| 87 // Given two boundaries a and b, select one of them as c so that | 116 // Given two boundaries a and b, select one of them as c so that |
| 88 // | 117 // |
| 89 // inf {[a, ...) ^ [b, ...)} >= inf {c} | 118 // inf {[a, ...) ^ [b, ...)} >= inf {c} |
| 90 // | 119 // |
| 91 static RangeBoundary IntersectionMin(RangeBoundary a, RangeBoundary b); | 120 static RangeBoundary IntersectionMin(RangeBoundary a, RangeBoundary b); |
| 92 | 121 |
| 93 // Given two boundaries a and b, select one of them as c so that | 122 // Given two boundaries a and b, select one of them as c so that |
| 94 // | 123 // |
| 95 // sup {(..., a] ^ (..., b]} <= sup {c} | 124 // sup {(..., a] ^ (..., b]} <= sup {c} |
| 96 // | 125 // |
| 97 static RangeBoundary IntersectionMax(RangeBoundary a, RangeBoundary b); | 126 static RangeBoundary IntersectionMax(RangeBoundary a, RangeBoundary b); |
| 98 | 127 |
| 99 // Given two boundaries a and b compute boundary c such that | 128 // Given two boundaries a and b compute boundary c such that |
| 100 // | 129 // |
| 101 // inf {[a, ...) U [b, ...)} >= inf {c} | 130 // inf {[a, ...) U [b, ...)} >= inf {c} |
| 102 // | 131 // |
| 103 // Try to select c such that it is as close to inf {[a, ...) U [b, ...)} | 132 // Try to select c such that it is as close to inf {[a, ...) U [b, ...)} |
| 104 // as possible. | 133 // as possible. |
| 105 static RangeBoundary JoinMin(RangeBoundary a, RangeBoundary b); | 134 static RangeBoundary JoinMin(RangeBoundary a, |
| 135 RangeBoundary b, | |
| 136 RangeBoundary::RangeSize size); | |
| 106 | 137 |
| 107 // Given two boundaries a and b compute boundary c such that | 138 // Given two boundaries a and b compute boundary c such that |
| 108 // | 139 // |
| 109 // sup {(..., a] U (..., b]} <= sup {c} | 140 // sup {(..., a] U (..., b]} <= sup {c} |
| 110 // | 141 // |
| 111 // Try to select c such that it is as close to sup {(..., a] U (..., b]} | 142 // Try to select c such that it is as close to sup {(..., a] U (..., b]} |
| 112 // as possible. | 143 // as possible. |
| 113 static RangeBoundary JoinMax(RangeBoundary a, RangeBoundary b); | 144 static RangeBoundary JoinMax(RangeBoundary a, |
| 145 RangeBoundary b, | |
| 146 RangeBoundary::RangeSize size); | |
| 114 | 147 |
| 115 // Returns true when this is a constant that is outside of Smi range. | 148 // Returns true when this is a constant that is outside of Smi range. |
| 116 bool OverflowedSmi() const { | 149 bool OverflowedSmi() const { |
| 117 return (IsConstant() && !Smi::IsValid(ConstantValue())) || IsInfinity(); | 150 return (IsConstant() && !Smi::IsValid(ConstantValue())) || IsInfinity(); |
| 118 } | 151 } |
| 119 | 152 |
| 153 bool Overflowed(RangeBoundary::RangeSize size) const { | |
| 154 ASSERT(IsConstantOrInfinity()); | |
| 155 return !Equals(Clamp(size)); | |
| 156 } | |
| 157 | |
| 120 // Returns true if this outside mint range. | 158 // Returns true if this outside mint range. |
| 121 bool OverflowedMint() const { | 159 bool OverflowedMint() const { |
| 122 return IsInfinity(); | 160 return IsInfinity(); |
| 123 } | 161 } |
| 124 | 162 |
| 125 // -/+ infinity are clamped to MinConstant/MaxConstant of the given type. | 163 // -/+ infinity are clamped to MinConstant/MaxConstant of the given type. |
| 126 RangeBoundary Clamp(RangeSize size) const { | 164 RangeBoundary Clamp(RangeSize size) const { |
| 127 if (IsNegativeInfinity()) { | 165 if (IsNegativeInfinity()) { |
| 128 return (size == kRangeBoundaryInt64) ? MinConstant() : MinSmi(); | 166 return RangeBoundary::MinConstant(size); |
| 129 } | 167 } |
| 168 | |
| 130 if (IsPositiveInfinity()) { | 169 if (IsPositiveInfinity()) { |
| 131 return (size == kRangeBoundaryInt64) ? MaxConstant() : MaxSmi(); | 170 return RangeBoundary::MaxConstant(size); |
| 132 } | 171 } |
| 133 if ((size == kRangeBoundarySmi) && IsConstant()) { | 172 |
| 134 if (ConstantValue() <= Smi::kMinValue) { | 173 if (IsConstant()) { |
| 135 return MinSmi(); | 174 const RangeBoundary range_min = RangeBoundary::MinConstant(size); |
| 175 const RangeBoundary range_max = RangeBoundary::MaxConstant(size); | |
| 176 | |
| 177 if (ConstantValue() <= range_min.ConstantValue()) { | |
| 178 return range_min; | |
| 136 } | 179 } |
| 137 if (ConstantValue() >= Smi::kMaxValue) { | 180 if (ConstantValue() >= range_max.ConstantValue()) { |
| 138 return MaxSmi(); | 181 return range_max; |
| 139 } | 182 } |
| 140 } | 183 } |
| 184 | |
| 141 // If this range is a symbolic range, we do not clamp it. | 185 // If this range is a symbolic range, we do not clamp it. |
| 142 // This could lead to some imprecision later on. | 186 // This could lead to some imprecision later on. |
| 143 return *this; | 187 return *this; |
| 144 } | 188 } |
| 145 | 189 |
| 146 bool IsSmiMinimumOrBelow() const { | 190 bool IsMinimumOrBelow(RangeSize size) const { |
| 147 return IsNegativeInfinity() || | 191 return IsNegativeInfinity() || |
| 148 (IsConstant() && (ConstantValue() <= Smi::kMinValue)); | 192 (IsConstant() && |
| 193 (ConstantValue() <= RangeBoundary::MinConstant(size).ConstantValue())); | |
| 149 } | 194 } |
| 150 | 195 |
| 151 bool IsSmiMaximumOrAbove() const { | 196 bool IsMaximumOrAbove(RangeSize size) const { |
| 152 return IsPositiveInfinity() || | 197 return IsPositiveInfinity() || |
| 153 (IsConstant() && (ConstantValue() >= Smi::kMaxValue)); | 198 (IsConstant() && |
| 154 } | 199 (ConstantValue() >= RangeBoundary::MaxConstant(size).ConstantValue())); |
| 155 | |
| 156 bool IsMinimumOrBelow() const { | |
| 157 return IsNegativeInfinity() || (IsConstant() && (ConstantValue() == kMin)); | |
| 158 } | |
| 159 | |
| 160 bool IsMaximumOrAbove() const { | |
| 161 return IsPositiveInfinity() || (IsConstant() && (ConstantValue() == kMax)); | |
| 162 } | 200 } |
| 163 | 201 |
| 164 intptr_t kind() const { | 202 intptr_t kind() const { |
| 165 return kind_; | 203 return kind_; |
| 166 } | 204 } |
| 167 | 205 |
| 168 // Kind tests. | 206 // Kind tests. |
| 169 bool IsUnknown() const { return kind_ == kUnknown; } | 207 bool IsUnknown() const { return kind_ == kUnknown; } |
| 170 bool IsConstant() const { return kind_ == kConstant; } | 208 bool IsConstant() const { return kind_ == kConstant; } |
| 171 bool IsSymbol() const { return kind_ == kSymbol; } | 209 bool IsSymbol() const { return kind_ == kSymbol; } |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 238 | 276 |
| 239 // Attempts to calculate a - b when: | 277 // Attempts to calculate a - b when: |
| 240 // a is a symbol and b is a constant | 278 // a is a symbol and b is a constant |
| 241 // returns true if it succeeds, output is in result. | 279 // returns true if it succeeds, output is in result. |
| 242 static bool SymbolicSub(const RangeBoundary& a, | 280 static bool SymbolicSub(const RangeBoundary& a, |
| 243 const RangeBoundary& b, | 281 const RangeBoundary& b, |
| 244 RangeBoundary* result); | 282 RangeBoundary* result); |
| 245 | 283 |
| 246 bool Equals(const RangeBoundary& other) const; | 284 bool Equals(const RangeBoundary& other) const; |
| 247 | 285 |
| 286 int64_t UpperBound(RangeSize size) const { | |
| 287 return UpperBound().Clamp(size).ConstantValue(); | |
| 288 } | |
| 289 | |
| 290 int64_t LowerBound(RangeSize size) const { | |
| 291 return LowerBound().Clamp(size).ConstantValue(); | |
| 292 } | |
| 293 | |
| 248 int64_t SmiUpperBound() const { | 294 int64_t SmiUpperBound() const { |
| 249 return UpperBound().Clamp(kRangeBoundarySmi).ConstantValue(); | 295 return UpperBound(kRangeBoundarySmi); |
| 250 } | 296 } |
| 251 | 297 |
| 252 int64_t SmiLowerBound() const { | 298 int64_t SmiLowerBound() const { |
| 253 return LowerBound().Clamp(kRangeBoundarySmi).ConstantValue(); | 299 return LowerBound(kRangeBoundarySmi); |
| 254 } | 300 } |
| 255 | 301 |
| 256 private: | 302 private: |
| 257 RangeBoundary(Kind kind, int64_t value, int64_t offset) | 303 RangeBoundary(Kind kind, int64_t value, int64_t offset) |
| 258 : kind_(kind), value_(value), offset_(offset) { } | 304 : kind_(kind), value_(value), offset_(offset) { } |
| 259 | 305 |
| 260 Kind kind_; | 306 Kind kind_; |
| 261 int64_t value_; | 307 int64_t value_; |
| 262 int64_t offset_; | 308 int64_t offset_; |
| 263 }; | 309 }; |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 283 } | 329 } |
| 284 | 330 |
| 285 static bool IsUnknown(const Range* other) { | 331 static bool IsUnknown(const Range* other) { |
| 286 if (other == NULL) { | 332 if (other == NULL) { |
| 287 return true; | 333 return true; |
| 288 } | 334 } |
| 289 return other->min().IsUnknown(); | 335 return other->min().IsUnknown(); |
| 290 } | 336 } |
| 291 | 337 |
| 292 static Range Full(RangeBoundary::RangeSize size) { | 338 static Range Full(RangeBoundary::RangeSize size) { |
| 293 if (size == RangeBoundary::kRangeBoundarySmi) { | 339 return Range(RangeBoundary::MinConstant(size), |
| 294 return Range(RangeBoundary::MinSmi(), RangeBoundary::MaxSmi()); | 340 RangeBoundary::MaxConstant(size)); |
| 295 } else { | |
| 296 ASSERT(size == RangeBoundary::kRangeBoundaryInt64); | |
| 297 return Range(RangeBoundary::MinConstant(), RangeBoundary::MaxConstant()); | |
| 298 } | |
| 299 } | 341 } |
| 300 | 342 |
| 301 void PrintTo(BufferFormatter* f) const; | 343 void PrintTo(BufferFormatter* f) const; |
| 302 static const char* ToCString(const Range* range); | 344 static const char* ToCString(const Range* range); |
| 303 | 345 |
| 304 bool Equals(const Range* other) { | 346 bool Equals(const Range* other) { |
| 305 ASSERT(min_.IsUnknown() == max_.IsUnknown()); | 347 ASSERT(min_.IsUnknown() == max_.IsUnknown()); |
| 306 if (other == NULL) { | 348 if (other == NULL) { |
| 307 return min_.IsUnknown(); | 349 return min_.IsUnknown(); |
| 308 } | 350 } |
| 309 return min_.Equals(other->min_) && | 351 return min_.Equals(other->min_) && |
| 310 max_.Equals(other->max_); | 352 max_.Equals(other->max_); |
| 311 } | 353 } |
| 312 | 354 |
| 313 const RangeBoundary& min() const { return min_; } | 355 const RangeBoundary& min() const { return min_; } |
| 314 const RangeBoundary& max() const { return max_; } | 356 const RangeBoundary& max() const { return max_; } |
| 315 void set_min(const RangeBoundary& value) { | 357 void set_min(const RangeBoundary& value) { |
| 316 min_ = value; | 358 min_ = value; |
| 317 } | 359 } |
| 318 void set_max(const RangeBoundary& value) { | 360 void set_max(const RangeBoundary& value) { |
| 319 max_ = value; | 361 max_ = value; |
| 320 } | 362 } |
| 321 | 363 |
| 322 static RangeBoundary ConstantMinSmi(const Range* range) { | 364 static RangeBoundary ConstantMinSmi(const Range* range) { |
| 323 if (range == NULL) { | 365 return ConstantMin(range, RangeBoundary::kRangeBoundarySmi); |
| 324 return RangeBoundary::MinSmi(); | |
| 325 } | |
| 326 return range->min().LowerBound().Clamp(RangeBoundary::kRangeBoundarySmi); | |
| 327 } | 366 } |
| 328 | 367 |
| 329 static RangeBoundary ConstantMaxSmi(const Range* range) { | 368 static RangeBoundary ConstantMaxSmi(const Range* range) { |
| 330 if (range == NULL) { | 369 return ConstantMax(range, RangeBoundary::kRangeBoundarySmi); |
| 331 return RangeBoundary::MaxSmi(); | |
| 332 } | |
| 333 return range->max().UpperBound().Clamp(RangeBoundary::kRangeBoundarySmi); | |
| 334 } | 370 } |
| 335 | 371 |
| 336 static RangeBoundary ConstantMin(const Range* range) { | 372 static RangeBoundary ConstantMin(const Range* range) { |
| 337 if (range == NULL) { | 373 return ConstantMin(range, RangeBoundary::kRangeBoundaryInt64); |
| 338 return RangeBoundary::MinConstant(); | |
| 339 } | |
| 340 return range->min().LowerBound().Clamp(RangeBoundary::kRangeBoundaryInt64); | |
| 341 } | 374 } |
| 342 | 375 |
| 343 static RangeBoundary ConstantMax(const Range* range) { | 376 static RangeBoundary ConstantMax(const Range* range) { |
| 377 return ConstantMax(range, RangeBoundary::kRangeBoundaryInt64); | |
| 378 } | |
| 379 | |
| 380 static RangeBoundary ConstantMin(const Range* range, | |
| 381 RangeBoundary::RangeSize size) { | |
| 344 if (range == NULL) { | 382 if (range == NULL) { |
| 345 return RangeBoundary::MaxConstant(); | 383 return RangeBoundary::MinConstant(size); |
| 346 } | 384 } |
| 347 return range->max().UpperBound().Clamp(RangeBoundary::kRangeBoundaryInt64); | 385 return range->min().LowerBound().Clamp(size); |
| 348 } | 386 } |
| 349 | 387 |
| 388 static RangeBoundary ConstantMax(const Range* range, | |
| 389 RangeBoundary::RangeSize size) { | |
| 390 if (range == NULL) { | |
| 391 return RangeBoundary::MaxConstant(size); | |
| 392 } | |
| 393 return range->max().UpperBound().Clamp(size); | |
| 394 } | |
| 395 | |
| 396 | |
| 350 // [0, +inf] | 397 // [0, +inf] |
| 351 bool IsPositive() const; | 398 bool IsPositive() const; |
| 352 | 399 |
| 353 // [-inf, val]. | 400 // [-inf, val]. |
| 354 bool OnlyLessThanOrEqualTo(int64_t val) const; | 401 bool OnlyLessThanOrEqualTo(int64_t val) const; |
| 355 | 402 |
| 356 // [val, +inf]. | 403 // [val, +inf]. |
| 357 bool OnlyGreaterThanOrEqualTo(int64_t val) const; | 404 bool OnlyGreaterThanOrEqualTo(int64_t val) const; |
| 358 | 405 |
| 359 // Inclusive. | 406 // Inclusive. |
| 360 bool IsWithin(int64_t min_int, int64_t max_int) const; | 407 bool IsWithin(int64_t min_int, int64_t max_int) const; |
| 361 | 408 |
| 362 // Inclusive. | 409 // Inclusive. |
| 363 bool Overlaps(int64_t min_int, int64_t max_int) const; | 410 bool Overlaps(int64_t min_int, int64_t max_int) const; |
| 364 | 411 |
| 365 bool IsUnsatisfiable() const; | 412 bool IsUnsatisfiable() const; |
| 366 | 413 |
| 367 bool IsFinite() const { | 414 bool IsFinite() const { |
| 368 return !min_.IsInfinity() && !max_.IsInfinity(); | 415 return !min_.IsInfinity() && !max_.IsInfinity(); |
| 369 } | 416 } |
| 370 | 417 |
| 371 Range Intersect(const Range* other) const { | 418 Range Intersect(const Range* other) const { |
| 372 return Range(RangeBoundary::IntersectionMin(min(), other->min()), | 419 return Range(RangeBoundary::IntersectionMin(min(), other->min()), |
| 373 RangeBoundary::IntersectionMax(max(), other->max())); | 420 RangeBoundary::IntersectionMax(max(), other->max())); |
| 374 } | 421 } |
| 375 | 422 |
| 423 bool Fits(RangeBoundary::RangeSize size) const { | |
| 424 return !min().LowerBound().Overflowed(size) && | |
| 425 !max().UpperBound().Overflowed(size); | |
| 426 } | |
| 427 | |
| 428 static bool Fits(Range* range, RangeBoundary::RangeSize size) { | |
| 429 return !IsUnknown(range) && range->Fits(size); | |
| 430 } | |
|
srdjan
2014/08/27 16:17:13
I think it is confusing to have a non-static and s
Vyacheslav Egorov (Google)
2014/08/28 20:48:37
Agreed. Moved into a separate AllStatic helper cla
| |
| 431 | |
| 376 // Clamp this to be within size. | 432 // Clamp this to be within size. |
| 377 void Clamp(RangeBoundary::RangeSize size); | 433 void Clamp(RangeBoundary::RangeSize size); |
| 378 | 434 |
| 379 static void Add(const Range* left_range, | 435 static void Add(const Range* left_range, |
| 380 const Range* right_range, | 436 const Range* right_range, |
| 381 RangeBoundary* min, | 437 RangeBoundary* min, |
| 382 RangeBoundary* max, | 438 RangeBoundary* max, |
| 383 Definition* left_defn); | 439 Definition* left_defn); |
| 384 | 440 |
| 385 static void Sub(const Range* left_range, | 441 static void Sub(const Range* left_range, |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 496 void Iterate(JoinOperator op, intptr_t max_iterations); | 552 void Iterate(JoinOperator op, intptr_t max_iterations); |
| 497 bool InferRange(JoinOperator op, Definition* defn, intptr_t iteration); | 553 bool InferRange(JoinOperator op, Definition* defn, intptr_t iteration); |
| 498 | 554 |
| 499 // Based on computed ranges find and eliminate redundant CheckArrayBound | 555 // Based on computed ranges find and eliminate redundant CheckArrayBound |
| 500 // instructions. | 556 // instructions. |
| 501 void EliminateRedundantBoundsChecks(); | 557 void EliminateRedundantBoundsChecks(); |
| 502 | 558 |
| 503 // Find unsatisfiable constraints and mark corresponding blocks unreachable. | 559 // Find unsatisfiable constraints and mark corresponding blocks unreachable. |
| 504 void MarkUnreachableBlocks(); | 560 void MarkUnreachableBlocks(); |
| 505 | 561 |
| 562 // Convert mint operations that stay within int32 range into Int32 operations. | |
| 563 void NarrowMintToInt32(); | |
| 564 | |
| 506 // Remove artificial Constraint instructions and replace them with actual | 565 // Remove artificial Constraint instructions and replace them with actual |
| 507 // unconstrained definitions. | 566 // unconstrained definitions. |
| 508 void RemoveConstraints(); | 567 void RemoveConstraints(); |
| 509 | 568 |
| 510 Range* ConstraintSmiRange(Token::Kind op, Definition* boundary); | 569 Range* ConstraintSmiRange(Token::Kind op, Definition* boundary); |
| 511 | 570 |
| 512 Isolate* isolate() const { return flow_graph_->isolate(); } | 571 Isolate* isolate() const { return flow_graph_->isolate(); } |
| 513 | 572 |
| 514 FlowGraph* flow_graph_; | 573 FlowGraph* flow_graph_; |
| 515 | 574 |
| 516 // Range object representing full Smi range. | 575 // Range object representing full Smi range. |
| 517 Range smi_range_; | 576 Range smi_range_; |
| 518 | 577 |
| 519 // Value that are known to be smi or mint. | 578 // Value that are known to be smi or mint. |
| 520 GrowableArray<Definition*> values_; | 579 GrowableArray<Definition*> values_; |
| 521 | 580 |
| 581 GrowableArray<BinaryMintOpInstr*> binary_mint_ops_; | |
| 582 | |
| 583 GrowableArray<ShiftMintOpInstr*> shift_mint_ops_; | |
| 584 | |
| 522 // All CheckArrayBound instructions. | 585 // All CheckArrayBound instructions. |
| 523 GrowableArray<CheckArrayBoundInstr*> bounds_checks_; | 586 GrowableArray<CheckArrayBoundInstr*> bounds_checks_; |
| 524 | 587 |
| 525 // All Constraints inserted during InsertConstraints phase. They are treated | 588 // All Constraints inserted during InsertConstraints phase. They are treated |
| 526 // as smi values. | 589 // as smi values. |
| 527 GrowableArray<ConstraintInstr*> constraints_; | 590 GrowableArray<ConstraintInstr*> constraints_; |
| 528 | 591 |
| 529 // List of integer (smi or mint) definitions including constraints sorted | 592 // List of integer (smi or mint) definitions including constraints sorted |
| 530 // in the reverse postorder. | 593 // in the reverse postorder. |
| 531 GrowableArray<Definition*> definitions_; | 594 GrowableArray<Definition*> definitions_; |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 559 BitVector* selected_uint32_defs_; | 622 BitVector* selected_uint32_defs_; |
| 560 | 623 |
| 561 FlowGraph* flow_graph_; | 624 FlowGraph* flow_graph_; |
| 562 Isolate* isolate_; | 625 Isolate* isolate_; |
| 563 }; | 626 }; |
| 564 | 627 |
| 565 | 628 |
| 566 } // namespace dart | 629 } // namespace dart |
| 567 | 630 |
| 568 #endif // VM_FLOW_GRAPH_RANGE_ANALYSIS_H_ | 631 #endif // VM_FLOW_GRAPH_RANGE_ANALYSIS_H_ |
| OLD | NEW |