Chromium Code Reviews| Index: src/types.cc |
| diff --git a/src/types.cc b/src/types.cc |
| index 45dcea2de7d8c84f82ab7e3903fefd671ec2668e..f9b1eea19c9508bc92eb17cf503b795868a0a1ca 100644 |
| --- a/src/types.cc |
| +++ b/src/types.cc |
| @@ -10,6 +10,21 @@ |
| namespace v8 { |
| namespace internal { |
| + |
| +// ----------------------------------------------------------------------------- |
| +// Range-related custom order on doubles. |
| +// We want -0 to be less than +0. |
| + |
| +static bool dle(double x, double y) { |
| + return x <= y && (!IsMinusZero(y) || x != 0 || IsMinusZero(x)); |
|
rossberg
2014/08/07 14:12:57
Nit: I would order this
(x != 0 || IsMinusZero(x)
|
| +} |
| + |
| + |
| +static bool deq(double x, double y) { |
| + return dle(x, y) && dle(y, x); |
| +} |
| + |
| + |
| // ----------------------------------------------------------------------------- |
| // Glb and lub computation. |
| @@ -48,6 +63,8 @@ int TypeImpl<Config>::BitsetType::Lub(TypeImpl* type) { |
| type->AsClass()->Bound(NULL)->AsBitset(); |
| } else if (type->IsConstant()) { |
| return type->AsConstant()->Bound()->AsBitset(); |
| + } else if (type->IsRange()) { |
| + return type->AsRange()->Bound()->AsBitset(); |
| } else if (type->IsContext()) { |
| return type->AsContext()->Bound()->AsBitset(); |
| } else if (type->IsArray()) { |
| @@ -78,6 +95,8 @@ int TypeImpl<Config>::BitsetType::InherentLub(TypeImpl* type) { |
| return Lub(*type->AsClass()->Map()); |
| } else if (type->IsConstant()) { |
| return Lub(*type->AsConstant()->Value()); |
| + } else if (type->IsRange()) { |
| + return Lub(type->AsRange()->Min(), type->AsRange()->Max()); |
| } else if (type->IsContext()) { |
| return kInternal & kTaggedPtr; |
| } else if (type->IsArray()) { |
| @@ -113,6 +132,18 @@ int TypeImpl<Config>::BitsetType::Lub(double value) { |
| template<class Config> |
| +int TypeImpl<Config>::BitsetType::Lub(double min, double max) { |
| + DisallowHeapAllocation no_allocation; |
| + DCHECK(dle(min, max)); |
| + if (deq(min, max)) return BitsetType::Lub(min); // Singleton range. |
| + int bitset = BitsetType::kNumber ^ SEMANTIC(BitsetType::kNaN); |
| + if (dle(0, min) || max < 0) bitset ^= SEMANTIC(BitsetType::kMinusZero); |
| + return bitset; |
| + // TODO(neis): Could refine this further by doing more checks on min/max. |
| +} |
| + |
| + |
| +template<class Config> |
| int TypeImpl<Config>::BitsetType::Lub(int32_t value) { |
| if (value >= 0x40000000) { |
| return i::SmiValuesAre31Bits() ? kOtherUnsigned31 : kUnsignedSmall; |
| @@ -256,6 +287,12 @@ bool TypeImpl<Config>::SlowIs(TypeImpl* that) { |
| && *this->AsConstant()->Value() == *that->AsConstant()->Value() |
| && this->AsConstant()->Bound()->Is(that->AsConstant()->Bound()); |
| } |
| + if (that->IsRange()) { |
| + return this->IsRange() |
| + && this->AsRange()->Bound()->Is(that->AsRange()->Bound()) |
| + && dle(that->AsRange()->Min(), this->AsRange()->Min()) |
| + && dle(this->AsRange()->Max(), that->AsRange()->Max()); |
| + } |
| if (that->IsContext()) { |
| return this->IsContext() |
| && this->AsContext()->Outer()->Equals(that->AsContext()->Outer()); |
| @@ -388,6 +425,12 @@ bool TypeImpl<Config>::Maybe(TypeImpl* that) { |
| template<class Config> |
| bool TypeImpl<Config>::Contains(i::Object* value) { |
| DisallowHeapAllocation no_allocation; |
| + if (this->IsRange()) { |
| + return value->IsNumber() && |
| + dle(this->AsRange()->Min(), value->Number()) && |
| + dle(value->Number(), this->AsRange()->Max()) && |
| + BitsetType::Is(BitsetType::Lub(value), this->BitsetLub()); |
| + } |
| for (Iterator<i::Object> it = this->Constants(); !it.Done(); it.Advance()) { |
| if (*it.Current() == value) return true; |
| } |
| @@ -420,6 +463,9 @@ typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Rebound( |
| return ClassType::New(this->AsClass()->Map(), bound, region); |
| } else if (this->IsConstant()) { |
| return ConstantType::New(this->AsConstant()->Value(), bound, region); |
| + } else if (this->IsRange()) { |
| + return RangeType::New( |
| + this->AsRange()->Min(), this->AsRange()->Max(), bound, region); |
| } else if (this->IsContext()) { |
| return ContextType::New(this->AsContext()->Outer(), bound, region); |
| } else if (this->IsArray()) { |
| @@ -508,8 +554,8 @@ int TypeImpl<Config>::ExtendUnion( |
| } |
| } |
| } else if (!type->IsBitset()) { |
| - DCHECK(type->IsClass() || type->IsConstant() || |
| - type->IsArray() || type->IsFunction() || type->IsContext()); |
| + DCHECK(type->IsClass() || type->IsConstant() || type->IsRange() || |
| + type->IsContext() || type->IsArray() || type->IsFunction()); |
| int inherent_bound = type->InherentBitsetLub(); |
| int old_bound = type->BitsetLub(); |
| int other_bound = type->BoundBy(other->unhandle()) & inherent_bound; |
| @@ -752,6 +798,10 @@ typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Convert( |
| } else if (type->IsConstant()) { |
| TypeHandle bound = Convert<OtherType>(type->AsConstant()->Bound(), region); |
| return ConstantType::New(type->AsConstant()->Value(), bound, region); |
| + } else if (type->IsRange()) { |
| + TypeHandle bound = Convert<OtherType>(type->AsRange()->Bound(), region); |
| + return RangeType::New( |
| + type->AsRange()->Min(), type->AsRange()->Max(), bound, region); |
| } else if (type->IsContext()) { |
| TypeHandle bound = Convert<OtherType>(type->AsContext()->Bound(), region); |
| TypeHandle outer = Convert<OtherType>(type->AsContext()->Outer(), region); |