| Index: runtime/vm/intermediate_language.h
|
| diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
|
| index d6bb77b5201ee8bca016a7ecd9c6eeadb1c85a01..03af68a6fbeea719ac55e6f885d6a06038e95fe4 100644
|
| --- a/runtime/vm/intermediate_language.h
|
| +++ b/runtime/vm/intermediate_language.h
|
| @@ -2511,24 +2511,33 @@ class RangeBoundary : public ValueObject {
|
| return *this;
|
| }
|
|
|
| + static const intptr_t kMin = kIntptrMin;
|
| + static const intptr_t kMax = kIntptrMax;
|
| +
|
| + // Construct a RangeBoundary for a constant value.
|
| static RangeBoundary FromConstant(intptr_t val) {
|
| return RangeBoundary(kConstant, val, 0);
|
| }
|
|
|
| + // Construct a RangeBoundary for -inf.
|
| static RangeBoundary NegativeInfinity() {
|
| return RangeBoundary(kNegativeInfinity, 0, 0);
|
| }
|
|
|
| + // Construct a RangeBoundary for +inf.
|
| static RangeBoundary PositiveInfinity() {
|
| return RangeBoundary(kPositiveInfinity, 0, 0);
|
| }
|
|
|
| + // Construct a RangeBoundary from a definition and offset.
|
| static RangeBoundary FromDefinition(Definition* defn, intptr_t offs = 0);
|
|
|
| + // Construct a RangeBoundary for the constant MinSmi value.
|
| static RangeBoundary MinSmi() {
|
| return FromConstant(Smi::kMinValue);
|
| }
|
|
|
| + // Construct a RangeBoundary for the constant MaxSmi value.
|
| static RangeBoundary MaxSmi() {
|
| return FromConstant(Smi::kMaxValue);
|
| }
|
| @@ -2537,23 +2546,34 @@ class RangeBoundary : public ValueObject {
|
|
|
| static RangeBoundary Max(RangeBoundary a, RangeBoundary b);
|
|
|
| + // Returns true when this is a constant that is outside of range or is +/-inf.
|
| bool Overflowed() const {
|
| - // If the value is a constant outside of Smi range or infinity.
|
| - return (IsConstant() && !Smi::IsValid(value())) || IsInfinity();
|
| + // TODO(johnmccutchan): Support overflow testing to non-smi ranges.
|
| + return (IsConstant() && !Smi::IsValid(ConstantValue())) || IsInfinity();
|
| }
|
|
|
| + // Clamps this into a representable constant or symbol RangeBoundary.
|
| + // +/- infinity are clamped to MinSmi/MaxSmi.
|
| RangeBoundary Clamp() const {
|
| + // TODO(johnmccutchan): Support clamping to non-smi ranges.
|
| if (IsNegativeInfinity()) {
|
| return MinSmi();
|
| - } else if (IsPositiveInfinity()) {
|
| + }
|
| + if (IsPositiveInfinity()) {
|
| return MaxSmi();
|
| - } else if (IsConstant()) {
|
| - if (value() < Smi::kMinValue) return MinSmi();
|
| - if (value() > Smi::kMaxValue) return MaxSmi();
|
| + }
|
| + if (IsConstant()) {
|
| + if (ConstantValue() < Smi::kMinValue) return MinSmi();
|
| + if (ConstantValue() > Smi::kMaxValue) return MaxSmi();
|
| }
|
| return *this;
|
| }
|
|
|
| + intptr_t kind() const {
|
| + return kind_;
|
| + }
|
| +
|
| + // Kind tests.
|
| bool IsUnknown() const { return kind_ == kUnknown; }
|
| bool IsConstant() const { return kind_ == kConstant; }
|
| bool IsSymbol() const { return kind_ == kSymbol; }
|
| @@ -2562,22 +2582,34 @@ class RangeBoundary : public ValueObject {
|
| bool IsInfinity() const {
|
| return IsNegativeInfinity() || IsPositiveInfinity();
|
| }
|
| -
|
| - intptr_t value() const {
|
| - ASSERT(IsConstant());
|
| - return value_;
|
| + bool IsConstantOrInfinity() const {
|
| + return IsConstant() || IsInfinity();
|
| }
|
|
|
| + // Returns the value of a kConstant RangeBoundary.
|
| + intptr_t ConstantValue() const;
|
| +
|
| + // Returns the Definition associated with a kSymbol RangeBoundary.
|
| Definition* symbol() const {
|
| ASSERT(IsSymbol());
|
| return reinterpret_cast<Definition*>(value_);
|
| }
|
|
|
| + // Offset from symbol.
|
| intptr_t offset() const {
|
| return offset_;
|
| }
|
|
|
| + // Computes the LowerBound of this. Three cases:
|
| + // IsInfinity() -> NegativeInfinity().
|
| + // IsConstant() -> value().
|
| + // IsSymbol() -> lower bound computed from definition + offset.
|
| RangeBoundary LowerBound() const;
|
| +
|
| + // Computes the UpperBound of this. Three cases:
|
| + // IsInfinity() -> PositiveInfinity().
|
| + // IsConstant() -> value().
|
| + // IsSymbol() -> upper bound computed from definition + offset.
|
| RangeBoundary UpperBound() const;
|
|
|
| void PrintTo(BufferFormatter* f) const;
|
| @@ -2585,27 +2617,30 @@ class RangeBoundary : public ValueObject {
|
|
|
| static RangeBoundary Add(const RangeBoundary& a,
|
| const RangeBoundary& b,
|
| - const RangeBoundary& overflow) {
|
| - ASSERT(a.IsConstant() && b.IsConstant());
|
| -
|
| - intptr_t result = a.value() + b.value();
|
| - if (!Smi::IsValid(result)) {
|
| - return overflow;
|
| - }
|
| - return RangeBoundary::FromConstant(result);
|
| - }
|
| + const RangeBoundary& overflow);
|
|
|
| static RangeBoundary Sub(const RangeBoundary& a,
|
| const RangeBoundary& b,
|
| - const RangeBoundary& overflow) {
|
| - ASSERT(a.IsConstant() && b.IsConstant());
|
| + const RangeBoundary& overflow);
|
| +
|
| + // Attempts to calculate a + b when:
|
| + // a is a symbol and b is a constant OR
|
| + // a is a constant and b is a symbol
|
| + // returns true if it succeeds, output is in result.
|
| + static bool SymbolicAdd(const RangeBoundary& a,
|
| + const RangeBoundary& b,
|
| + RangeBoundary* result);
|
| +
|
| + // Attempts to calculate a - b when:
|
| + // a is a symbol and b is a constant
|
| + // returns true if it succeeds, output is in result.
|
| + static bool SymbolicSub(const RangeBoundary& a,
|
| + const RangeBoundary& b,
|
| + RangeBoundary* result);
|
| +
|
| + bool Equals(const RangeBoundary& other) const;
|
| +
|
|
|
| - intptr_t result = a.value() - b.value();
|
| - if (!Smi::IsValid(result)) {
|
| - return overflow;
|
| - }
|
| - return RangeBoundary::FromConstant(result);
|
| - }
|
|
|
| private:
|
| RangeBoundary(Kind kind, intptr_t value, intptr_t offset)
|
| @@ -2654,6 +2689,9 @@ class Range : public ZoneAllocated {
|
| // [-inf, val].
|
| bool OnlyLessThanOrEqualTo(intptr_t val) const;
|
|
|
| + // [val, +inf].
|
| + bool OnlyGreaterThanOrEqualTo(intptr_t val) const;
|
| +
|
| // Inclusive.
|
| bool IsWithin(intptr_t min_int, intptr_t max_int) const;
|
|
|
| @@ -2662,6 +2700,28 @@ class Range : public ZoneAllocated {
|
|
|
| bool IsUnsatisfiable() const;
|
|
|
| + // Returns true if range is NULL or includes -inf.
|
| + static bool IncludesNegativeInfinity(const Range* range);
|
| +
|
| + // Returns true if range is NULL or includes +inf.
|
| + static bool IncludesPositiveInfinity(const Range* range);
|
| +
|
| + // Both the a and b ranges are >= 0.
|
| + static bool OnlyPositiveOrZero(const Range& a, const Range& b);
|
| +
|
| + // Both the a and b ranges are <= 0.
|
| + static bool OnlyNegativeOrZero(const Range& a, const Range& b);
|
| +
|
| + // Return the maximum absolute value included in range.
|
| + static int64_t ConstantAbsMax(const Range* range);
|
| +
|
| + static Range* BinaryOp(const Token::Kind op,
|
| + const RangeBoundary& left_min,
|
| + const RangeBoundary& left_max,
|
| + const Range* left_range,
|
| + const Range* right_range,
|
| + const Range* original_range);
|
| +
|
| private:
|
| RangeBoundary min_;
|
| RangeBoundary max_;
|
|
|