Construct Range rather than Constant when typing integers.
authorneis <neis@chromium.org>
Mon, 14 Sep 2015 09:23:19 +0000 (02:23 -0700)
committerCommit bot <commit-bot@chromium.org>
Mon, 14 Sep 2015 09:23:34 +0000 (09:23 +0000)
Also clarify some comments.

R=jarin@chromium.org
BUG=

Review URL: https://codereview.chromium.org/1328193003

Cr-Commit-Position: refs/heads/master@{#30708}

src/compiler/typer.cc
src/types.cc
src/types.h

index 594e4bd..6724668 100644 (file)
@@ -48,6 +48,8 @@ Typer::Typer(Isolate* isolate, Graph* graph, Type::FunctionType* function_type)
 
   Type* infinity = Type::Constant(factory->infinity_value(), zone);
   Type* minus_infinity = Type::Constant(factory->minus_infinity_value(), zone);
+  // TODO(neis): Unfortunately, the infinities created in other places might
+  // be different ones (eg the result of NewNumber in TypeNumberConstant).
   Type* truncating_to_zero =
       Type::Union(Type::Union(infinity, minus_infinity, zone),
                   Type::MinusZeroOrNaN(), zone);
@@ -535,8 +537,11 @@ Bounds Typer::Visitor::TypeFloat64Constant(Node* node) {
 
 Bounds Typer::Visitor::TypeNumberConstant(Node* node) {
   Factory* f = isolate()->factory();
-  return Bounds(Type::Constant(
-      f->NewNumber(OpParameter<double>(node)), zone()));
+  double number = OpParameter<double>(node);
+  if (Type::IsInteger(number)) {
+    return Bounds(Type::Range(number, number, zone()));
+  }
+  return Bounds(Type::Constant(f->NewNumber(number), zone()));
 }
 
 
@@ -2288,6 +2293,9 @@ Type* Typer::Visitor::TypeConstant(Handle<Object> value) {
 #undef TYPED_ARRAY_CASE
     }
   }
+  if (Type::IsInteger(*value)) {
+    return Type::Range(value->Number(), value->Number(), zone());
+  }
   return Type::Constant(value, zone());
 }
 
index 7695456..0896b79 100644 (file)
@@ -930,7 +930,7 @@ int TypeImpl<Config>::IntersectAux(TypeHandle lhs, TypeHandle rhs,
 
 // Make sure that we produce a well-formed range and bitset:
 // If the range is non-empty, the number bits in the bitset should be
-// clear. Moreover, if we have a canonical range (such as Signed32(),
+// clear. Moreover, if we have a canonical range (such as Signed32),
 // we want to produce a bitset rather than a range.
 template <class Config>
 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::NormalizeRangeAndBitset(
@@ -942,8 +942,8 @@ typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::NormalizeRangeAndBitset(
     return range;
   }
 
-  // If the range is contained within the bitset, return an empty range
-  // (but make sure we take the representation).
+  // If the range is semantically contained within the bitset, return None and
+  // leave the bitset untouched.
   bitset range_lub = SEMANTIC(range->BitsetLub());
   if (BitsetType::Is(BitsetType::NumberBits(range_lub), *bits)) {
     return None(region);
@@ -993,7 +993,7 @@ typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Union(
 
   // Figure out the representation of the result.
   // The rest of the method should not change this representation and
-  // it should make any decisions based on representations (i.e.,
+  // it should not make any decisions based on representations (i.e.,
   // it should only use the semantic part of types).
   const bitset representation =
       type1->Representation() | type2->Representation();
index 84fbe38..67a8550 100644 (file)
@@ -95,10 +95,13 @@ namespace internal {
 // RANGE TYPES
 //
 // A range type represents a continuous integer interval by its minimum and
-// maximum value.  Either value might be an infinity.
+// maximum value.  Either value may be an infinity, in which case that infinity
+// itself is also included in the range.   A range never contains NaN or -0.
 //
-// Constant(v) is considered a subtype of Range(x..y) if v happens to be an
-// integer between x and y.
+// If a value v happens to be an integer n, then Constant(v) is considered a
+// subtype of Range(n, n) (and therefore also a subtype of any larger range).
+// In order to avoid large unions, however, it is usually a good idea to use
+// Range rather than Constant.
 //
 //
 // PREDICATES
@@ -513,11 +516,17 @@ class TypeImpl : public Config::Base {
   double Min();
   double Max();
 
-  // Extracts a range from the type. If the type is a range, it just
-  // returns it; if it is a union, it returns the range component.
-  // Note that it does not contain range for constants.
+  // Extracts a range from the type: if the type is a range or a union
+  // containing a range, that range is returned; otherwise, NULL is returned.
   RangeType* GetRange();
 
+  static bool IsInteger(double x) {
+    return nearbyint(x) == x && !i::IsMinusZero(x);  // Allows for infinities.
+  }
+  static bool IsInteger(i::Object* x) {
+    return x->IsNumber() && IsInteger(x->Number());
+  }
+
   int NumClasses();
   int NumConstants();
 
@@ -589,13 +598,6 @@ class TypeImpl : public Config::Base {
   bool SlowIs(TypeImpl* that);
   bool SemanticIs(TypeImpl* that);
 
-  static bool IsInteger(double x) {
-    return nearbyint(x) == x && !i::IsMinusZero(x);  // Allows for infinities.
-  }
-  static bool IsInteger(i::Object* x) {
-    return x->IsNumber() && IsInteger(x->Number());
-  }
-
   struct Limits {
     double min;
     double max;