Revert "Revert "Upgrade to 5.0.71.48"" DO NOT MERGE
This reverts commit f2e3994fa5148cc3d9946666f0b0596290192b0e,
and updates the x64 makefile properly so it doesn't break that
build.
FPIIM-449
Change-Id: Ib83e35bfbae6af627451c926a9650ec57c045605
(cherry picked from commit 109988c7ccb6f3fd1a58574fa3dfb88beaef6632)
diff --git a/src/types.h b/src/types.h
index 9ce650d..9984ad8 100644
--- a/src/types.h
+++ b/src/types.h
@@ -143,14 +143,6 @@
// bitsets. Bit 0 is reserved for tagging. Class is a heap pointer to the
// respective map. Only structured types require allocation.
// Note that the bitset representation is closed under both Union and Intersect.
-//
-// There are two type representations, using different allocation:
-//
-// - class Type (zone-allocated, for compiler and concurrent compilation)
-// - class HeapType (heap-allocated, for persistent types)
-//
-// Both provide the same API, and the Convert method can be used to interconvert
-// them. For zone types, no query method touches the heap, only constructors do.
// -----------------------------------------------------------------------------
@@ -159,20 +151,21 @@
// clang-format off
#define MASK_BITSET_TYPE_LIST(V) \
- V(Representation, 0xff800000u) \
- V(Semantic, 0x007ffffeu)
+ V(Representation, 0xffc00000u) \
+ V(Semantic, 0x003ffffeu)
#define REPRESENTATION(k) ((k) & BitsetType::kRepresentation)
#define SEMANTIC(k) ((k) & BitsetType::kSemantic)
#define REPRESENTATION_BITSET_TYPE_LIST(V) \
V(None, 0) \
- V(UntaggedBit, 1u << 23 | kSemantic) \
- V(UntaggedIntegral8, 1u << 24 | kSemantic) \
- V(UntaggedIntegral16, 1u << 25 | kSemantic) \
- V(UntaggedIntegral32, 1u << 26 | kSemantic) \
- V(UntaggedFloat32, 1u << 27 | kSemantic) \
- V(UntaggedFloat64, 1u << 28 | kSemantic) \
+ V(UntaggedBit, 1u << 22 | kSemantic) \
+ V(UntaggedIntegral8, 1u << 23 | kSemantic) \
+ V(UntaggedIntegral16, 1u << 24 | kSemantic) \
+ V(UntaggedIntegral32, 1u << 25 | kSemantic) \
+ V(UntaggedFloat32, 1u << 26 | kSemantic) \
+ V(UntaggedFloat64, 1u << 27 | kSemantic) \
+ V(UntaggedSimd128, 1u << 28 | kSemantic) \
V(UntaggedPointer, 1u << 29 | kSemantic) \
V(TaggedSigned, 1u << 30 | kSemantic) \
V(TaggedPointer, 1u << 31 | kSemantic) \
@@ -267,400 +260,27 @@
INTERNAL_BITSET_TYPE_LIST(V) \
SEMANTIC_BITSET_TYPE_LIST(V)
-
-// -----------------------------------------------------------------------------
-// The abstract Type class, parameterized over the low-level representation.
-
-// struct Config {
-// typedef TypeImpl<Config> Type;
-// typedef Base;
-// typedef Struct;
-// typedef Range;
-// typedef Region;
-// template<class> struct Handle { typedef type; } // No template typedefs...
-//
-// template<class T> static Handle<T>::type null_handle();
-// template<class T> static Handle<T>::type handle(T* t); // !is_bitset(t)
-// template<class T> static Handle<T>::type cast(Handle<Type>::type);
-//
-// static bool is_bitset(Type*);
-// static bool is_class(Type*);
-// static bool is_struct(Type*, int tag);
-// static bool is_range(Type*);
-//
-// static bitset as_bitset(Type*);
-// static i::Handle<i::Map> as_class(Type*);
-// static Handle<Struct>::type as_struct(Type*);
-// static Handle<Range>::type as_range(Type*);
-//
-// static Type* from_bitset(bitset);
-// static Handle<Type>::type from_bitset(bitset, Region*);
-// static Handle<Type>::type from_class(i::Handle<Map>, Region*);
-// static Handle<Type>::type from_struct(Handle<Struct>::type, int tag);
-// static Handle<Type>::type from_range(Handle<Range>::type);
-//
-// static Handle<Struct>::type struct_create(int tag, int length, Region*);
-// static void struct_shrink(Handle<Struct>::type, int length);
-// static int struct_tag(Handle<Struct>::type);
-// static int struct_length(Handle<Struct>::type);
-// static Handle<Type>::type struct_get(Handle<Struct>::type, int);
-// static void struct_set(Handle<Struct>::type, int, Handle<Type>::type);
-// template<class V>
-// static i::Handle<V> struct_get_value(Handle<Struct>::type, int);
-// template<class V>
-// static void struct_set_value(Handle<Struct>::type, int, i::Handle<V>);
-//
-// static Handle<Range>::type range_create(Region*);
-// static int range_get_bitset(Handle<Range>::type);
-// static void range_set_bitset(Handle<Range>::type, int);
-// static double range_get_double(Handle<Range>::type, int);
-// static void range_set_double(Handle<Range>::type, int, double, Region*);
-// }
-template<class Config>
-class TypeImpl : public Config::Base {
- public:
- // Auxiliary types.
-
- typedef uint32_t bitset; // Internal
- class BitsetType; // Internal
- class StructuralType; // Internal
- class UnionType; // Internal
-
- class ClassType;
- class ConstantType;
- class RangeType;
- class ContextType;
- class ArrayType;
- class FunctionType;
-
- typedef typename Config::template Handle<TypeImpl>::type TypeHandle;
- typedef typename Config::template Handle<ClassType>::type ClassHandle;
- typedef typename Config::template Handle<ConstantType>::type ConstantHandle;
- typedef typename Config::template Handle<RangeType>::type RangeHandle;
- typedef typename Config::template Handle<ContextType>::type ContextHandle;
- typedef typename Config::template Handle<ArrayType>::type ArrayHandle;
- typedef typename Config::template Handle<FunctionType>::type FunctionHandle;
- typedef typename Config::template Handle<UnionType>::type UnionHandle;
- typedef typename Config::Region Region;
-
- // Constructors.
-
- #define DEFINE_TYPE_CONSTRUCTOR(type, value) \
- static TypeImpl* type() { \
- return BitsetType::New(BitsetType::k##type); \
- } \
- static TypeHandle type(Region* region) { \
- return BitsetType::New(BitsetType::k##type, region); \
- }
- PROPER_BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR)
- #undef DEFINE_TYPE_CONSTRUCTOR
-
- static TypeImpl* SignedSmall() {
- return BitsetType::New(BitsetType::SignedSmall());
- }
- static TypeHandle SignedSmall(Region* region) {
- return BitsetType::New(BitsetType::SignedSmall(), region);
- }
- static TypeImpl* UnsignedSmall() {
- return BitsetType::New(BitsetType::UnsignedSmall());
- }
- static TypeHandle UnsignedSmall(Region* region) {
- return BitsetType::New(BitsetType::UnsignedSmall(), region);
- }
-
- static TypeHandle Class(i::Handle<i::Map> map, Region* region) {
- return ClassType::New(map, region);
- }
- static TypeHandle Constant(i::Handle<i::Object> value, Region* region) {
- return ConstantType::New(value, region);
- }
- static TypeHandle Range(double min, double max, Region* region) {
- return RangeType::New(
- min, max, BitsetType::New(REPRESENTATION(BitsetType::kTagged |
- BitsetType::kUntaggedNumber),
- region),
- region);
- }
- static TypeHandle Context(TypeHandle outer, Region* region) {
- return ContextType::New(outer, region);
- }
- static TypeHandle Array(TypeHandle element, Region* region) {
- return ArrayType::New(element, region);
- }
- static FunctionHandle Function(
- TypeHandle result, TypeHandle receiver, int arity, Region* region) {
- return FunctionType::New(result, receiver, arity, region);
- }
- static TypeHandle Function(TypeHandle result, Region* region) {
- return Function(result, Any(region), 0, region);
- }
- static TypeHandle Function(
- TypeHandle result, TypeHandle param0, Region* region) {
- FunctionHandle function = Function(result, Any(region), 1, region);
- function->InitParameter(0, param0);
- return function;
- }
- static TypeHandle Function(
- TypeHandle result, TypeHandle param0, TypeHandle param1, Region* region) {
- FunctionHandle function = Function(result, Any(region), 2, region);
- function->InitParameter(0, param0);
- function->InitParameter(1, param1);
- return function;
- }
- static TypeHandle Function(
- TypeHandle result, TypeHandle param0, TypeHandle param1,
- TypeHandle param2, Region* region) {
- FunctionHandle function = Function(result, Any(region), 3, region);
- function->InitParameter(0, param0);
- function->InitParameter(1, param1);
- function->InitParameter(2, param2);
- return function;
- }
- static TypeHandle Function(TypeHandle result, int arity, TypeHandle* params,
- Region* region) {
- FunctionHandle function = Function(result, Any(region), arity, region);
- for (int i = 0; i < arity; ++i) {
- function->InitParameter(i, params[i]);
- }
- return function;
- }
-
-#define CONSTRUCT_SIMD_TYPE(NAME, Name, name, lane_count, lane_type) \
- static TypeHandle Name(Isolate* isolate, Region* region);
- SIMD128_TYPES(CONSTRUCT_SIMD_TYPE)
-#undef CONSTRUCT_SIMD_TYPE
-
- static TypeHandle Union(TypeHandle type1, TypeHandle type2, Region* reg);
- static TypeHandle Intersect(TypeHandle type1, TypeHandle type2, Region* reg);
-
- static TypeHandle Of(double value, Region* region) {
- return Config::from_bitset(BitsetType::ExpandInternals(
- BitsetType::Lub(value)), region);
- }
- static TypeHandle Of(i::Object* value, Region* region) {
- return Config::from_bitset(BitsetType::ExpandInternals(
- BitsetType::Lub(value)), region);
- }
- static TypeHandle Of(i::Handle<i::Object> value, Region* region) {
- return Of(*value, region);
- }
-
- // Extraction of components.
- static TypeHandle Representation(TypeHandle t, Region* region);
- static TypeHandle Semantic(TypeHandle t, Region* region);
-
- // Predicates.
- bool IsInhabited() { return BitsetType::IsInhabited(this->BitsetLub()); }
-
- bool Is(TypeImpl* that) { return this == that || this->SlowIs(that); }
- template<class TypeHandle>
- bool Is(TypeHandle that) { return this->Is(*that); }
-
- bool Maybe(TypeImpl* that);
- template<class TypeHandle>
- bool Maybe(TypeHandle that) { return this->Maybe(*that); }
-
- bool Equals(TypeImpl* that) { return this->Is(that) && that->Is(this); }
- template<class TypeHandle>
- bool Equals(TypeHandle that) { return this->Equals(*that); }
-
- // Equivalent to Constant(val)->Is(this), but avoiding allocation.
- bool Contains(i::Object* val);
- bool Contains(i::Handle<i::Object> val) { return this->Contains(*val); }
-
- // State-dependent versions of the above that consider subtyping between
- // a constant and its map class.
- inline static TypeHandle NowOf(i::Object* value, Region* region);
- static TypeHandle NowOf(i::Handle<i::Object> value, Region* region) {
- return NowOf(*value, region);
- }
- bool NowIs(TypeImpl* that);
- template<class TypeHandle>
- bool NowIs(TypeHandle that) { return this->NowIs(*that); }
- inline bool NowContains(i::Object* val);
- bool NowContains(i::Handle<i::Object> val) { return this->NowContains(*val); }
-
- bool NowStable();
-
- // Inspection.
-
- bool IsRange() { return Config::is_range(this); }
- bool IsClass() {
- return Config::is_class(this)
- || Config::is_struct(this, StructuralType::kClassTag);
- }
- bool IsConstant() {
- return Config::is_struct(this, StructuralType::kConstantTag);
- }
- bool IsContext() {
- return Config::is_struct(this, StructuralType::kContextTag);
- }
- bool IsArray() {
- return Config::is_struct(this, StructuralType::kArrayTag);
- }
- bool IsFunction() {
- return Config::is_struct(this, StructuralType::kFunctionTag);
- }
-
- ClassType* AsClass() { return ClassType::cast(this); }
- ConstantType* AsConstant() { return ConstantType::cast(this); }
- RangeType* AsRange() { return RangeType::cast(this); }
- ContextType* AsContext() { return ContextType::cast(this); }
- ArrayType* AsArray() { return ArrayType::cast(this); }
- FunctionType* AsFunction() { return FunctionType::cast(this); }
-
- // Minimum and maximum of a numeric type.
- // These functions do not distinguish between -0 and +0. If the type equals
- // kNaN, they return NaN; otherwise kNaN is ignored. Only call these
- // functions on subtypes of Number.
- double Min();
- double Max();
-
- // 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();
-
- template<class T> class Iterator;
- Iterator<i::Map> Classes() {
- if (this->IsBitset()) return Iterator<i::Map>();
- return Iterator<i::Map>(Config::handle(this));
- }
- Iterator<i::Object> Constants() {
- if (this->IsBitset()) return Iterator<i::Object>();
- return Iterator<i::Object>(Config::handle(this));
- }
-
- // Casting and conversion.
-
- static inline TypeImpl* cast(typename Config::Base* object);
-
- template<class OtherTypeImpl>
- static TypeHandle Convert(
- typename OtherTypeImpl::TypeHandle type, Region* region);
-
- // Printing.
-
- enum PrintDimension { BOTH_DIMS, SEMANTIC_DIM, REPRESENTATION_DIM };
-
- void PrintTo(std::ostream& os, PrintDimension dim = BOTH_DIMS); // NOLINT
-
-#ifdef DEBUG
- void Print();
-#endif
-
- bool IsUnionForTesting() { return IsUnion(); }
-
- protected:
- // Friends.
-
- template<class> friend class Iterator;
- template<class> friend class TypeImpl;
-
- // Handle conversion.
-
- template<class T>
- static typename Config::template Handle<T>::type handle(T* type) {
- return Config::handle(type);
- }
- TypeImpl* unhandle() { return this; }
-
- // Internal inspection.
-
- bool IsNone() { return this == None(); }
- bool IsAny() { return this == Any(); }
- bool IsBitset() { return Config::is_bitset(this); }
- bool IsUnion() { return Config::is_struct(this, StructuralType::kUnionTag); }
-
- bitset AsBitset() {
- DCHECK(this->IsBitset());
- return static_cast<BitsetType*>(this)->Bitset();
- }
- UnionType* AsUnion() { return UnionType::cast(this); }
-
- bitset Representation();
-
- // Auxiliary functions.
- bool SemanticMaybe(TypeImpl* that);
-
- bitset BitsetGlb() { return BitsetType::Glb(this); }
- bitset BitsetLub() { return BitsetType::Lub(this); }
-
- bool SlowIs(TypeImpl* that);
- bool SemanticIs(TypeImpl* that);
-
- struct Limits {
- double min;
- double max;
- Limits(double min, double max) : min(min), max(max) {}
- explicit Limits(RangeType* range) : min(range->Min()), max(range->Max()) {}
- bool IsEmpty();
- static Limits Empty() { return Limits(1, 0); }
- static Limits Intersect(Limits lhs, Limits rhs);
- static Limits Union(Limits lhs, Limits rhs);
- };
-
- static bool Overlap(RangeType* lhs, RangeType* rhs);
- static bool Contains(RangeType* lhs, RangeType* rhs);
- static bool Contains(RangeType* range, ConstantType* constant);
- static bool Contains(RangeType* range, i::Object* val);
-
- static int UpdateRange(
- RangeHandle type, UnionHandle result, int size, Region* region);
-
- static Limits IntersectRangeAndBitset(TypeHandle range, TypeHandle bits,
- Region* region);
- static Limits ToLimits(bitset bits, Region* region);
-
- bool SimplyEquals(TypeImpl* that);
- template<class TypeHandle>
- bool SimplyEquals(TypeHandle that) { return this->SimplyEquals(*that); }
-
- static int AddToUnion(
- TypeHandle type, UnionHandle result, int size, Region* region);
- static int IntersectAux(TypeHandle type, TypeHandle other, UnionHandle result,
- int size, Limits* limits, Region* region);
- static TypeHandle NormalizeUnion(UnionHandle unioned, int size,
- Region* region);
- static TypeHandle NormalizeRangeAndBitset(RangeHandle range, bitset* bits,
- Region* region);
-};
-
+class Type;
// -----------------------------------------------------------------------------
// Bitset types (internal).
-template<class Config>
-class TypeImpl<Config>::BitsetType : public TypeImpl<Config> {
- protected:
- friend class TypeImpl<Config>;
+class BitsetType {
+ public:
+ typedef uint32_t bitset; // Internal
enum : uint32_t {
- #define DECLARE_TYPE(type, value) k##type = (value),
+#define DECLARE_TYPE(type, value) k##type = (value),
BITSET_TYPE_LIST(DECLARE_TYPE)
- #undef DECLARE_TYPE
- kUnusedEOL = 0
+#undef DECLARE_TYPE
+ kUnusedEOL = 0
};
static bitset SignedSmall();
static bitset UnsignedSmall();
- bitset Bitset() { return Config::as_bitset(this); }
-
- static TypeImpl* New(bitset bits) {
- return Config::from_bitset(bits);
- }
- static TypeHandle New(bitset bits, Region* region) {
- return Config::from_bitset(bits, region);
+ bitset Bitset() {
+ return static_cast<bitset>(reinterpret_cast<uintptr_t>(this) ^ 1u);
}
static bool IsInhabited(bitset bits) {
@@ -678,9 +298,9 @@
static double Min(bitset);
static double Max(bitset);
- static bitset Glb(TypeImpl* type); // greatest lower bound that's a bitset
+ static bitset Glb(Type* type); // greatest lower bound that's a bitset
static bitset Glb(double min, double max);
- static bitset Lub(TypeImpl* type); // least upper bound that's a bitset
+ static bitset Lub(Type* type); // least upper bound that's a bitset
static bitset Lub(i::Map* map);
static bitset Lub(i::Object* value);
static bitset Lub(double value);
@@ -695,7 +315,19 @@
static bitset NumberBits(bitset bits);
+ static bool IsBitset(Type* type) {
+ return reinterpret_cast<uintptr_t>(type) & 1;
+ }
+
+ static Type* NewForTesting(bitset bits) { return New(bits); }
+
private:
+ friend class Type;
+
+ static Type* New(bitset bits) {
+ return reinterpret_cast<Type*>(static_cast<uintptr_t>(bits | 1u));
+ }
+
struct Boundary {
bitset internal;
bitset external;
@@ -706,57 +338,302 @@
static inline size_t BoundariesSize();
};
-
// -----------------------------------------------------------------------------
// Superclass for non-bitset types (internal).
-// Contains a tag and a variable number of type or value fields.
-
-template<class Config>
-class TypeImpl<Config>::StructuralType : public TypeImpl<Config> {
+class TypeBase {
protected:
- template<class> friend class TypeImpl;
- friend struct ZoneTypeConfig; // For tags.
- friend struct HeapTypeConfig;
+ friend class Type;
- enum Tag {
- kClassTag,
- kConstantTag,
- kContextTag,
- kArrayTag,
- kFunctionTag,
- kUnionTag
+ enum Kind {
+ kClass,
+ kConstant,
+ kContext,
+ kArray,
+ kFunction,
+ kTuple,
+ kUnion,
+ kRange
};
- int Length() {
- return Config::struct_length(Config::as_struct(this));
- }
- TypeHandle Get(int i) {
- DCHECK(0 <= i && i < this->Length());
- return Config::struct_get(Config::as_struct(this), i);
- }
- void Set(int i, TypeHandle type) {
- DCHECK(0 <= i && i < this->Length());
- Config::struct_set(Config::as_struct(this), i, type);
- }
- void Shrink(int length) {
- DCHECK(2 <= length && length <= this->Length());
- Config::struct_shrink(Config::as_struct(this), length);
- }
- template<class V> i::Handle<V> GetValue(int i) {
- DCHECK(0 <= i && i < this->Length());
- return Config::template struct_get_value<V>(Config::as_struct(this), i);
- }
- template<class V> void SetValue(int i, i::Handle<V> x) {
- DCHECK(0 <= i && i < this->Length());
- Config::struct_set_value(Config::as_struct(this), i, x);
+ Kind kind() const { return kind_; }
+ explicit TypeBase(Kind kind) : kind_(kind) {}
+
+ static bool IsKind(Type* type, Kind kind) {
+ if (BitsetType::IsBitset(type)) return false;
+ TypeBase* base = reinterpret_cast<TypeBase*>(type);
+ return base->kind() == kind;
}
- static TypeHandle New(Tag tag, int length, Region* region) {
- DCHECK(1 <= length);
- return Config::from_struct(Config::struct_create(tag, length, region));
+ // The hacky conversion to/from Type*.
+ static Type* AsType(TypeBase* type) { return reinterpret_cast<Type*>(type); }
+ static TypeBase* FromType(Type* type) {
+ return reinterpret_cast<TypeBase*>(type);
+ }
+
+ private:
+ Kind kind_;
+};
+
+// -----------------------------------------------------------------------------
+// Class types.
+
+class ClassType : public TypeBase {
+ public:
+ i::Handle<i::Map> Map() { return map_; }
+
+ private:
+ friend class Type;
+ friend class BitsetType;
+
+ static Type* New(i::Handle<i::Map> map, Zone* zone) {
+ return AsType(new (zone->New(sizeof(ClassType)))
+ ClassType(BitsetType::Lub(*map), map));
+ }
+
+ static ClassType* cast(Type* type) {
+ DCHECK(IsKind(type, kClass));
+ return static_cast<ClassType*>(FromType(type));
+ }
+
+ ClassType(BitsetType::bitset bitset, i::Handle<i::Map> map)
+ : TypeBase(kClass), bitset_(bitset), map_(map) {}
+
+ BitsetType::bitset Lub() { return bitset_; }
+
+ BitsetType::bitset bitset_;
+ Handle<i::Map> map_;
+};
+
+// -----------------------------------------------------------------------------
+// Constant types.
+
+class ConstantType : public TypeBase {
+ public:
+ i::Handle<i::Object> Value() { return object_; }
+
+ private:
+ friend class Type;
+ friend class BitsetType;
+
+ static Type* New(i::Handle<i::Object> value, Zone* zone) {
+ BitsetType::bitset bitset = BitsetType::Lub(*value);
+ return AsType(new (zone->New(sizeof(ConstantType)))
+ ConstantType(bitset, value));
+ }
+
+ static ConstantType* cast(Type* type) {
+ DCHECK(IsKind(type, kConstant));
+ return static_cast<ConstantType*>(FromType(type));
+ }
+
+ ConstantType(BitsetType::bitset bitset, i::Handle<i::Object> object)
+ : TypeBase(kConstant), bitset_(bitset), object_(object) {}
+
+ BitsetType::bitset Lub() { return bitset_; }
+
+ BitsetType::bitset bitset_;
+ Handle<i::Object> object_;
+};
+// TODO(neis): Also cache value if numerical.
+// TODO(neis): Allow restricting the representation.
+
+// -----------------------------------------------------------------------------
+// Range types.
+
+class RangeType : public TypeBase {
+ public:
+ struct Limits {
+ double min;
+ double max;
+ Limits(double min, double max) : min(min), max(max) {}
+ explicit Limits(RangeType* range) : min(range->Min()), max(range->Max()) {}
+ bool IsEmpty();
+ static Limits Empty() { return Limits(1, 0); }
+ static Limits Intersect(Limits lhs, Limits rhs);
+ static Limits Union(Limits lhs, Limits rhs);
+ };
+
+ double Min() { return limits_.min; }
+ double Max() { return limits_.max; }
+
+ private:
+ friend class Type;
+ friend class BitsetType;
+ friend class UnionType;
+
+ static Type* New(double min, double max, BitsetType::bitset representation,
+ Zone* zone) {
+ return New(Limits(min, max), representation, zone);
+ }
+
+ static bool IsInteger(double x) {
+ return nearbyint(x) == x && !i::IsMinusZero(x); // Allows for infinities.
+ }
+
+ static Type* New(Limits lim, BitsetType::bitset representation, Zone* zone) {
+ DCHECK(IsInteger(lim.min) && IsInteger(lim.max));
+ DCHECK(lim.min <= lim.max);
+ DCHECK(REPRESENTATION(representation) == representation);
+ BitsetType::bitset bits =
+ SEMANTIC(BitsetType::Lub(lim.min, lim.max)) | representation;
+
+ return AsType(new (zone->New(sizeof(RangeType))) RangeType(bits, lim));
+ }
+
+ static RangeType* cast(Type* type) {
+ DCHECK(IsKind(type, kRange));
+ return static_cast<RangeType*>(FromType(type));
+ }
+
+ RangeType(BitsetType::bitset bitset, Limits limits)
+ : TypeBase(kRange), bitset_(bitset), limits_(limits) {}
+
+ BitsetType::bitset Lub() { return bitset_; }
+
+ BitsetType::bitset bitset_;
+ Limits limits_;
+};
+
+// -----------------------------------------------------------------------------
+// Context types.
+
+class ContextType : public TypeBase {
+ public:
+ Type* Outer() { return outer_; }
+
+ private:
+ friend class Type;
+
+ static Type* New(Type* outer, Zone* zone) {
+ return AsType(new (zone->New(sizeof(ContextType))) ContextType(outer));
+ }
+
+ static ContextType* cast(Type* type) {
+ DCHECK(IsKind(type, kContext));
+ return static_cast<ContextType*>(FromType(type));
+ }
+
+ explicit ContextType(Type* outer) : TypeBase(kContext), outer_(outer) {}
+
+ Type* outer_;
+};
+
+// -----------------------------------------------------------------------------
+// Array types.
+
+class ArrayType : public TypeBase {
+ public:
+ Type* Element() { return element_; }
+
+ private:
+ friend class Type;
+
+ explicit ArrayType(Type* element) : TypeBase(kArray), element_(element) {}
+
+ static Type* New(Type* element, Zone* zone) {
+ return AsType(new (zone->New(sizeof(ArrayType))) ArrayType(element));
+ }
+
+ static ArrayType* cast(Type* type) {
+ DCHECK(IsKind(type, kArray));
+ return static_cast<ArrayType*>(FromType(type));
+ }
+
+ Type* element_;
+};
+
+// -----------------------------------------------------------------------------
+// Superclass for types with variable number of type fields.
+class StructuralType : public TypeBase {
+ public:
+ int LengthForTesting() { return Length(); }
+
+ protected:
+ friend class Type;
+
+ int Length() { return length_; }
+
+ Type* Get(int i) {
+ DCHECK(0 <= i && i < this->Length());
+ return elements_[i];
+ }
+
+ void Set(int i, Type* type) {
+ DCHECK(0 <= i && i < this->Length());
+ elements_[i] = type;
+ }
+
+ void Shrink(int length) {
+ DCHECK(2 <= length && length <= this->Length());
+ length_ = length;
+ }
+
+ StructuralType(Kind kind, int length, i::Zone* zone)
+ : TypeBase(kind), length_(length) {
+ elements_ = reinterpret_cast<Type**>(zone->New(sizeof(Type*) * length));
+ }
+
+ private:
+ int length_;
+ Type** elements_;
+};
+
+// -----------------------------------------------------------------------------
+// Function types.
+
+class FunctionType : public StructuralType {
+ public:
+ int Arity() { return this->Length() - 2; }
+ Type* Result() { return this->Get(0); }
+ Type* Receiver() { return this->Get(1); }
+ Type* Parameter(int i) { return this->Get(2 + i); }
+
+ void InitParameter(int i, Type* type) { this->Set(2 + i, type); }
+
+ private:
+ friend class Type;
+
+ FunctionType(Type* result, Type* receiver, int arity, Zone* zone)
+ : StructuralType(kFunction, 2 + arity, zone) {
+ Set(0, result);
+ Set(1, receiver);
+ }
+
+ static Type* New(Type* result, Type* receiver, int arity, Zone* zone) {
+ return AsType(new (zone->New(sizeof(FunctionType)))
+ FunctionType(result, receiver, arity, zone));
+ }
+
+ static FunctionType* cast(Type* type) {
+ DCHECK(IsKind(type, kFunction));
+ return static_cast<FunctionType*>(FromType(type));
}
};
+// -----------------------------------------------------------------------------
+// Tuple types.
+
+class TupleType : public StructuralType {
+ public:
+ int Arity() { return this->Length(); }
+ Type* Element(int i) { return this->Get(i); }
+
+ void InitElement(int i, Type* type) { this->Set(i, type); }
+
+ private:
+ friend class Type;
+
+ TupleType(int length, Zone* zone) : StructuralType(kTuple, length, zone) {}
+
+ static Type* New(int length, Zone* zone) {
+ return AsType(new (zone->New(sizeof(TupleType))) TupleType(length, zone));
+ }
+
+ static TupleType* cast(Type* type) {
+ DCHECK(IsKind(type, kTuple));
+ return static_cast<TupleType*>(FromType(type));
+ }
+};
// -----------------------------------------------------------------------------
// Union types (internal).
@@ -765,420 +642,329 @@
// - at most one field is a bitset, and it must go into index 0
// - no field is a union
// - no field is a subtype of any other field
-template<class Config>
-class TypeImpl<Config>::UnionType : public StructuralType {
- public:
- static UnionHandle New(int length, Region* region) {
- return Config::template cast<UnionType>(
- StructuralType::New(StructuralType::kUnionTag, length, region));
+class UnionType : public StructuralType {
+ private:
+ friend Type;
+ friend BitsetType;
+
+ UnionType(int length, Zone* zone) : StructuralType(kUnion, length, zone) {}
+
+ static Type* New(int length, Zone* zone) {
+ return AsType(new (zone->New(sizeof(UnionType))) UnionType(length, zone));
}
- static UnionType* cast(TypeImpl* type) {
- DCHECK(type->IsUnion());
- return static_cast<UnionType*>(type);
+ static UnionType* cast(Type* type) {
+ DCHECK(IsKind(type, kUnion));
+ return static_cast<UnionType*>(FromType(type));
}
bool Wellformed();
};
-
-// -----------------------------------------------------------------------------
-// Class types.
-
-template<class Config>
-class TypeImpl<Config>::ClassType : public StructuralType {
+class Type {
public:
- i::Handle<i::Map> Map() {
- return Config::is_class(this) ? Config::as_class(this) :
- this->template GetValue<i::Map>(1);
+ typedef BitsetType::bitset bitset; // Internal
+
+// Constructors.
+#define DEFINE_TYPE_CONSTRUCTOR(type, value) \
+ static Type* type() { return BitsetType::New(BitsetType::k##type); }
+ PROPER_BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR)
+#undef DEFINE_TYPE_CONSTRUCTOR
+
+ static Type* SignedSmall() {
+ return BitsetType::New(BitsetType::SignedSmall());
+ }
+ static Type* UnsignedSmall() {
+ return BitsetType::New(BitsetType::UnsignedSmall());
}
- static ClassHandle New(i::Handle<i::Map> map, Region* region) {
- ClassHandle type =
- Config::template cast<ClassType>(Config::from_class(map, region));
- if (!type->IsClass()) {
- type = Config::template cast<ClassType>(
- StructuralType::New(StructuralType::kClassTag, 2, region));
- type->Set(0, BitsetType::New(BitsetType::Lub(*map), region));
- type->SetValue(1, map);
+ static Type* Class(i::Handle<i::Map> map, Zone* zone) {
+ return ClassType::New(map, zone);
+ }
+ static Type* Constant(i::Handle<i::Object> value, Zone* zone) {
+ return ConstantType::New(value, zone);
+ }
+ static Type* Range(double min, double max, Zone* zone) {
+ return RangeType::New(min, max, REPRESENTATION(BitsetType::kTagged |
+ BitsetType::kUntaggedNumber),
+ zone);
+ }
+ static Type* Context(Type* outer, Zone* zone) {
+ return ContextType::New(outer, zone);
+ }
+ static Type* Array(Type* element, Zone* zone) {
+ return ArrayType::New(element, zone);
+ }
+ static Type* Function(Type* result, Type* receiver, int arity, Zone* zone) {
+ return FunctionType::New(result, receiver, arity, zone);
+ }
+ static Type* Function(Type* result, Zone* zone) {
+ return Function(result, Any(), 0, zone);
+ }
+ static Type* Function(Type* result, Type* param0, Zone* zone) {
+ Type* function = Function(result, Any(), 1, zone);
+ function->AsFunction()->InitParameter(0, param0);
+ return function;
+ }
+ static Type* Function(Type* result, Type* param0, Type* param1, Zone* zone) {
+ Type* function = Function(result, Any(), 2, zone);
+ function->AsFunction()->InitParameter(0, param0);
+ function->AsFunction()->InitParameter(1, param1);
+ return function;
+ }
+ static Type* Function(Type* result, Type* param0, Type* param1, Type* param2,
+ Zone* zone) {
+ Type* function = Function(result, Any(), 3, zone);
+ function->AsFunction()->InitParameter(0, param0);
+ function->AsFunction()->InitParameter(1, param1);
+ function->AsFunction()->InitParameter(2, param2);
+ return function;
+ }
+ static Type* Function(Type* result, int arity, Type** params, Zone* zone) {
+ Type* function = Function(result, Any(), arity, zone);
+ for (int i = 0; i < arity; ++i) {
+ function->AsFunction()->InitParameter(i, params[i]);
}
- return type;
+ return function;
+ }
+ static Type* Tuple(Type* first, Type* second, Type* third, Zone* zone) {
+ Type* tuple = TupleType::New(3, zone);
+ tuple->AsTuple()->InitElement(0, first);
+ tuple->AsTuple()->InitElement(1, second);
+ tuple->AsTuple()->InitElement(2, third);
+ return tuple;
}
- static ClassType* cast(TypeImpl* type) {
- DCHECK(type->IsClass());
- return static_cast<ClassType*>(type);
+#define CONSTRUCT_SIMD_TYPE(NAME, Name, name, lane_count, lane_type) \
+ static Type* Name(Isolate* isolate, Zone* zone);
+ SIMD128_TYPES(CONSTRUCT_SIMD_TYPE)
+#undef CONSTRUCT_SIMD_TYPE
+
+ static Type* Union(Type* type1, Type* type2, Zone* reg);
+ static Type* Intersect(Type* type1, Type* type2, Zone* reg);
+
+ static Type* Of(double value, Zone* zone) {
+ return BitsetType::New(BitsetType::ExpandInternals(BitsetType::Lub(value)));
+ }
+ static Type* Of(i::Object* value, Zone* zone) {
+ return BitsetType::New(BitsetType::ExpandInternals(BitsetType::Lub(value)));
+ }
+ static Type* Of(i::Handle<i::Object> value, Zone* zone) {
+ return Of(*value, zone);
}
- private:
- template<class> friend class TypeImpl;
- bitset Lub() {
- return Config::is_class(this) ?
- BitsetType::Lub(*Config::as_class(this)) :
- this->Get(0)->AsBitset();
+ // Extraction of components.
+ static Type* Representation(Type* t, Zone* zone);
+ static Type* Semantic(Type* t, Zone* zone);
+
+ // Predicates.
+ bool IsInhabited() { return BitsetType::IsInhabited(this->BitsetLub()); }
+
+ bool Is(Type* that) { return this == that || this->SlowIs(that); }
+ bool Maybe(Type* that);
+ bool Equals(Type* that) { return this->Is(that) && that->Is(this); }
+
+ // Equivalent to Constant(val)->Is(this), but avoiding allocation.
+ bool Contains(i::Object* val);
+ bool Contains(i::Handle<i::Object> val) { return this->Contains(*val); }
+
+ // State-dependent versions of the above that consider subtyping between
+ // a constant and its map class.
+ static Type* NowOf(i::Object* value, Zone* zone);
+ static Type* NowOf(i::Handle<i::Object> value, Zone* zone) {
+ return NowOf(*value, zone);
}
-};
+ bool NowIs(Type* that);
+ bool NowContains(i::Object* val);
+ bool NowContains(i::Handle<i::Object> val) { return this->NowContains(*val); }
+ bool NowStable();
-// -----------------------------------------------------------------------------
-// Constant types.
+ // Inspection.
+ bool IsRange() { return IsKind(TypeBase::kRange); }
+ bool IsClass() { return IsKind(TypeBase::kClass); }
+ bool IsConstant() { return IsKind(TypeBase::kConstant); }
+ bool IsContext() { return IsKind(TypeBase::kContext); }
+ bool IsArray() { return IsKind(TypeBase::kArray); }
+ bool IsFunction() { return IsKind(TypeBase::kFunction); }
+ bool IsTuple() { return IsKind(TypeBase::kTuple); }
-template<class Config>
-class TypeImpl<Config>::ConstantType : public StructuralType {
- public:
- i::Handle<i::Object> Value() { return this->template GetValue<i::Object>(1); }
+ ClassType* AsClass() { return ClassType::cast(this); }
+ ConstantType* AsConstant() { return ConstantType::cast(this); }
+ RangeType* AsRange() { return RangeType::cast(this); }
+ ContextType* AsContext() { return ContextType::cast(this); }
+ ArrayType* AsArray() { return ArrayType::cast(this); }
+ FunctionType* AsFunction() { return FunctionType::cast(this); }
+ TupleType* AsTuple() { return TupleType::cast(this); }
- static ConstantHandle New(i::Handle<i::Object> value, Region* region) {
- ConstantHandle type = Config::template cast<ConstantType>(
- StructuralType::New(StructuralType::kConstantTag, 2, region));
- type->Set(0, BitsetType::New(BitsetType::Lub(*value), region));
- type->SetValue(1, value);
- return type;
+ // Minimum and maximum of a numeric type.
+ // These functions do not distinguish between -0 and +0. If the type equals
+ // kNaN, they return NaN; otherwise kNaN is ignored. Only call these
+ // functions on subtypes of Number.
+ double Min();
+ double Max();
+
+ // 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.
+ Type* GetRange();
+
+ static bool IsInteger(i::Object* x);
+ static bool IsInteger(double x) {
+ return nearbyint(x) == x && !i::IsMinusZero(x); // Allows for infinities.
}
- static ConstantType* cast(TypeImpl* type) {
- DCHECK(type->IsConstant());
- return static_cast<ConstantType*>(type);
- }
+ int NumClasses();
+ int NumConstants();
- private:
- template<class> friend class TypeImpl;
- bitset Lub() { return this->Get(0)->AsBitset(); }
-};
-// TODO(neis): Also cache value if numerical.
-// TODO(neis): Allow restricting the representation.
+ template <class T>
+ class Iterator {
+ public:
+ bool Done() const { return index_ < 0; }
+ i::Handle<T> Current();
+ void Advance();
+ private:
+ friend class Type;
-// -----------------------------------------------------------------------------
-// Range types.
+ Iterator() : index_(-1) {}
+ explicit Iterator(Type* type) : type_(type), index_(-1) { Advance(); }
-template <class Config>
-class TypeImpl<Config>::RangeType : public TypeImpl<Config> {
- public:
- double Min() { return Config::range_get_double(Config::as_range(this), 0); }
- double Max() { return Config::range_get_double(Config::as_range(this), 1); }
+ inline bool matches(Type* type);
+ inline Type* get_type();
- static RangeHandle New(double min, double max, TypeHandle representation,
- Region* region) {
- DCHECK(IsInteger(min) && IsInteger(max));
- DCHECK(min <= max);
- bitset representation_bits = representation->AsBitset();
- DCHECK(REPRESENTATION(representation_bits) == representation_bits);
-
- typename Config::template Handle<typename Config::Range>::type range =
- Config::range_create(region);
-
- bitset bits = SEMANTIC(BitsetType::Lub(min, max)) | representation_bits;
- Config::range_set_bitset(range, bits);
- Config::range_set_double(range, 0, min, region);
- Config::range_set_double(range, 1, max, region);
- return Config::template cast<RangeType>(Config::from_range(range));
- }
-
- static RangeHandle New(Limits lim, bitset representation, Region* region) {
- return New(lim.min, lim.max, BitsetType::New(representation, region),
- region);
- }
-
- static RangeType* cast(TypeImpl* type) {
- DCHECK(type->IsRange());
- return static_cast<RangeType*>(type);
- }
-
- private:
- template<class> friend class TypeImpl;
- bitset Lub() {
- return Config::range_get_bitset(Config::as_range(this));
- }
-};
-
-
-// -----------------------------------------------------------------------------
-// Context types.
-
-template<class Config>
-class TypeImpl<Config>::ContextType : public StructuralType {
- public:
- TypeHandle Outer() { return this->Get(0); }
-
- static ContextHandle New(TypeHandle outer, Region* region) {
- ContextHandle type = Config::template cast<ContextType>(
- StructuralType::New(StructuralType::kContextTag, 1, region));
- type->Set(0, outer);
- return type;
- }
-
- static ContextType* cast(TypeImpl* type) {
- DCHECK(type->IsContext());
- return static_cast<ContextType*>(type);
- }
-};
-
-
-// -----------------------------------------------------------------------------
-// Array types.
-
-template<class Config>
-class TypeImpl<Config>::ArrayType : public StructuralType {
- public:
- TypeHandle Element() { return this->Get(0); }
-
- static ArrayHandle New(TypeHandle element, Region* region) {
- ArrayHandle type = Config::template cast<ArrayType>(
- StructuralType::New(StructuralType::kArrayTag, 1, region));
- type->Set(0, element);
- return type;
- }
-
- static ArrayType* cast(TypeImpl* type) {
- DCHECK(type->IsArray());
- return static_cast<ArrayType*>(type);
- }
-};
-
-
-// -----------------------------------------------------------------------------
-// Function types.
-
-template<class Config>
-class TypeImpl<Config>::FunctionType : public StructuralType {
- public:
- int Arity() { return this->Length() - 2; }
- TypeHandle Result() { return this->Get(0); }
- TypeHandle Receiver() { return this->Get(1); }
- TypeHandle Parameter(int i) { return this->Get(2 + i); }
-
- void InitParameter(int i, TypeHandle type) { this->Set(2 + i, type); }
-
- static FunctionHandle New(
- TypeHandle result, TypeHandle receiver, int arity, Region* region) {
- FunctionHandle type = Config::template cast<FunctionType>(
- StructuralType::New(StructuralType::kFunctionTag, 2 + arity, region));
- type->Set(0, result);
- type->Set(1, receiver);
- return type;
- }
-
- static FunctionType* cast(TypeImpl* type) {
- DCHECK(type->IsFunction());
- return static_cast<FunctionType*>(type);
- }
-};
-
-
-// -----------------------------------------------------------------------------
-// Type iterators.
-
-template<class Config> template<class T>
-class TypeImpl<Config>::Iterator {
- public:
- bool Done() const { return index_ < 0; }
- i::Handle<T> Current();
- void Advance();
-
- private:
- template<class> friend class TypeImpl;
-
- Iterator() : index_(-1) {}
- explicit Iterator(TypeHandle type) : type_(type), index_(-1) {
- Advance();
- }
-
- inline bool matches(TypeHandle type);
- inline TypeHandle get_type();
-
- TypeHandle type_;
- int index_;
-};
-
-
-// -----------------------------------------------------------------------------
-// Zone-allocated types; they are either (odd) integers to represent bitsets, or
-// (even) pointers to structures for everything else.
-
-struct ZoneTypeConfig {
- typedef TypeImpl<ZoneTypeConfig> Type;
- class Base {};
- typedef void* Struct;
- // Hack: the Struct and Range types can be aliased in memory, the first
- // pointer word of each both must be the tag (kRangeStructTag for Range,
- // anything else for Struct) so that we can differentiate them.
- struct Range {
- void* tag;
- int bitset;
- double limits[2];
+ Type* type_;
+ int index_;
};
- typedef i::Zone Region;
- template<class T> struct Handle { typedef T* type; };
- static const int kRangeStructTag = 0x1000;
-
- template<class T> static inline T* null_handle() { return nullptr; }
- template<class T> static inline T* handle(T* type);
- template<class T> static inline T* cast(Type* type);
-
- static inline bool is_bitset(Type* type);
- static inline bool is_class(Type* type);
- static inline bool is_struct(Type* type, int tag);
- static inline bool is_range(Type* type);
-
- static inline Type::bitset as_bitset(Type* type);
- static inline i::Handle<i::Map> as_class(Type* type);
- static inline Struct* as_struct(Type* type);
- static inline Range* as_range(Type* type);
-
- static inline Type* from_bitset(Type::bitset);
- static inline Type* from_bitset(Type::bitset, Zone* zone);
- static inline Type* from_class(i::Handle<i::Map> map, Zone* zone);
- static inline Type* from_struct(Struct* structured);
- static inline Type* from_range(Range* range);
-
- static inline Struct* struct_create(int tag, int length, Zone* zone);
- static inline void struct_shrink(Struct* structure, int length);
- static inline int struct_tag(Struct* structure);
- static inline int struct_length(Struct* structure);
- static inline Type* struct_get(Struct* structure, int i);
- static inline void struct_set(Struct* structure, int i, Type* type);
- template<class V>
- static inline i::Handle<V> struct_get_value(Struct* structure, int i);
- template<class V> static inline void struct_set_value(
- Struct* structure, int i, i::Handle<V> x);
-
- static inline Range* range_create(Zone* zone);
- static inline int range_get_bitset(Range* range);
- static inline void range_set_bitset(Range* range, int);
- static inline double range_get_double(Range*, int index);
- static inline void range_set_double(Range*, int index, double value, Zone*);
-};
-
-typedef TypeImpl<ZoneTypeConfig> Type;
-
-
-// -----------------------------------------------------------------------------
-// Heap-allocated types; either smis for bitsets, maps for classes, boxes for
-// constants, or fixed arrays for unions.
-
-struct HeapTypeConfig {
- typedef TypeImpl<HeapTypeConfig> Type;
- typedef i::Object Base;
- typedef i::FixedArray Struct;
- typedef i::FixedArray Range;
- typedef i::Isolate Region;
- template<class T> struct Handle { typedef i::Handle<T> type; };
-
- static const int kRangeStructTag = 0xffff;
-
- template<class T> static inline i::Handle<T> null_handle() {
- return i::Handle<T>();
+ Iterator<i::Map> Classes() {
+ if (this->IsBitset()) return Iterator<i::Map>();
+ return Iterator<i::Map>(this);
}
- template<class T> static inline i::Handle<T> handle(T* type);
- template<class T> static inline i::Handle<T> cast(i::Handle<Type> type);
+ Iterator<i::Object> Constants() {
+ if (this->IsBitset()) return Iterator<i::Object>();
+ return Iterator<i::Object>(this);
+ }
- static inline bool is_bitset(Type* type);
- static inline bool is_class(Type* type);
- static inline bool is_struct(Type* type, int tag);
- static inline bool is_range(Type* type);
+ // Printing.
- static inline Type::bitset as_bitset(Type* type);
- static inline i::Handle<i::Map> as_class(Type* type);
- static inline i::Handle<Struct> as_struct(Type* type);
- static inline i::Handle<Range> as_range(Type* type);
+ enum PrintDimension { BOTH_DIMS, SEMANTIC_DIM, REPRESENTATION_DIM };
- static inline Type* from_bitset(Type::bitset);
- static inline i::Handle<Type> from_bitset(Type::bitset, Isolate* isolate);
- static inline i::Handle<Type> from_class(
- i::Handle<i::Map> map, Isolate* isolate);
- static inline i::Handle<Type> from_struct(i::Handle<Struct> structure);
- static inline i::Handle<Type> from_range(i::Handle<Range> range);
+ void PrintTo(std::ostream& os, PrintDimension dim = BOTH_DIMS); // NOLINT
- static inline i::Handle<Struct> struct_create(
- int tag, int length, Isolate* isolate);
- static inline void struct_shrink(i::Handle<Struct> structure, int length);
- static inline int struct_tag(i::Handle<Struct> structure);
- static inline int struct_length(i::Handle<Struct> structure);
- static inline i::Handle<Type> struct_get(i::Handle<Struct> structure, int i);
- static inline void struct_set(
- i::Handle<Struct> structure, int i, i::Handle<Type> type);
- template<class V>
- static inline i::Handle<V> struct_get_value(
- i::Handle<Struct> structure, int i);
- template<class V>
- static inline void struct_set_value(
- i::Handle<Struct> structure, int i, i::Handle<V> x);
+#ifdef DEBUG
+ void Print();
+#endif
- static inline i::Handle<Range> range_create(Isolate* isolate);
- static inline int range_get_bitset(i::Handle<Range> range);
- static inline void range_set_bitset(i::Handle<Range> range, int value);
- static inline double range_get_double(i::Handle<Range> range, int index);
- static inline void range_set_double(i::Handle<Range> range, int index,
- double value, Isolate* isolate);
+ // Helpers for testing.
+ bool IsBitsetForTesting() { return IsBitset(); }
+ bool IsUnionForTesting() { return IsUnion(); }
+ bitset AsBitsetForTesting() { return AsBitset(); }
+ UnionType* AsUnionForTesting() { return AsUnion(); }
+
+ private:
+ // Friends.
+ template <class>
+ friend class Iterator;
+ friend BitsetType;
+ friend UnionType;
+
+ // Internal inspection.
+ bool IsKind(TypeBase::Kind kind) { return TypeBase::IsKind(this, kind); }
+
+ bool IsNone() { return this == None(); }
+ bool IsAny() { return this == Any(); }
+ bool IsBitset() { return BitsetType::IsBitset(this); }
+ bool IsUnion() { return IsKind(TypeBase::kUnion); }
+
+ bitset AsBitset() {
+ DCHECK(this->IsBitset());
+ return reinterpret_cast<BitsetType*>(this)->Bitset();
+ }
+ UnionType* AsUnion() { return UnionType::cast(this); }
+
+ bitset Representation();
+
+ // Auxiliary functions.
+ bool SemanticMaybe(Type* that);
+
+ bitset BitsetGlb() { return BitsetType::Glb(this); }
+ bitset BitsetLub() { return BitsetType::Lub(this); }
+
+ bool SlowIs(Type* that);
+ bool SemanticIs(Type* that);
+
+ static bool Overlap(RangeType* lhs, RangeType* rhs);
+ static bool Contains(RangeType* lhs, RangeType* rhs);
+ static bool Contains(RangeType* range, ConstantType* constant);
+ static bool Contains(RangeType* range, i::Object* val);
+
+ static int UpdateRange(Type* type, UnionType* result, int size, Zone* zone);
+
+ static RangeType::Limits IntersectRangeAndBitset(Type* range, Type* bits,
+ Zone* zone);
+ static RangeType::Limits ToLimits(bitset bits, Zone* zone);
+
+ bool SimplyEquals(Type* that);
+
+ static int AddToUnion(Type* type, UnionType* result, int size, Zone* zone);
+ static int IntersectAux(Type* type, Type* other, UnionType* result, int size,
+ RangeType::Limits* limits, Zone* zone);
+ static Type* NormalizeUnion(Type* unioned, int size, Zone* zone);
+ static Type* NormalizeRangeAndBitset(Type* range, bitset* bits, Zone* zone);
};
-typedef TypeImpl<HeapTypeConfig> HeapType;
-
-
// -----------------------------------------------------------------------------
// Type bounds. A simple struct to represent a pair of lower/upper types.
-template<class Config>
-struct BoundsImpl {
- typedef TypeImpl<Config> Type;
- typedef typename Type::TypeHandle TypeHandle;
- typedef typename Type::Region Region;
+struct Bounds {
+ Type* lower;
+ Type* upper;
- TypeHandle lower;
- TypeHandle upper;
-
- BoundsImpl() : // Make sure accessing uninitialized bounds crashes big-time.
- lower(Config::template null_handle<Type>()),
- upper(Config::template null_handle<Type>()) {}
- explicit BoundsImpl(TypeHandle t) : lower(t), upper(t) {}
- BoundsImpl(TypeHandle l, TypeHandle u) : lower(l), upper(u) {
- DCHECK(lower->Is(upper));
- }
+ Bounds()
+ : // Make sure accessing uninitialized bounds crashes big-time.
+ lower(nullptr),
+ upper(nullptr) {}
+ explicit Bounds(Type* t) : lower(t), upper(t) {}
+ Bounds(Type* l, Type* u) : lower(l), upper(u) { DCHECK(lower->Is(upper)); }
// Unrestricted bounds.
- static BoundsImpl Unbounded() {
- return BoundsImpl(Type::None(), Type::Any());
- }
+ static Bounds Unbounded() { return Bounds(Type::None(), Type::Any()); }
// Meet: both b1 and b2 are known to hold.
- static BoundsImpl Both(BoundsImpl b1, BoundsImpl b2, Region* region) {
- TypeHandle lower = Type::Union(b1.lower, b2.lower, region);
- TypeHandle upper = Type::Intersect(b1.upper, b2.upper, region);
+ static Bounds Both(Bounds b1, Bounds b2, Zone* zone) {
+ Type* lower = Type::Union(b1.lower, b2.lower, zone);
+ Type* upper = Type::Intersect(b1.upper, b2.upper, zone);
// Lower bounds are considered approximate, correct as necessary.
if (!lower->Is(upper)) lower = upper;
- return BoundsImpl(lower, upper);
+ return Bounds(lower, upper);
}
// Join: either b1 or b2 is known to hold.
- static BoundsImpl Either(BoundsImpl b1, BoundsImpl b2, Region* region) {
- TypeHandle lower = Type::Intersect(b1.lower, b2.lower, region);
- TypeHandle upper = Type::Union(b1.upper, b2.upper, region);
- return BoundsImpl(lower, upper);
+ static Bounds Either(Bounds b1, Bounds b2, Zone* zone) {
+ Type* lower = Type::Intersect(b1.lower, b2.lower, zone);
+ Type* upper = Type::Union(b1.upper, b2.upper, zone);
+ return Bounds(lower, upper);
}
- static BoundsImpl NarrowLower(BoundsImpl b, TypeHandle t, Region* region) {
- TypeHandle lower = Type::Union(b.lower, t, region);
+ static Bounds NarrowLower(Bounds b, Type* t, Zone* zone) {
+ Type* lower = Type::Union(b.lower, t, zone);
// Lower bounds are considered approximate, correct as necessary.
if (!lower->Is(b.upper)) lower = b.upper;
- return BoundsImpl(lower, b.upper);
+ return Bounds(lower, b.upper);
}
- static BoundsImpl NarrowUpper(BoundsImpl b, TypeHandle t, Region* region) {
- TypeHandle lower = b.lower;
- TypeHandle upper = Type::Intersect(b.upper, t, region);
+ static Bounds NarrowUpper(Bounds b, Type* t, Zone* zone) {
+ Type* lower = b.lower;
+ Type* upper = Type::Intersect(b.upper, t, zone);
// Lower bounds are considered approximate, correct as necessary.
if (!lower->Is(upper)) lower = upper;
- return BoundsImpl(lower, upper);
+ return Bounds(lower, upper);
}
- bool Narrows(BoundsImpl that) {
+ bool Narrows(Bounds that) {
return that.lower->Is(this->lower) && this->upper->Is(that.upper);
}
};
-typedef BoundsImpl<ZoneTypeConfig> Bounds;
-
} // namespace internal
} // namespace v8