Reviewers: rossberg,

Description:
Extend some operations to range types.

[email protected]
BUG=

Please review this at https://codereview.chromium.org/437393005/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files (+60, -8 lines):
  M src/types.h
  M src/types.cc


Index: src/types.cc
diff --git a/src/types.cc b/src/types.cc
index c4e32f7823e6a15ac684a163c864b5de929bcc25..125fd02875239a2ce63a96e9ed4384c630452c68 100644
--- a/src/types.cc
+++ b/src/types.cc
@@ -65,6 +65,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()) {
@@ -95,6 +97,9 @@ 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 RangeType::InherentLub(
+        type->AsRange()->Min(), type->AsRange()->Max());
   } else if (type->IsContext()) {
     return kInternal & kTaggedPtr;
   } else if (type->IsArray()) {
@@ -274,8 +279,14 @@ bool TypeImpl<Config>::SlowIs(TypeImpl* that) {
   }
   if (that->IsConstant()) {
     return this->IsConstant()
-        && *this->AsConstant()->Value() == *that->AsConstant()->Value()
-        && this->AsConstant()->Bound()->Is(that->AsConstant()->Bound());
+        && this->AsConstant()->Bound()->Is(that->AsConstant()->Bound())
+        && *this->AsConstant()->Value() == *that->AsConstant()->Value();
+  }
+  if (that->IsRange()) {
+    return this->IsRange()
+        && this->AsRange()->Bound()->Is(that->AsRange()->Bound())
+        && RangeType::le(that->AsRange()->Min(), this->AsRange()->Min())
+        && RangeType::le(this->AsRange()->Max(), that->AsRange()->Max());
   }
   if (that->IsContext()) {
     return this->IsContext()
@@ -409,6 +420,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() &&
+           RangeType::le(this->AsRange()->Min(), value->Number()) &&
+           RangeType::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;
   }
@@ -441,6 +458,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()) {
@@ -529,8 +549,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;
@@ -797,6 +817,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);
Index: src/types.h
diff --git a/src/types.h b/src/types.h
index f141712bb84f09c5e58124174517eadc7a2241f6..711d2eebb99a3b38d5ebfd41a9bfbd683af02f88 100644
--- a/src/types.h
+++ b/src/types.h
@@ -285,7 +285,7 @@ class TypeImpl : public Config::Base {
     return ClassType::New(map, region);
   }
   static TypeHandle Constant(i::Handle<i::Object> value, Region* region) {
-    // TODO(neis): return RangeType for numerical values
+    // TODO(neis): Return RangeType for numerical values.
     return ConstantType::New(value, region);
   }
   static TypeHandle Range(double min, double max, Region* region) {
@@ -514,6 +514,7 @@ class TypeImpl<Config>::BitsetType : public TypeImpl<Config> {
   static int Lub(int32_t value);
   static int Lub(uint32_t value);
   static int Lub(i::Map* map);
+  static int RangeLub(double min, double max, TypeHandle bound);
   static int InherentLub(TypeImpl* type);

   static const char* Name(int bitset);
@@ -684,10 +685,37 @@ class TypeImpl<Config>::RangeType : public StructuralType { double Min() { return this->template GetValue<i::HeapNumber>(1)->value(); } double Max() { return this->template GetValue<i::HeapNumber>(2)->value(); }

+  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);
+  }
+  static double min(double x, double y) {
+    return le(x, y) ? x : y;
+  }
+  static double max(double x, double y) {
+    return le(x, y) ? y : x;
+  }
+
+  static int InherentLub(double min, double max) {
+    DCHECK(le(min, max));
+    DisallowHeapAllocation no_allocation;
+    if (min == max) {
+      return BitsetType::Lub(min);  // Singleton range.
+    }
+    int bitset = BitsetType::kNumber ^ SEMANTIC(BitsetType::kNaN);
+    if (le(0, min) || max < 0)
+      bitset ^= SEMANTIC(BitsetType::kMinusZero);
+    return bitset;
+ // TODO(neis): Could refine this further by doing more checks on min/max.
+  }
+
   static RangeHandle New(
       double min, double max, TypeHandle bound, Region* region) {
-    DCHECK(BitsetType::Is(bound->AsBitset(), BitsetType::kNumber));
-    DCHECK(!std::isnan(min) && !std::isnan(max) && min <= max);
+    DCHECK(le(min, max));
+    DCHECK(bound->IsBitset());
+    DCHECK(BitsetType::Is(bound->AsBitset(), InherentLub(min, max)));
     RangeHandle type = Config::template cast<RangeType>(
         StructuralType::New(StructuralType::kRangeTag, 3, region));
     type->Set(0, bound);
@@ -700,7 +728,7 @@ class TypeImpl<Config>::RangeType : public StructuralType {
   }

   static RangeHandle New(double min, double max, Region* region) {
-    TypeHandle bound = BitsetType::New(BitsetType::kNumber, region);
+    TypeHandle bound = BitsetType::New(InherentLub(min, max), region);
     return New(min, max, bound, region);
   }



--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to