| 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();
|
|
|