 Chromium Code Reviews
 Chromium Code Reviews Issue 437393005:
  Extend some operations to range types.  (Closed) 
  Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
    
  
    Issue 437393005:
  Extend some operations to range types.  (Closed) 
  Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge| Index: src/types.cc | 
| diff --git a/src/types.cc b/src/types.cc | 
| index fa1bac6dd5319d3923202a16fcf1538a5b09943c..da3554981367686f848b11a3e0a356fa5cbeb067 100644 | 
| --- a/src/types.cc | 
| +++ b/src/types.cc | 
| @@ -10,6 +10,21 @@ | 
| namespace v8 { | 
| namespace internal { | 
| + | 
| +// ----------------------------------------------------------------------------- | 
| +// Range-related custom order on numbers. | 
| +// We want -0 to be less than +0. | 
| + | 
| +static bool le(double x, double y) { | 
| + return x <= y && copysign(1, x) <= copysign(1, y); | 
| +} | 
| + | 
| + | 
| +static bool eq(double x, double y) { | 
| + return le(x, y) && le(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,21 @@ int TypeImpl<Config>::BitsetType::Lub(double value) { | 
| template<class Config> | 
| +int TypeImpl<Config>::BitsetType::Lub(double min, double max) { | 
| + DCHECK(le(min, max)); | 
| + DisallowHeapAllocation no_allocation; | 
| 
rossberg
2014/08/06 13:27:31
Nit: put this first
 | 
| + if (eq(min, max)) { | 
| 
rossberg
2014/08/06 13:27:31
Style nit: same line:
  if (eq(min, max)) return
 | 
| + return BitsetType::Lub(min); // Singleton range. | 
| + } | 
| + int bitset = BitsetType::kNumber ^ SEMANTIC(BitsetType::kNaN); | 
| + if (le(0, min) || max < 0) | 
| 
rossberg
2014/08/06 13:27:31
Style nit: same line
 | 
| + 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 +290,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()) | 
| + && le(that->AsRange()->Min(), this->AsRange()->Min()) | 
| + && le(this->AsRange()->Max(), that->AsRange()->Max()); | 
| + } | 
| if (that->IsContext()) { | 
| return this->IsContext() | 
| && this->AsContext()->Outer()->Equals(that->AsContext()->Outer()); | 
| @@ -388,6 +428,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() && | 
| + le(this->AsRange()->Min(), value->Number()) && | 
| + le(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 +466,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 +557,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; | 
| @@ -754,6 +803,10 @@ typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Convert( | 
| return ConstantType::New( | 
| type->AsConstant()->Value(), | 
| Convert<OtherType>(type->AsConstant()->Bound(), region), region); | 
| + } else if (type->IsRange()) { | 
| + return RangeType::New( | 
| + type->AsRange()->Min(), type->AsRange()->Max(), | 
| + Convert<OtherType>(type->AsRange()->Bound(), region), region); | 
| } else if (type->IsContext()) { | 
| TypeHandle outer = Convert<OtherType>(type->AsContext()->Outer(), region); | 
| return ContextType::New(outer, region); |