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);
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()));
}
#undef TYPED_ARRAY_CASE
}
}
+ if (Type::IsInteger(*value)) {
+ return Type::Range(value->Number(), value->Number(), zone());
+ }
return Type::Constant(value, zone());
}
// 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(
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);
// 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();
// 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
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();
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;