Commit 08dc4394 authored by neis's avatar neis Committed by Commit bot

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}
parent d90a4047
...@@ -48,6 +48,8 @@ Typer::Typer(Isolate* isolate, Graph* graph, Type::FunctionType* function_type) ...@@ -48,6 +48,8 @@ Typer::Typer(Isolate* isolate, Graph* graph, Type::FunctionType* function_type)
Type* infinity = Type::Constant(factory->infinity_value(), zone); Type* infinity = Type::Constant(factory->infinity_value(), zone);
Type* minus_infinity = Type::Constant(factory->minus_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* truncating_to_zero =
Type::Union(Type::Union(infinity, minus_infinity, zone), Type::Union(Type::Union(infinity, minus_infinity, zone),
Type::MinusZeroOrNaN(), zone); Type::MinusZeroOrNaN(), zone);
...@@ -535,8 +537,11 @@ Bounds Typer::Visitor::TypeFloat64Constant(Node* node) { ...@@ -535,8 +537,11 @@ Bounds Typer::Visitor::TypeFloat64Constant(Node* node) {
Bounds Typer::Visitor::TypeNumberConstant(Node* node) { Bounds Typer::Visitor::TypeNumberConstant(Node* node) {
Factory* f = isolate()->factory(); Factory* f = isolate()->factory();
return Bounds(Type::Constant( double number = OpParameter<double>(node);
f->NewNumber(OpParameter<double>(node)), zone())); 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) { ...@@ -2288,6 +2293,9 @@ Type* Typer::Visitor::TypeConstant(Handle<Object> value) {
#undef TYPED_ARRAY_CASE #undef TYPED_ARRAY_CASE
} }
} }
if (Type::IsInteger(*value)) {
return Type::Range(value->Number(), value->Number(), zone());
}
return Type::Constant(value, zone()); return Type::Constant(value, zone());
} }
......
...@@ -930,7 +930,7 @@ int TypeImpl<Config>::IntersectAux(TypeHandle lhs, TypeHandle rhs, ...@@ -930,7 +930,7 @@ int TypeImpl<Config>::IntersectAux(TypeHandle lhs, TypeHandle rhs,
// Make sure that we produce a well-formed range and bitset: // 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 // 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. // we want to produce a bitset rather than a range.
template <class Config> template <class Config>
typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::NormalizeRangeAndBitset( typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::NormalizeRangeAndBitset(
...@@ -942,8 +942,8 @@ typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::NormalizeRangeAndBitset( ...@@ -942,8 +942,8 @@ typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::NormalizeRangeAndBitset(
return range; return range;
} }
// If the range is contained within the bitset, return an empty range // If the range is semantically contained within the bitset, return None and
// (but make sure we take the representation). // leave the bitset untouched.
bitset range_lub = SEMANTIC(range->BitsetLub()); bitset range_lub = SEMANTIC(range->BitsetLub());
if (BitsetType::Is(BitsetType::NumberBits(range_lub), *bits)) { if (BitsetType::Is(BitsetType::NumberBits(range_lub), *bits)) {
return None(region); return None(region);
...@@ -993,7 +993,7 @@ typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Union( ...@@ -993,7 +993,7 @@ typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Union(
// Figure out the representation of the result. // Figure out the representation of the result.
// The rest of the method should not change this representation and // 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). // it should only use the semantic part of types).
const bitset representation = const bitset representation =
type1->Representation() | type2->Representation(); type1->Representation() | type2->Representation();
......
...@@ -95,10 +95,13 @@ namespace internal { ...@@ -95,10 +95,13 @@ namespace internal {
// RANGE TYPES // RANGE TYPES
// //
// A range type represents a continuous integer interval by its minimum and // 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 // If a value v happens to be an integer n, then Constant(v) is considered a
// integer between x and y. // 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 // PREDICATES
...@@ -513,11 +516,17 @@ class TypeImpl : public Config::Base { ...@@ -513,11 +516,17 @@ class TypeImpl : public Config::Base {
double Min(); double Min();
double Max(); double Max();
// Extracts a range from the type. If the type is a range, it just // Extracts a range from the type: if the type is a range or a union
// returns it; if it is a union, it returns the range component. // containing a range, that range is returned; otherwise, NULL is returned.
// Note that it does not contain range for constants.
RangeType* GetRange(); 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 NumClasses();
int NumConstants(); int NumConstants();
...@@ -589,13 +598,6 @@ class TypeImpl : public Config::Base { ...@@ -589,13 +598,6 @@ class TypeImpl : public Config::Base {
bool SlowIs(TypeImpl* that); bool SlowIs(TypeImpl* that);
bool SemanticIs(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 { struct Limits {
double min; double min;
double max; double max;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment