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}
This commit is contained in:
parent
d90a404747
commit
08dc43947d
@ -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());
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
28
src/types.h
28
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;
|
||||
|
Loading…
Reference in New Issue
Block a user