Revision: 22945
Author:   [email protected]
Date:     Wed Aug  6 17:23:47 2014 UTC
Log:      Extend some operations to range types.

This is a reland of 22934, which failed to build on Windows due to a missing include, and on ARM due to a name clash with some predefined constants.

[email protected]
BUG=

Review URL: https://codereview.chromium.org/444023002
http://code.google.com/p/v8/source/detail?r=22945

Modified:
 /branches/bleeding_edge/src/types.cc
 /branches/bleeding_edge/src/types.h
 /branches/bleeding_edge/test/cctest/test-types.cc

=======================================
--- /branches/bleeding_edge/src/types.cc        Wed Aug  6 14:09:21 2014 UTC
+++ /branches/bleeding_edge/src/types.cc        Wed Aug  6 17:23:47 2014 UTC
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.

+#include <math.h>
+
 #include "src/types.h"

 #include "src/ostreams.h"
@@ -10,6 +12,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 && copysign(1, x) <= copysign(1, y);
+}
+
+
+static bool deq(double x, double y) {
+  return dle(x, y) && dle(y, x);
+}
+
+
// -----------------------------------------------------------------------------
 // Glb and lub computation.

@@ -48,6 +65,8 @@
         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 +97,8 @@
     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()) {
@@ -110,6 +131,18 @@
   if (IsInt32Double(value)) return Lub(FastD2I(value));
   return kOtherNumber;
 }
+
+
+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>
@@ -256,6 +289,12 @@
         && *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 +427,12 @@
 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 +465,9 @@
     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 +556,8 @@
       }
     }
   } 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 +800,10 @@
   } 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);
=======================================
--- /branches/bleeding_edge/src/types.h Wed Aug  6 14:09:21 2014 UTC
+++ /branches/bleeding_edge/src/types.h Wed Aug  6 17:23:47 2014 UTC
@@ -286,7 +286,7 @@
     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) {
@@ -518,6 +518,7 @@
   static int Lub(int32_t value);
   static int Lub(uint32_t value);
   static int Lub(i::Map* map);
+  static int Lub(double min, double max);
   static int InherentLub(TypeImpl* type);

   static const char* Name(int bitset);
@@ -690,8 +691,7 @@

   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(BitsetType::Is(bound->AsBitset(), BitsetType::Lub(min, max)));
     RangeHandle type = Config::template cast<RangeType>(
         StructuralType::New(StructuralType::kRangeTag, 3, region));
     type->Set(0, bound);
@@ -704,7 +704,7 @@
   }

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

=======================================
--- /branches/bleeding_edge/test/cctest/test-types.cc Wed Aug 6 14:09:21 2014 UTC +++ /branches/bleeding_edge/test/cctest/test-types.cc Wed Aug 6 17:23:47 2014 UTC
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.

+#include <math.h>
 #include <vector>

 #include "src/hydrogen-types.h"
@@ -139,7 +140,7 @@
     NumberFunction2 = Type::Function(Number, Number, Number, region);
     MethodFunction = Type::Function(String, Object, 0, region);

-    for (int i = 0; i < 40; ++i) {
+    for (int i = 0; i < 30; ++i) {
       types.push_back(Fuzz());
     }
   }
@@ -188,6 +189,21 @@
   MapVector maps;
   ValueVector values;
   DoubleVector doubles;  // Some floating-point values, excluding NaN.
+
+  // Range type helper functions, partially copied from types.cc.
+  // Note: dle(dmin(x,y), dmax(x,y)) holds iff neither x nor y is NaN.
+  bool dle(double x, double y) {
+    return x <= y && copysign(1, x) <= copysign(1, y);
+  }
+  bool deq(double x, double y) {
+    return dle(x, y) && dle(y, x);
+  }
+  double dmin(double x, double y) {
+    return dle(x, y) ? x : y;
+  }
+  double dmax(double x, double y) {
+    return dle(x, y) ? y : x;
+  }

   TypeHandle Of(Handle<i::Object> value) {
     return Type::Of(value, region_);
@@ -549,8 +565,8 @@
     // Constructor
     for (DoubleIterator i = T.doubles.begin(); i != T.doubles.end(); ++i) {
for (DoubleIterator j = T.doubles.begin(); j != T.doubles.end(); ++j) {
-        double min = std::min(*i, *j);
-        double max = std::max(*i, *j);
+        double min = T.dmin(*i, *j);
+        double max = T.dmax(*i, *j);
         TypeHandle type = T.Range(min, max);
         CHECK(type->IsRange());
       }
@@ -559,8 +575,8 @@
     // Range attributes
     for (DoubleIterator i = T.doubles.begin(); i != T.doubles.end(); ++i) {
for (DoubleIterator j = T.doubles.begin(); j != T.doubles.end(); ++j) {
-        double min = std::min(*i, *j);
-        double max = std::max(*i, *j);
+        double min = T.dmin(*i, *j);
+        double max = T.dmax(*i, *j);
         printf("RangeType: min, max = %f, %f\n", min, max);
         TypeHandle type = T.Range(min, max);
         printf("RangeType: Min, Max = %f, %f\n",
@@ -579,13 +595,14 @@
 //           i2 != T.doubles.end(); ++i2) {
 //        for (DoubleIterator j2 = T.doubles.begin();
 //             j2 != T.doubles.end(); ++j2) {
-//          double min1 = std::min(*i1, *j1);
-//          double max1 = std::max(*i1, *j1);
-//          double min2 = std::min(*i2, *j2);
-//          double max2 = std::max(*i2, *j2);
+//          double min1 = T.dmin(*i1, *j1);
+//          double max1 = T.dmax(*i1, *j1);
+//          double min2 = T.dmin(*i2, *j2);
+//          double max2 = T.dmax(*i2, *j2);
 //          TypeHandle type1 = T.Range(min1, max1);
 //          TypeHandle type2 = T.Range(min2, max2);
-//          CHECK(Equal(type1, type2) == (min1 == min2 && max1 == max2));
+//          CHECK(Equal(type1, type2) ==
+//                (T.deq(min1, min2) && T.deq(max1, max2)));
 //        }
 //      }
 //    }

--
--
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