| Index: runtime/vm/intermediate_language.h
|
| diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
|
| index 55bc22dbaa53eaeef9e6570542651af0082f066c..ade44987abd93e71d387f04818370616e70df53e 100644
|
| --- a/runtime/vm/intermediate_language.h
|
| +++ b/runtime/vm/intermediate_language.h
|
| @@ -32,6 +32,7 @@ class Instruction;
|
| class LocalVariable;
|
| class ParsedFunction;
|
| class Range;
|
| +class RangeBoundary;
|
|
|
|
|
| // TODO(srdjan): Unify with INTRINSIC_LIST.
|
| @@ -2563,352 +2564,6 @@ class RedefinitionInstr : public TemplateDefinition<1> {
|
| };
|
|
|
|
|
| -class RangeBoundary : public ValueObject {
|
| - public:
|
| - enum Kind {
|
| - kUnknown,
|
| - kNegativeInfinity,
|
| - kPositiveInfinity,
|
| - kSymbol,
|
| - kConstant,
|
| - };
|
| -
|
| - enum RangeSize {
|
| - kRangeBoundarySmi,
|
| - kRangeBoundaryInt64,
|
| - };
|
| -
|
| - RangeBoundary() : kind_(kUnknown), value_(0), offset_(0) { }
|
| -
|
| - RangeBoundary(const RangeBoundary& other)
|
| - : ValueObject(),
|
| - kind_(other.kind_),
|
| - value_(other.value_),
|
| - offset_(other.offset_) { }
|
| -
|
| - explicit RangeBoundary(int64_t val)
|
| - : kind_(kConstant), value_(val), offset_(0) { }
|
| -
|
| - RangeBoundary& operator=(const RangeBoundary& other) {
|
| - kind_ = other.kind_;
|
| - value_ = other.value_;
|
| - offset_ = other.offset_;
|
| - return *this;
|
| - }
|
| -
|
| - static const int64_t kMin = kMinInt64;
|
| - static const int64_t kMax = kMaxInt64;
|
| -
|
| - // Construct a RangeBoundary for a constant value.
|
| - static RangeBoundary FromConstant(int64_t val) {
|
| - return RangeBoundary(val);
|
| - }
|
| -
|
| - // 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, int64_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);
|
| - }
|
| -
|
| - // Construct a RangeBoundary for the constant kMin value.
|
| - static RangeBoundary MinConstant() {
|
| - return FromConstant(kMin);
|
| - }
|
| -
|
| - // Construct a RangeBoundary for the constant kMax value.
|
| - static RangeBoundary MaxConstant() {
|
| - return FromConstant(kMax);
|
| - }
|
| -
|
| - // Calculate the minimum of a and b within the given range.
|
| - static RangeBoundary Min(RangeBoundary a, RangeBoundary b, RangeSize size);
|
| - static RangeBoundary Max(RangeBoundary a, RangeBoundary b, RangeSize size);
|
| -
|
| - // Returns true when this is a constant that is outside of Smi range.
|
| - bool OverflowedSmi() const {
|
| - return (IsConstant() && !Smi::IsValid(ConstantValue())) || IsInfinity();
|
| - }
|
| -
|
| - // Returns true if this outside mint range.
|
| - bool OverflowedMint() const {
|
| - return IsInfinity();
|
| - }
|
| -
|
| - // -/+ infinity are clamped to MinConstant/MaxConstant of the given type.
|
| - RangeBoundary Clamp(RangeSize size) const {
|
| - if (IsNegativeInfinity()) {
|
| - return (size == kRangeBoundaryInt64) ? MinConstant() : MinSmi();
|
| - }
|
| - if (IsPositiveInfinity()) {
|
| - return (size == kRangeBoundaryInt64) ? MaxConstant() : MaxSmi();
|
| - }
|
| - if ((size == kRangeBoundarySmi) && IsConstant()) {
|
| - if (ConstantValue() <= Smi::kMinValue) {
|
| - return MinSmi();
|
| - }
|
| - if (ConstantValue() >= Smi::kMaxValue) {
|
| - return MaxSmi();
|
| - }
|
| - }
|
| - // If this range is a symbolic range, we do not clamp it.
|
| - // This could lead to some imprecision later on.
|
| - return *this;
|
| - }
|
| -
|
| -
|
| - bool IsSmiMinimumOrBelow() const {
|
| - return IsNegativeInfinity() ||
|
| - (IsConstant() && (ConstantValue() <= Smi::kMinValue));
|
| - }
|
| -
|
| - bool IsSmiMaximumOrAbove() const {
|
| - return IsPositiveInfinity() ||
|
| - (IsConstant() && (ConstantValue() >= Smi::kMaxValue));
|
| - }
|
| -
|
| - bool IsMinimumOrBelow() const {
|
| - return IsNegativeInfinity() || (IsConstant() && (ConstantValue() == kMin));
|
| - }
|
| -
|
| - bool IsMaximumOrAbove() const {
|
| - return IsPositiveInfinity() || (IsConstant() && (ConstantValue() == kMax));
|
| - }
|
| -
|
| - 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; }
|
| - bool IsNegativeInfinity() const { return kind_ == kNegativeInfinity; }
|
| - bool IsPositiveInfinity() const { return kind_ == kPositiveInfinity; }
|
| - bool IsInfinity() const {
|
| - return IsNegativeInfinity() || IsPositiveInfinity();
|
| - }
|
| - bool IsConstantOrInfinity() const {
|
| - return IsConstant() || IsInfinity();
|
| - }
|
| -
|
| - // Returns the value of a kConstant RangeBoundary.
|
| - int64_t ConstantValue() const;
|
| -
|
| - // Returns the Definition associated with a kSymbol RangeBoundary.
|
| - Definition* symbol() const {
|
| - ASSERT(IsSymbol());
|
| - return reinterpret_cast<Definition*>(value_);
|
| - }
|
| -
|
| - // Offset from symbol.
|
| - int64_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;
|
| - const char* ToCString() const;
|
| -
|
| - static RangeBoundary Add(const RangeBoundary& a,
|
| - const RangeBoundary& b,
|
| - const RangeBoundary& overflow);
|
| -
|
| - static RangeBoundary Sub(const RangeBoundary& a,
|
| - const RangeBoundary& b,
|
| - const RangeBoundary& overflow);
|
| -
|
| - static RangeBoundary Shl(const RangeBoundary& value_boundary,
|
| - int64_t shift_count,
|
| - const RangeBoundary& overflow);
|
| -
|
| - static RangeBoundary Shr(const RangeBoundary& value_boundary,
|
| - int64_t shift_count) {
|
| - ASSERT(value_boundary.IsConstant());
|
| - ASSERT(shift_count >= 0);
|
| - int64_t value = static_cast<int64_t>(value_boundary.ConstantValue());
|
| - int64_t result = value >> shift_count;
|
| - return RangeBoundary(result);
|
| - }
|
| -
|
| - // 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;
|
| -
|
| - private:
|
| - RangeBoundary(Kind kind, int64_t value, int64_t offset)
|
| - : kind_(kind), value_(value), offset_(offset) { }
|
| -
|
| - Kind kind_;
|
| - int64_t value_;
|
| - int64_t offset_;
|
| -};
|
| -
|
| -
|
| -class Range : public ZoneAllocated {
|
| - public:
|
| - Range(RangeBoundary min, RangeBoundary max) : min_(min), max_(max) { }
|
| -
|
| - static Range* Unknown() {
|
| - return new Range(RangeBoundary::MinConstant(),
|
| - RangeBoundary::MaxConstant());
|
| - }
|
| -
|
| - static Range* UnknownSmi() {
|
| - return new Range(RangeBoundary::MinSmi(),
|
| - RangeBoundary::MaxSmi());
|
| - }
|
| -
|
| - void PrintTo(BufferFormatter* f) const;
|
| - static const char* ToCString(const Range* range);
|
| -
|
| - const RangeBoundary& min() const { return min_; }
|
| - const RangeBoundary& max() const { return max_; }
|
| -
|
| - static RangeBoundary ConstantMinSmi(const Range* range) {
|
| - if (range == NULL) {
|
| - return RangeBoundary::MinSmi();
|
| - }
|
| - return range->min().LowerBound().Clamp(RangeBoundary::kRangeBoundarySmi);
|
| - }
|
| -
|
| - static RangeBoundary ConstantMaxSmi(const Range* range) {
|
| - if (range == NULL) {
|
| - return RangeBoundary::MaxSmi();
|
| - }
|
| - return range->max().UpperBound().Clamp(RangeBoundary::kRangeBoundarySmi);
|
| - }
|
| -
|
| - static RangeBoundary ConstantMin(const Range* range) {
|
| - if (range == NULL) {
|
| - return RangeBoundary::MinConstant();
|
| - }
|
| - return range->min().LowerBound().Clamp(RangeBoundary::kRangeBoundaryInt64);
|
| - }
|
| -
|
| - static RangeBoundary ConstantMax(const Range* range) {
|
| - if (range == NULL) {
|
| - return RangeBoundary::MaxConstant();
|
| - }
|
| - return range->max().UpperBound().Clamp(RangeBoundary::kRangeBoundaryInt64);
|
| - }
|
| -
|
| - // [0, +inf]
|
| - bool IsPositive() const;
|
| -
|
| - // [-inf, val].
|
| - bool OnlyLessThanOrEqualTo(int64_t val) const;
|
| -
|
| - // [val, +inf].
|
| - bool OnlyGreaterThanOrEqualTo(int64_t val) const;
|
| -
|
| - // Inclusive.
|
| - bool IsWithin(int64_t min_int, int64_t max_int) const;
|
| -
|
| - // Inclusive.
|
| - bool Overlaps(int64_t min_int, int64_t max_int) const;
|
| -
|
| - bool IsUnsatisfiable() const;
|
| -
|
| - bool IsFinite() const {
|
| - return !min_.IsInfinity() && !max_.IsInfinity();
|
| - }
|
| -
|
| - // Clamp this to be within size.
|
| - void Clamp(RangeBoundary::RangeSize size);
|
| -
|
| - static void Add(const Range* left_range,
|
| - const Range* right_range,
|
| - RangeBoundary* min,
|
| - RangeBoundary* max,
|
| - Definition* left_defn);
|
| -
|
| - static void Sub(const Range* left_range,
|
| - const Range* right_range,
|
| - RangeBoundary* min,
|
| - RangeBoundary* max,
|
| - Definition* left_defn);
|
| -
|
| - static bool Mul(const Range* left_range,
|
| - const Range* right_range,
|
| - RangeBoundary* min,
|
| - RangeBoundary* max);
|
| - static void Shr(const Range* left_range,
|
| - const Range* right_range,
|
| - RangeBoundary* min,
|
| - RangeBoundary* max);
|
| -
|
| - static void Shl(const Range* left_range,
|
| - const Range* right_range,
|
| - RangeBoundary* min,
|
| - RangeBoundary* max);
|
| -
|
| - static bool And(const Range* left_range,
|
| - const Range* right_range,
|
| - RangeBoundary* min,
|
| - RangeBoundary* max);
|
| -
|
| -
|
| - // 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 Range* left_range,
|
| - const Range* right_range,
|
| - Definition* left_defn);
|
| -
|
| - private:
|
| - RangeBoundary min_;
|
| - RangeBoundary max_;
|
| -};
|
| -
|
| -
|
| class ConstraintInstr : public TemplateDefinition<2> {
|
| public:
|
| ConstraintInstr(Value* value, Range* constraint)
|
| @@ -8086,7 +7741,7 @@ class CheckArrayBoundInstr : public TemplateInstruction<2> {
|
|
|
| virtual bool CanDeoptimize() const { return true; }
|
|
|
| - bool IsRedundant(RangeBoundary length);
|
| + bool IsRedundant(const RangeBoundary& length);
|
|
|
| virtual Instruction* Canonicalize(FlowGraph* flow_graph);
|
|
|
|
|