Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(328)

Unified Diff: src/types.h

Issue 1655833002: Remove the template magic from types.(h|cc), remove types-inl.h. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Undo whitespace change Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/type-info.cc ('k') | src/types.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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();
« no previous file with comments | « src/type-info.cc ('k') | src/types.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698