From 08dc43947d14e4b02809400222f23ff6afb6852a Mon Sep 17 00:00:00 2001 From: neis Date: Mon, 14 Sep 2015 02:23:19 -0700 Subject: [PATCH] Construct Range rather than Constant when typing integers. 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 | 12 ++++++++++-- src/types.cc | 8 ++++---- src/types.h | 28 +++++++++++++++------------- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc index 594e4bd..6724668 100644 --- a/src/compiler/typer.cc +++ b/src/compiler/typer.cc @@ -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(node)), zone())); + double number = OpParameter(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 value) { #undef TYPED_ARRAY_CASE } } + if (Type::IsInteger(*value)) { + return Type::Range(value->Number(), value->Number(), zone()); + } return Type::Constant(value, zone()); } diff --git a/src/types.cc b/src/types.cc index 7695456..0896b79 100644 --- a/src/types.cc +++ b/src/types.cc @@ -930,7 +930,7 @@ int TypeImpl::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 typename TypeImpl::TypeHandle TypeImpl::NormalizeRangeAndBitset( @@ -942,8 +942,8 @@ typename TypeImpl::TypeHandle TypeImpl::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::TypeHandle TypeImpl::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(); diff --git a/src/types.h b/src/types.h index 84fbe38..67a8550 100644 --- a/src/types.h +++ b/src/types.h @@ -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; -- 2.7.4