Index: src/types.h |
diff --git a/src/types.h b/src/types.h |
index b293376add31f41e3faac08d3c76eda337df4bf0..e3a0cfefb5ab97d9f2eaa990535167727a064b6a 100644 |
--- a/src/types.h |
+++ b/src/types.h |
@@ -259,345 +259,188 @@ namespace internal { |
INTERNAL_BITSET_TYPE_LIST(V) \ |
SEMANTIC_BITSET_TYPE_LIST(V) |
+class Type; |
// ----------------------------------------------------------------------------- |
-// 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. |
+// Bitset types (internal). |
+class BitsetType { |
+ public: |
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; |
- class TupleType; |
- |
- 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::template Handle<TupleType>::type TupleHandle; |
- 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; |
- } |
- static TypeHandle Tuple(TypeHandle first, TypeHandle second, TypeHandle third, |
- Region* region) { |
- TupleHandle tuple = TupleType::New(3, region); |
- tuple->InitElement(0, first); |
- tuple->InitElement(1, second); |
- tuple->InitElement(2, third); |
- return tuple; |
- } |
- |
-#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 |
+ enum : uint32_t { |
+#define DECLARE_TYPE(type, value) k##type = (value), |
+ BITSET_TYPE_LIST(DECLARE_TYPE) |
+#undef DECLARE_TYPE |
+ kUnusedEOL = 0 |
+ }; |
- static TypeHandle Union(TypeHandle type1, TypeHandle type2, Region* reg); |
- static TypeHandle Intersect(TypeHandle type1, TypeHandle type2, Region* reg); |
+ static bitset SignedSmall(); |
+ static bitset UnsignedSmall(); |
- 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); |
+ bitset Bitset() { |
+ return static_cast<bitset>(reinterpret_cast<uintptr_t>(this) ^ 1u); |
} |
- static TypeHandle Of(i::Handle<i::Object> value, Region* region) { |
- return Of(*value, region); |
+ |
+ static bool IsInhabited(bitset bits) { |
+ return SEMANTIC(bits) != kNone && REPRESENTATION(bits) != kNone; |
} |
- // Extraction of components. |
- static TypeHandle Representation(TypeHandle t, Region* region); |
- static TypeHandle Semantic(TypeHandle t, Region* region); |
+ static bool SemanticIsInhabited(bitset bits) { |
+ return SEMANTIC(bits) != kNone; |
+ } |
- // Predicates. |
- bool IsInhabited() { return BitsetType::IsInhabited(this->BitsetLub()); } |
+ static bool Is(bitset bits1, bitset bits2) { |
+ return (bits1 | bits2) == bits2; |
+ } |
- bool Is(TypeImpl* that) { return this == that || this->SlowIs(that); } |
- template<class TypeHandle> |
- bool Is(TypeHandle that) { return this->Is(*that); } |
+ static double Min(bitset); |
+ static double Max(bitset); |
- bool Maybe(TypeImpl* that); |
- template<class TypeHandle> |
- bool Maybe(TypeHandle that) { return this->Maybe(*that); } |
+ static bitset Glb(Type* type); // greatest lower bound that's a bitset |
+ static bitset Glb(double min, double max); |
+ 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); |
+ static bitset Lub(double min, double max); |
+ static bitset ExpandInternals(bitset bits); |
- bool Equals(TypeImpl* that) { return this->Is(that) && that->Is(this); } |
- template<class TypeHandle> |
- bool Equals(TypeHandle that) { return this->Equals(*that); } |
+ static const char* Name(bitset); |
+ static void Print(std::ostream& os, bitset); // NOLINT |
+#ifdef DEBUG |
+ static void Print(bitset); |
+#endif |
- // 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); } |
+ static bitset NumberBits(bitset bits); |
- // 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); |
+ static bool IsBitset(Type* type) { |
+ return reinterpret_cast<uintptr_t>(type) & 1; |
} |
- 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(); |
+ static Type* NewForTesting(bitset bits) { return New(bits); } |
- // Inspection. |
+ private: |
+ friend class Type; |
- 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); |
+ static Type* New(bitset bits) { |
+ return reinterpret_cast<Type*>(static_cast<uintptr_t>(bits | 1u)); |
} |
- bool IsArray() { |
- return Config::is_struct(this, StructuralType::kArrayTag); |
- } |
- bool IsFunction() { |
- return Config::is_struct(this, StructuralType::kFunctionTag); |
- } |
- bool IsTuple() { return Config::is_struct(this, StructuralType::kTupleTag); } |
- 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); } |
+ struct Boundary { |
+ bitset internal; |
+ bitset external; |
+ double min; |
+ }; |
+ static const Boundary BoundariesArray[]; |
+ static inline const Boundary* Boundaries(); |
+ static inline size_t BoundariesSize(); |
+}; |
- // 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(); |
+// ----------------------------------------------------------------------------- |
+// Superclass for non-bitset types (internal). |
+class TypeBase { |
+ protected: |
+ friend class Type; |
+ |
+ enum Kind { |
+ kClass, |
+ kConstant, |
+ kContext, |
+ kArray, |
+ kFunction, |
+ kTuple, |
+ kUnion, |
+ kRange |
+ }; |
- // 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(); |
+ Kind kind() const { return kind_; } |
+ explicit TypeBase(Kind kind) : kind_(kind) {} |
- 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()); |
+ static bool IsKind(Type* type, Kind kind) { |
+ if (BitsetType::IsBitset(type)) return false; |
+ TypeBase* base = reinterpret_cast<TypeBase*>(type); |
+ return base->kind() == kind; |
} |
- 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)); |
+ // 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); |
} |
- // Casting and conversion. |
+ private: |
+ Kind kind_; |
+}; |
- static inline TypeImpl* cast(typename Config::Base* object); |
+// ----------------------------------------------------------------------------- |
+// Class types. |
- // Printing. |
+class ClassType : public TypeBase { |
+ public: |
+ i::Handle<i::Map> Map() { return map_; } |
- enum PrintDimension { BOTH_DIMS, SEMANTIC_DIM, REPRESENTATION_DIM }; |
+ private: |
+ friend class Type; |
+ friend class BitsetType; |
- void PrintTo(std::ostream& os, PrintDimension dim = BOTH_DIMS); // NOLINT |
+ static Type* New(i::Handle<i::Map> map, Zone* zone) { |
+ return AsType(new (zone->New(sizeof(ClassType))) |
+ ClassType(BitsetType::Lub(*map), map)); |
+ } |
-#ifdef DEBUG |
- void Print(); |
-#endif |
+ static ClassType* cast(Type* type) { |
+ DCHECK(IsKind(type, kClass)); |
+ return static_cast<ClassType*>(FromType(type)); |
+ } |
- bool IsUnionForTesting() { return IsUnion(); } |
+ ClassType(BitsetType::bitset bitset, i::Handle<i::Map> map) |
+ : TypeBase(kClass), bitset_(bitset), map_(map) {} |
- protected: |
- // Friends. |
+ BitsetType::bitset Lub() { return bitset_; } |
- template<class> friend class Iterator; |
- template<class> friend class TypeImpl; |
+ BitsetType::bitset bitset_; |
+ Handle<i::Map> map_; |
+}; |
- // Handle conversion. |
+// ----------------------------------------------------------------------------- |
+// Constant types. |
- template<class T> |
- static typename Config::template Handle<T>::type handle(T* type) { |
- return Config::handle(type); |
- } |
- TypeImpl* unhandle() { return this; } |
+class ConstantType : public TypeBase { |
+ public: |
+ i::Handle<i::Object> Value() { return object_; } |
- // Internal inspection. |
+ private: |
+ friend class Type; |
+ friend class BitsetType; |
- 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); } |
+ 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)); |
+ } |
- bitset AsBitset() { |
- DCHECK(this->IsBitset()); |
- return static_cast<BitsetType*>(this)->Bitset(); |
+ static ConstantType* cast(Type* type) { |
+ DCHECK(IsKind(type, kConstant)); |
+ return static_cast<ConstantType*>(FromType(type)); |
} |
- UnionType* AsUnion() { return UnionType::cast(this); } |
- bitset Representation(); |
+ ConstantType(BitsetType::bitset bitset, i::Handle<i::Object> object) |
+ : TypeBase(kConstant), bitset_(bitset), object_(object) {} |
- // Auxiliary functions. |
- bool SemanticMaybe(TypeImpl* that); |
+ BitsetType::bitset Lub() { return bitset_; } |
- bitset BitsetGlb() { return BitsetType::Glb(this); } |
- bitset BitsetLub() { return BitsetType::Lub(this); } |
+ BitsetType::bitset bitset_; |
+ Handle<i::Object> object_; |
+}; |
+// TODO(neis): Also cache value if numerical. |
+// TODO(neis): Allow restricting the representation. |
- bool SlowIs(TypeImpl* that); |
- bool SemanticIs(TypeImpl* that); |
+// ----------------------------------------------------------------------------- |
+// Range types. |
+class RangeType : public TypeBase { |
+ public: |
struct Limits { |
double min; |
double max; |
@@ -609,155 +452,187 @@ class TypeImpl : public Config::Base { |
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); |
+ double Min() { return limits_.min; } |
+ double Max() { return limits_.max; } |
- 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); |
-}; |
+ 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); |
+ } |
-// ----------------------------------------------------------------------------- |
-// Bitset types (internal). |
+ static bool IsInteger(double x) { |
+ return nearbyint(x) == x && !i::IsMinusZero(x); // Allows for infinities. |
+ } |
-template<class Config> |
-class TypeImpl<Config>::BitsetType : public TypeImpl<Config> { |
- protected: |
- friend class TypeImpl<Config>; |
+ 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; |
- enum : uint32_t { |
- #define DECLARE_TYPE(type, value) k##type = (value), |
- BITSET_TYPE_LIST(DECLARE_TYPE) |
- #undef DECLARE_TYPE |
- kUnusedEOL = 0 |
- }; |
+ return AsType(new (zone->New(sizeof(RangeType))) RangeType(bits, lim)); |
+ } |
- static bitset SignedSmall(); |
- static bitset UnsignedSmall(); |
+ static RangeType* cast(Type* type) { |
+ DCHECK(IsKind(type, kRange)); |
+ return static_cast<RangeType*>(FromType(type)); |
+ } |
- bitset Bitset() { return Config::as_bitset(this); } |
+ RangeType(BitsetType::bitset bitset, Limits limits) |
+ : TypeBase(kRange), bitset_(bitset), limits_(limits) {} |
- static TypeImpl* New(bitset bits) { |
- return Config::from_bitset(bits); |
- } |
- static TypeHandle New(bitset bits, Region* region) { |
- return Config::from_bitset(bits, region); |
- } |
+ BitsetType::bitset Lub() { return bitset_; } |
- static bool IsInhabited(bitset bits) { |
- return SEMANTIC(bits) != kNone && REPRESENTATION(bits) != kNone; |
- } |
+ BitsetType::bitset bitset_; |
+ Limits limits_; |
+}; |
- static bool SemanticIsInhabited(bitset bits) { |
- return SEMANTIC(bits) != kNone; |
+// ----------------------------------------------------------------------------- |
+// 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 bool Is(bitset bits1, bitset bits2) { |
- return (bits1 | bits2) == bits2; |
+ static ContextType* cast(Type* type) { |
+ DCHECK(IsKind(type, kContext)); |
+ return static_cast<ContextType*>(FromType(type)); |
} |
- static double Min(bitset); |
- static double Max(bitset); |
+ explicit ContextType(Type* outer) : TypeBase(kContext), outer_(outer) {} |
- static bitset Glb(TypeImpl* 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(i::Map* map); |
- static bitset Lub(i::Object* value); |
- static bitset Lub(double value); |
- static bitset Lub(double min, double max); |
- static bitset ExpandInternals(bitset bits); |
+ Type* outer_; |
+}; |
- static const char* Name(bitset); |
- static void Print(std::ostream& os, bitset); // NOLINT |
-#ifdef DEBUG |
- static void Print(bitset); |
-#endif |
+// ----------------------------------------------------------------------------- |
+// Array types. |
- static bitset NumberBits(bitset bits); |
+class ArrayType : public TypeBase { |
+ public: |
+ Type* Element() { return element_; } |
private: |
- struct Boundary { |
- bitset internal; |
- bitset external; |
- double min; |
- }; |
- static const Boundary BoundariesArray[]; |
- static inline const Boundary* Boundaries(); |
- static inline size_t BoundariesSize(); |
-}; |
+ 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 non-bitset types (internal). |
-// Contains a tag and a variable number of type or value fields. |
+// Superclass for types with variable number of type fields. |
+class StructuralType : public TypeBase { |
+ public: |
+ int LengthForTesting() { return Length(); } |
-template<class Config> |
-class TypeImpl<Config>::StructuralType : public TypeImpl<Config> { |
protected: |
- template<class> friend class TypeImpl; |
- friend struct ZoneTypeConfig; // For tags. |
- friend struct HeapTypeConfig; |
- |
- enum Tag { |
- kClassTag, |
- kConstantTag, |
- kContextTag, |
- kArrayTag, |
- kFunctionTag, |
- kTupleTag, |
- kUnionTag |
- }; |
+ friend class Type; |
- int Length() { |
- return Config::struct_length(Config::as_struct(this)); |
- } |
- TypeHandle Get(int i) { |
+ int Length() { return length_; } |
+ |
+ Type* Get(int i) { |
DCHECK(0 <= i && i < this->Length()); |
- return Config::struct_get(Config::as_struct(this), i); |
+ return elements_[i]; |
} |
- void Set(int i, TypeHandle type) { |
+ |
+ void Set(int i, Type* type) { |
DCHECK(0 <= i && i < this->Length()); |
- Config::struct_set(Config::as_struct(this), i, type); |
+ elements_[i] = type; |
} |
+ |
void Shrink(int length) { |
DCHECK(2 <= length && length <= this->Length()); |
- Config::struct_shrink(Config::as_struct(this), length); |
+ length_ = 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); |
+ |
+ StructuralType(Kind kind, int length, i::Zone* zone) |
+ : TypeBase(kind), length_(length) { |
+ elements_ = reinterpret_cast<Type**>(zone->New(sizeof(Type*) * length)); |
} |
- 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); |
+ |
+ 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 TypeHandle New(Tag tag, int length, Region* region) { |
- DCHECK(1 <= length); |
- return Config::from_struct(Config::struct_create(tag, length, region)); |
+ 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). |
@@ -766,380 +641,329 @@ class TypeImpl<Config>::StructuralType : public TypeImpl<Config> { |
// - 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 Type { |
+ public: |
+ typedef BitsetType::bitset bitset; // Internal |
-// ----------------------------------------------------------------------------- |
-// Class types. |
+// 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 |
-template<class Config> |
-class TypeImpl<Config>::ClassType : public StructuralType { |
- public: |
- i::Handle<i::Map> Map() { |
- return Config::is_class(this) ? Config::as_class(this) : |
- this->template GetValue<i::Map>(1); |
+ static Type* SignedSmall() { |
+ return BitsetType::New(BitsetType::SignedSmall()); |
} |
- |
- 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); |
- } |
- return type; |
+ static Type* UnsignedSmall() { |
+ return BitsetType::New(BitsetType::UnsignedSmall()); |
} |
- static ClassType* cast(TypeImpl* type) { |
- DCHECK(type->IsClass()); |
- return static_cast<ClassType*>(type); |
+ static Type* Class(i::Handle<i::Map> map, Zone* zone) { |
+ return ClassType::New(map, zone); |
} |
- |
- private: |
- template<class> friend class TypeImpl; |
- bitset Lub() { |
- return Config::is_class(this) ? |
- BitsetType::Lub(*Config::as_class(this)) : |
- this->Get(0)->AsBitset(); |
+ 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 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; |
} |
-}; |
+#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 |
-// ----------------------------------------------------------------------------- |
-// Constant types. |
+ static Type* Union(Type* type1, Type* type2, Zone* reg); |
+ static Type* Intersect(Type* type1, Type* type2, Zone* reg); |
-template<class Config> |
-class TypeImpl<Config>::ConstantType : public StructuralType { |
- public: |
- i::Handle<i::Object> Value() { return this->template GetValue<i::Object>(1); } |
- |
- 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; |
+ static Type* Of(double value, Zone* zone) { |
+ return BitsetType::New(BitsetType::ExpandInternals(BitsetType::Lub(value))); |
} |
- |
- static ConstantType* cast(TypeImpl* type) { |
- DCHECK(type->IsConstant()); |
- return static_cast<ConstantType*>(type); |
+ 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 this->Get(0)->AsBitset(); } |
-}; |
-// TODO(neis): Also cache value if numerical. |
-// TODO(neis): Allow restricting the representation. |
+ // 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()); } |
-// ----------------------------------------------------------------------------- |
-// Range types. |
+ 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); } |
-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); } |
- |
- 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)); |
- } |
+ // 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); } |
- static RangeHandle New(Limits lim, bitset representation, Region* region) { |
- return New(lim.min, lim.max, BitsetType::New(representation, region), |
- region); |
+ // 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); } |
- static RangeType* cast(TypeImpl* type) { |
- DCHECK(type->IsRange()); |
- return static_cast<RangeType*>(type); |
- } |
+ bool NowStable(); |
- private: |
- template<class> friend class TypeImpl; |
- bitset Lub() { |
- return Config::range_get_bitset(Config::as_range(this)); |
- } |
-}; |
+ // 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); } |
+ 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); } |
-// ----------------------------------------------------------------------------- |
-// Context types. |
+ // 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(); |
-template<class Config> |
-class TypeImpl<Config>::ContextType : public StructuralType { |
- public: |
- TypeHandle Outer() { return this->Get(0); } |
+ // 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 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 bool IsInteger(i::Object* x); |
+ static bool IsInteger(double x) { |
+ return nearbyint(x) == x && !i::IsMinusZero(x); // Allows for infinities. |
} |
- static ContextType* cast(TypeImpl* type) { |
- DCHECK(type->IsContext()); |
- return static_cast<ContextType*>(type); |
- } |
-}; |
+ int NumClasses(); |
+ int NumConstants(); |
+ template <class T> |
+ class Iterator { |
+ public: |
+ bool Done() const { return index_ < 0; } |
+ i::Handle<T> Current(); |
+ void Advance(); |
-// ----------------------------------------------------------------------------- |
-// Array types. |
+ private: |
+ friend class Type; |
-template<class Config> |
-class TypeImpl<Config>::ArrayType : public StructuralType { |
- public: |
- TypeHandle Element() { return this->Get(0); } |
+ Iterator() : index_(-1) {} |
+ explicit Iterator(Type* type) : type_(type), index_(-1) { Advance(); } |
- 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; |
- } |
+ inline bool matches(Type* type); |
+ inline Type* get_type(); |
- static ArrayType* cast(TypeImpl* type) { |
- DCHECK(type->IsArray()); |
- return static_cast<ArrayType*>(type); |
- } |
-}; |
+ Type* type_; |
+ int index_; |
+ }; |
+ Iterator<i::Map> Classes() { |
+ if (this->IsBitset()) return Iterator<i::Map>(); |
+ return Iterator<i::Map>(this); |
+ } |
+ Iterator<i::Object> Constants() { |
+ if (this->IsBitset()) return Iterator<i::Object>(); |
+ return Iterator<i::Object>(this); |
+ } |
-// ----------------------------------------------------------------------------- |
-// Function types. |
+ // Printing. |
-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; |
- } |
+ enum PrintDimension { BOTH_DIMS, SEMANTIC_DIM, REPRESENTATION_DIM }; |
- static FunctionType* cast(TypeImpl* type) { |
- DCHECK(type->IsFunction()); |
- return static_cast<FunctionType*>(type); |
- } |
-}; |
+ void PrintTo(std::ostream& os, PrintDimension dim = BOTH_DIMS); // NOLINT |
+#ifdef DEBUG |
+ void Print(); |
+#endif |
-// ----------------------------------------------------------------------------- |
-// Tuple types. |
+ // Helpers for testing. |
+ bool IsBitsetForTesting() { return IsBitset(); } |
+ bool IsUnionForTesting() { return IsUnion(); } |
+ bitset AsBitsetForTesting() { return AsBitset(); } |
+ UnionType* AsUnionForTesting() { return AsUnion(); } |
-template <class Config> |
-class TypeImpl<Config>::TupleType : public StructuralType { |
- public: |
- int Arity() { return this->Length(); } |
- TypeHandle Element(int i) { return this->Get(i); } |
+ private: |
+ // Friends. |
+ template <class> |
+ friend class Iterator; |
+ friend BitsetType; |
+ friend UnionType; |
- void InitElement(int i, TypeHandle type) { this->Set(i, type); } |
+ // Internal inspection. |
+ bool IsKind(TypeBase::Kind kind) { return TypeBase::IsKind(this, kind); } |
- static TupleHandle New(int length, Region* region) { |
- TupleHandle type = Config::template cast<TupleType>( |
- StructuralType::New(StructuralType::kTupleTag, length, region)); |
- return type; |
- } |
+ bool IsNone() { return this == None(); } |
+ bool IsAny() { return this == Any(); } |
+ bool IsBitset() { return BitsetType::IsBitset(this); } |
+ bool IsUnion() { return IsKind(TypeBase::kUnion); } |
- static TupleType* cast(TypeImpl* type) { |
- DCHECK(type->IsTuple()); |
- return static_cast<TupleType*>(type); |
+ bitset AsBitset() { |
+ DCHECK(this->IsBitset()); |
+ return reinterpret_cast<BitsetType*>(this)->Bitset(); |
} |
-}; |
+ UnionType* AsUnion() { return UnionType::cast(this); } |
+ bitset Representation(); |
-// ----------------------------------------------------------------------------- |
-// Type iterators. |
+ // Auxiliary functions. |
+ bool SemanticMaybe(Type* that); |
-template<class Config> template<class T> |
-class TypeImpl<Config>::Iterator { |
- public: |
- bool Done() const { return index_ < 0; } |
- i::Handle<T> Current(); |
- void Advance(); |
+ bitset BitsetGlb() { return BitsetType::Glb(this); } |
+ bitset BitsetLub() { return BitsetType::Lub(this); } |
- private: |
- template<class> friend class TypeImpl; |
+ bool SlowIs(Type* that); |
+ bool SemanticIs(Type* that); |
- Iterator() : index_(-1) {} |
- explicit Iterator(TypeHandle type) : type_(type), index_(-1) { |
- Advance(); |
- } |
+ 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); |
- inline bool matches(TypeHandle type); |
- inline TypeHandle get_type(); |
+ static int UpdateRange(Type* type, UnionType* result, int size, Zone* zone); |
- TypeHandle type_; |
- int index_; |
-}; |
+ static RangeType::Limits IntersectRangeAndBitset(Type* range, Type* bits, |
+ Zone* zone); |
+ static RangeType::Limits ToLimits(bitset bits, Zone* zone); |
+ bool SimplyEquals(Type* that); |
-// ----------------------------------------------------------------------------- |
-// 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]; |
- }; |
- 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*); |
+ 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<ZoneTypeConfig> Type; |
- |
// ----------------------------------------------------------------------------- |
// 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; |
- |
- 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)); |
- } |
+struct Bounds { |
+ Type* lower; |
+ Type* 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; |
- |
class FieldType : public Object { |
public: |
static FieldType* None(); |