From d849dfa5d4d611600604a0330bb7276d74f6710c Mon Sep 17 00:00:00 2001 From: "rossberg@chromium.org" Date: Fri, 10 Jan 2014 14:43:48 +0000 Subject: [PATCH] Implement zone-allocated types More template magic FTW. R=titzer@chromium.org BUG= Review URL: https://codereview.chromium.org/103743004 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18543 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/list-inl.h | 1 + src/objects.cc | 8 + src/objects.h | 3 + src/types.cc | 100 ++-- src/types.h | 194 ++++++- test/cctest/test-types.cc | 1360 ++++++++++++++++++++++++--------------------- 6 files changed, 954 insertions(+), 712 deletions(-) diff --git a/src/list-inl.h b/src/list-inl.h index 143c830..7799ca4 100644 --- a/src/list-inl.h +++ b/src/list-inl.h @@ -166,6 +166,7 @@ void List::Clear() { template void List::Rewind(int pos) { + ASSERT(pos <= length_); length_ = pos; } diff --git a/src/objects.cc b/src/objects.cc index 539d4af..429676a 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -7857,6 +7857,14 @@ MaybeObject* PolymorphicCodeCacheHashTable::Put(MapHandleList* maps, } +void FixedArray::Shrink(int new_length) { + ASSERT(new_length <= length()); + if (new_length < length()) { + RightTrimFixedArray(GetHeap(), this, length() - new_length); + } +} + + MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) { ElementsAccessor* accessor = array->GetElementsAccessor(); MaybeObject* maybe_result = diff --git a/src/objects.h b/src/objects.h index 1dc54b2..3488a31 100644 --- a/src/objects.h +++ b/src/objects.h @@ -2941,6 +2941,9 @@ class FixedArray: public FixedArrayBase { // Gives access to raw memory which stores the array's data. inline Object** data_start(); + // Shrink length and insert filler objects. + void Shrink(int length); + // Copy operations. MUST_USE_RESULT inline MaybeObject* Copy(); MUST_USE_RESULT MaybeObject* CopySize(int new_length, diff --git a/src/types.cc b/src/types.cc index 2aa6081..9354965 100644 --- a/src/types.cc +++ b/src/types.cc @@ -38,7 +38,7 @@ int TypeImpl::NumClasses() { } else if (this->IsUnion()) { UnionedHandle unioned = this->AsUnion(); int result = 0; - for (int i = 0; i < unioned->length(); ++i) { + for (int i = 0; i < Config::union_length(unioned); ++i) { if (Config::union_get(unioned, i)->IsClass()) ++result; } return result; @@ -55,7 +55,7 @@ int TypeImpl::NumConstants() { } else if (this->IsUnion()) { UnionedHandle unioned = this->AsUnion(); int result = 0; - for (int i = 0; i < unioned->length(); ++i) { + for (int i = 0; i < Config::union_length(unioned); ++i) { if (Config::union_get(unioned, i)->IsConstant()) ++result; } return result; @@ -118,7 +118,7 @@ void TypeImpl::Iterator::Advance() { ++index_; if (type_->IsUnion()) { UnionedHandle unioned = type_->AsUnion(); - for (; index_ < unioned->length(); ++index_) { + for (; index_ < Config::union_length(unioned); ++index_) { if (matches(Config::union_get(unioned, index_))) return; } } else if (index_ == 0 && matches(type_)) { @@ -136,7 +136,7 @@ int TypeImpl::LubBitset() { } else if (this->IsUnion()) { UnionedHandle unioned = this->AsUnion(); int bitset = kNone; - for (int i = 0; i < unioned->length(); ++i) { + for (int i = 0; i < Config::union_length(unioned); ++i) { bitset |= Config::union_get(unioned, i)->LubBitset(); } return bitset; @@ -299,7 +299,7 @@ bool TypeImpl::SlowIs(TypeImpl* that) { // (T1 \/ ... \/ Tn) <= T <=> (T1 <= T) /\ ... /\ (Tn <= T) if (this->IsUnion()) { UnionedHandle unioned = this->AsUnion(); - for (int i = 0; i < unioned->length(); ++i) { + for (int i = 0; i < Config::union_length(unioned); ++i) { TypeHandle this_i = Config::union_get(unioned, i); if (!this_i->Is(that)) return false; } @@ -311,7 +311,7 @@ bool TypeImpl::SlowIs(TypeImpl* that) { ASSERT(!this->IsUnion()); if (that->IsUnion()) { UnionedHandle unioned = that->AsUnion(); - for (int i = 0; i < unioned->length(); ++i) { + for (int i = 0; i < Config::union_length(unioned); ++i) { TypeHandle that_i = Config::union_get(unioned, i); if (this->Is(that_i)) return true; if (this->IsBitset()) break; // Fast fail, only first field is a bitset. @@ -346,7 +346,7 @@ bool TypeImpl::Maybe(TypeImpl* that) { // (T1 \/ ... \/ Tn) overlaps T <=> (T1 overlaps T) \/ ... \/ (Tn overlaps T) if (this->IsUnion()) { UnionedHandle unioned = this->AsUnion(); - for (int i = 0; i < unioned->length(); ++i) { + for (int i = 0; i < Config::union_length(unioned); ++i) { TypeHandle this_i = Config::union_get(unioned, i); if (this_i->Maybe(that)) return true; } @@ -356,7 +356,7 @@ bool TypeImpl::Maybe(TypeImpl* that) { // T overlaps (T1 \/ ... \/ Tn) <=> (T overlaps T1) \/ ... \/ (T overlaps Tn) if (that->IsUnion()) { UnionedHandle unioned = that->AsUnion(); - for (int i = 0; i < unioned->length(); ++i) { + for (int i = 0; i < Config::union_length(unioned); ++i) { TypeHandle that_i = Config::union_get(unioned, i); if (this->Maybe(that_i)) return true; } @@ -389,18 +389,21 @@ bool TypeImpl::InUnion(UnionedHandle unioned, int current_size) { // Get non-bitsets from this which are not subsumed by union, store at unioned, // starting at index. Returns updated index. template -int TypeImpl::ExtendUnion(UnionedHandle result, int current_size) { +int TypeImpl::ExtendUnion( + UnionedHandle result, TypeHandle type, int current_size) { int old_size = current_size; - if (this->IsClass() || this->IsConstant()) { - if (!this->InUnion(result, old_size)) result->set(current_size++, this); - } else if (this->IsUnion()) { - UnionedHandle unioned = this->AsUnion(); - for (int i = 0; i < unioned->length(); ++i) { + if (type->IsClass() || type->IsConstant()) { + if (!type->InUnion(result, old_size)) { + Config::union_set(result, current_size++, type); + } + } else if (type->IsUnion()) { + UnionedHandle unioned = type->AsUnion(); + for (int i = 0; i < Config::union_length(unioned); ++i) { TypeHandle type = Config::union_get(unioned, i); ASSERT(i == 0 || !(type->IsBitset() || type->Is(Config::union_get(unioned, 0)))); if (!type->IsBitset() && !type->InUnion(result, old_size)) { - result->set(current_size++, *type); + Config::union_set(result, current_size++, type); } } } @@ -433,51 +436,50 @@ typename TypeImpl::TypeHandle TypeImpl::Union( // Slow case: may need to produce a Unioned object. int size = type1->IsBitset() || type2->IsBitset() ? 1 : 0; if (!type1->IsBitset()) { - size += (type1->IsUnion() ? type1->AsUnion()->length() : 1); + size += (type1->IsUnion() ? Config::union_length(type1->AsUnion()) : 1); } if (!type2->IsBitset()) { - size += (type2->IsUnion() ? type2->AsUnion()->length() : 1); + size += (type2->IsUnion() ? Config::union_length(type2->AsUnion()) : 1); } ASSERT(size >= 2); UnionedHandle unioned = Config::union_create(size, region); size = 0; int bitset = type1->GlbBitset() | type2->GlbBitset(); - if (bitset != kNone) unioned->set(size++, Config::from_bitset(bitset)); - size = type1->ExtendUnion(unioned, size); - size = type2->ExtendUnion(unioned, size); + if (bitset != kNone) { + Config::union_set(unioned, size++, Config::from_bitset(bitset, region)); + } + size = ExtendUnion(unioned, type1, size); + size = ExtendUnion(unioned, type2, size); if (size == 1) { return Config::union_get(unioned, 0); - } else if (size == unioned->length()) { + } else { + Config::union_shrink(unioned, size); return Config::from_union(unioned); } - - // There was an overlap. Copy to smaller union. - UnionedHandle result = Config::union_create(size, region); - for (int i = 0; i < size; ++i) result->set(i, unioned->get(i)); - return Config::from_union(result); } -// Get non-bitsets from this which are also in that, store at unioned, +// Get non-bitsets from type which are also in other, store at unioned, // starting at index. Returns updated index. template int TypeImpl::ExtendIntersection( - UnionedHandle result, TypeHandle that, int current_size) { + UnionedHandle result, TypeHandle type, TypeHandle other, int current_size) { int old_size = current_size; - if (this->IsClass() || this->IsConstant()) { - if (this->Is(that) && !this->InUnion(result, old_size)) - result->set(current_size++, this); - } else if (this->IsUnion()) { - UnionedHandle unioned = this->AsUnion(); - for (int i = 0; i < unioned->length(); ++i) { + if (type->IsClass() || type->IsConstant()) { + if (type->Is(other) && !type->InUnion(result, old_size)) { + Config::union_set(result, current_size++, type); + } + } else if (type->IsUnion()) { + UnionedHandle unioned = type->AsUnion(); + for (int i = 0; i < Config::union_length(unioned); ++i) { TypeHandle type = Config::union_get(unioned, i); ASSERT(i == 0 || !(type->IsBitset() || type->Is(Config::union_get(unioned, 0)))); - if (!type->IsBitset() && type->Is(that) && + if (!type->IsBitset() && type->Is(other) && !type->InUnion(result, old_size)) { - result->set(current_size++, *type); + Config::union_set(result, current_size++, type); } } } @@ -510,10 +512,10 @@ typename TypeImpl::TypeHandle TypeImpl::Intersect( // Slow case: may need to produce a Unioned object. int size = 0; if (!type1->IsBitset()) { - size = (type1->IsUnion() ? type1->AsUnion()->length() : 2); + size = (type1->IsUnion() ? Config::union_length(type1->AsUnion()) : 2); } if (!type2->IsBitset()) { - int size2 = (type2->IsUnion() ? type2->AsUnion()->length() : 2); + int size2 = (type2->IsUnion() ? Config::union_length(type2->AsUnion()) : 2); size = (size == 0 ? size2 : Min(size, size2)); } ASSERT(size >= 2); @@ -521,22 +523,20 @@ typename TypeImpl::TypeHandle TypeImpl::Intersect( size = 0; int bitset = type1->GlbBitset() & type2->GlbBitset(); - if (bitset != kNone) unioned->set(size++, Config::from_bitset(bitset)); - size = type1->ExtendIntersection(unioned, type2, size); - size = type2->ExtendIntersection(unioned, type1, size); + if (bitset != kNone) { + Config::union_set(unioned, size++, Config::from_bitset(bitset, region)); + } + size = ExtendIntersection(unioned, type1, type2, size); + size = ExtendIntersection(unioned, type2, type1, size); if (size == 0) { return None(region); } else if (size == 1) { return Config::union_get(unioned, 0); - } else if (size == unioned->length()) { + } else { + Config::union_shrink(unioned, size); return Config::from_union(unioned); } - - // There were dropped cases. Copy to smaller union. - UnionedHandle result = Config::union_create(size, region); - for (int i = 0; i < size; ++i) result->set(i, unioned->get(i)); - return Config::from_union(result); } @@ -601,7 +601,7 @@ void TypeImpl::TypePrint(FILE* out) { } else if (this->IsUnion()) { PrintF(out, "("); UnionedHandle unioned = this->AsUnion(); - for (int i = 0; i < unioned->length(); ++i) { + for (int i = 0; i < Config::union_length(unioned); ++i) { TypeHandle type_i = Config::union_get(unioned, i); if (i > 0) PrintF(out, " | "); type_i->TypePrint(out); @@ -612,6 +612,10 @@ void TypeImpl::TypePrint(FILE* out) { #endif +template class TypeImpl; +template class TypeImpl::Iterator; +template class TypeImpl::Iterator; + template class TypeImpl; template class TypeImpl::Iterator; template class TypeImpl::Iterator; diff --git a/src/types.h b/src/types.h index 4d8557e..7dcf6f6 100644 --- a/src/types.h +++ b/src/types.h @@ -137,22 +137,24 @@ namespace internal { // typedef Region; // template struct Handle { typedef type; } // No template typedefs... // static Handle::type handle(Type* type); // !is_bitset(type) -// static bool is_bitset(Type* type); -// static bool is_class(Type* type); -// static bool is_constant(Type* type); -// static bool is_union(Type* type); -// static int as_bitset(Type* type); -// static i::Handle as_class(Type* type); -// static i::Handle as_constant(Type* type); -// static Handle::type as_union(Type* type); +// static bool is_bitset(Type*); +// static bool is_class(Type*); +// static bool is_constant(Type*); +// static bool is_union(Type*); +// static int as_bitset(Type*); +// static i::Handle as_class(Type*); +// static i::Handle as_constant(Type*); +// static Handle::type as_union(Type*); // static Type* from_bitset(int bitset); -// static Handle::type from_bitset(int bitset, Region* region); -// static Handle::type from_class(i::Handle map, Region* region) -// static Handle::type from_constant( -// i::Handle value, Region* region); -// static Handle::type from_union(Handle::T unioned); -// static Handle::type union_create(int size, Region* region); -// static Handle::type union_get(Handle::T unioned, int i); +// static Handle::type from_bitset(int bitset, Region*); +// static Handle::type from_class(i::Handle, Region*) +// static Handle::type from_constant(i::Handle, Region*); +// static Handle::type from_union(Handle::type); +// static Handle::type union_create(int size, Region*); +// static void union_shrink(Handle::type, int size); +// static Handle::type union_get(Handle::type, int); +// static void union_set(Handle::type, int, Handle::type); +// static int union_length(Handle::type); // } template class TypeImpl : public Config::Base { @@ -183,14 +185,17 @@ class TypeImpl : public Config::Base { } bool Is(TypeImpl* that) { return this == that || this->SlowIs(that); } + template bool Is(TypeHandle that) { return this->Is(*that); } bool Maybe(TypeImpl* that); + template bool Maybe(TypeHandle that) { return this->Maybe(*that); } // State-dependent versions of Of and Is that consider subtyping between // a constant and its map class. static TypeHandle OfCurrently(i::Handle value, Region* region); bool IsCurrently(TypeImpl* that); + template bool IsCurrently(TypeHandle that) { return this->IsCurrently(*that); } bool IsClass() { return Config::is_class(this); } @@ -232,7 +237,7 @@ class TypeImpl : public Config::Base { return Iterator(Config::handle(this)); } - static TypeImpl* cast(i::Object* object) { + static TypeImpl* cast(typename Config::Base* object) { TypeImpl* t = static_cast(object); ASSERT(t->IsBitset() || t->IsClass() || t->IsConstant() || t->IsUnion()); return t; @@ -276,9 +281,10 @@ class TypeImpl : public Config::Base { static int LubBitset(i::Map* map); bool InUnion(UnionedHandle unioned, int current_size); - int ExtendUnion(UnionedHandle unioned, int current_size); - int ExtendIntersection( - UnionedHandle unioned, TypeHandle type, int current_size); + static int ExtendUnion( + UnionedHandle unioned, TypeHandle t, int current_size); + static int ExtendIntersection( + UnionedHandle unioned, TypeHandle t, TypeHandle other, int current_size); #ifdef OBJECT_PRINT static const char* bitset_name(int bitset); @@ -286,6 +292,141 @@ class TypeImpl : public Config::Base { }; +// Zone-allocated types are either (odd) integers to represent bitsets, or +// (even) pointers to zone lists for everything else. The first slot of every +// list is an explicit tag value to distinguish representation. +struct ZoneTypeConfig { + private: + typedef i::ZoneList Tagged; + + enum Tag { + kClassTag, + kConstantTag, + kUnionTag + }; + + static Tagged* tagged_create(Tag tag, int size, Zone* zone) { + Tagged* tagged = new(zone) Tagged(size + 1, zone); + tagged->Add(reinterpret_cast(tag), zone); + tagged->AddBlock(NULL, size, zone); + return tagged; + } + static void tagged_shrink(Tagged* tagged, int size) { + tagged->Rewind(size + 1); + } + static Tag tagged_tag(Tagged* tagged) { + return static_cast(reinterpret_cast(tagged->at(0))); + } + template + static T tagged_get(Tagged* tagged, int i) { + return reinterpret_cast(tagged->at(i + 1)); + } + template + static void tagged_set(Tagged* tagged, int i, T value) { + tagged->at(i + 1) = reinterpret_cast(value); + } + static int tagged_length(Tagged* tagged) { + return tagged->length() - 1; + } + + public: + typedef TypeImpl Type; + class Base {}; + typedef i::ZoneList Unioned; + typedef i::Zone Region; + template struct Handle { typedef T* type; }; + + static Type* handle(Type* type) { return type; } + + static bool is(Type* type, Tag tag) { + return is_tagged(type) && tagged_tag(as_tagged(type)) == tag; + } + + static bool is_bitset(Type* type) { + return reinterpret_cast(type) & 1; + } + static bool is_tagged(Type* type) { return !is_bitset(type); } + static bool is_class(Type* type) { return is(type, kClassTag); } + static bool is_constant(Type* type) { return is(type, kConstantTag); } + static bool is_union(Type* type) { return is(type, kUnionTag); } + static bool tagged_is_union(Tagged* tagged) { + return is(from_tagged(tagged), kUnionTag); + } + + static int as_bitset(Type* type) { + ASSERT(is_bitset(type)); + return reinterpret_cast(type) >> 1; + } + static Tagged* as_tagged(Type* type) { + ASSERT(is_tagged(type)); + return reinterpret_cast(type); + } + static i::Handle as_class(Type* type) { + ASSERT(is_class(type)); + return i::Handle(tagged_get(as_tagged(type), 0)); + } + static i::Handle as_constant(Type* type) { + ASSERT(is_constant(type)); + return i::Handle(tagged_get(as_tagged(type), 0)); + } + static Unioned* as_union(Type* type) { + ASSERT(is_union(type)); + return tagged_as_union(as_tagged(type)); + } + static Unioned* tagged_as_union(Tagged* tagged) { + ASSERT(tagged_is_union(tagged)); + return reinterpret_cast(tagged); + } + + static Type* from_bitset(int bitset) { + return reinterpret_cast((bitset << 1) | 1); + } + static Type* from_bitset(int bitset, Zone* Zone) { + return from_bitset(bitset); + } + static Type* from_tagged(Tagged* tagged) { + return reinterpret_cast(tagged); + } + static Type* from_class(i::Handle map, Zone* zone) { + Tagged* tagged = tagged_create(kClassTag, 1, zone); + tagged_set(tagged, 0, map.location()); + return from_tagged(tagged); + } + static Type* from_constant(i::Handle value, Zone* zone) { + Tagged* tagged = tagged_create(kConstantTag, 1, zone); + tagged_set(tagged, 0, value.location()); + return from_tagged(tagged); + } + static Type* from_union(Unioned* unioned) { + return from_tagged(tagged_from_union(unioned)); + } + static Tagged* tagged_from_union(Unioned* unioned) { + return reinterpret_cast(unioned); + } + + static Unioned* union_create(int size, Zone* zone) { + return tagged_as_union(tagged_create(kUnionTag, size, zone)); + } + static void union_shrink(Unioned* unioned, int size) { + tagged_shrink(tagged_from_union(unioned), size); + } + static Type* union_get(Unioned* unioned, int i) { + Type* type = tagged_get(tagged_from_union(unioned), i); + ASSERT(!is_union(type)); + return type; + } + static void union_set(Unioned* unioned, int i, Type* type) { + ASSERT(!is_union(type)); + tagged_set(tagged_from_union(unioned), i, type); + } + static int union_length(Unioned* unioned) { + return tagged_length(tagged_from_union(unioned)); + } +}; + + +// Heap-allocated types are either smis for bitsets, maps for classes, boxes for +// constants, or fixed arrays for unions. struct HeapTypeConfig { typedef TypeImpl Type; typedef i::Object Base; @@ -327,8 +468,6 @@ struct HeapTypeConfig { } static i::Handle from_constant( i::Handle value, Isolate* isolate) { - ASSERT(isolate || value->IsHeapObject()); - if (!isolate) isolate = i::HeapObject::cast(*value)->GetIsolate(); i::Handle box = isolate->factory()->NewBox(value); return i::Handle::cast(i::Handle::cast(box)); } @@ -339,13 +478,25 @@ struct HeapTypeConfig { static i::Handle union_create(int size, Isolate* isolate) { return isolate->factory()->NewFixedArray(size); } + static void union_shrink(i::Handle unioned, int size) { + unioned->Shrink(size); + } static i::Handle union_get(i::Handle unioned, int i) { Type* type = static_cast(unioned->get(i)); ASSERT(!is_union(type)); return i::handle(type, unioned->GetIsolate()); } + static void union_set( + i::Handle unioned, int i, i::Handle type) { + ASSERT(!is_union(*type)); + unioned->set(i, *type); + } + static int union_length(i::Handle unioned) { + return unioned->length(); + } }; +typedef TypeImpl ZoneType; typedef TypeImpl Type; @@ -399,6 +550,7 @@ struct BoundsImpl { } }; +typedef BoundsImpl ZoneBounds; typedef BoundsImpl Bounds; diff --git a/test/cctest/test-types.cc b/test/cctest/test-types.cc index adcc156..8b105dd 100644 --- a/test/cctest/test-types.cc +++ b/test/cctest/test-types.cc @@ -30,705 +30,779 @@ using namespace v8::internal; +template +class Types { + public: + Types(Region* region, Isolate* isolate) : + None(Type::None(region)), + Any(Type::Any(region)), + Oddball(Type::Oddball(region)), + Boolean(Type::Boolean(region)), + Null(Type::Null(region)), + Undefined(Type::Undefined(region)), + Number(Type::Number(region)), + Smi(Type::Smi(region)), + Signed32(Type::Signed32(region)), + Double(Type::Double(region)), + Name(Type::Name(region)), + UniqueName(Type::UniqueName(region)), + String(Type::String(region)), + InternalizedString(Type::InternalizedString(region)), + Symbol(Type::Symbol(region)), + Receiver(Type::Receiver(region)), + Object(Type::Object(region)), + Array(Type::Array(region)), + Function(Type::Function(region)), + Proxy(Type::Proxy(region)), + object_map(isolate->factory()->NewMap(JS_OBJECT_TYPE, 3 * kPointerSize)), + array_map(isolate->factory()->NewMap(JS_ARRAY_TYPE, 4 * kPointerSize)), + region_(region) { + smi = handle(Smi::FromInt(666), isolate); + signed32 = isolate->factory()->NewHeapNumber(0x40000000); + object1 = isolate->factory()->NewJSObjectFromMap(object_map); + object2 = isolate->factory()->NewJSObjectFromMap(object_map); + array = isolate->factory()->NewJSArray(20); + ObjectClass = Type::Class(object_map, region); + ArrayClass = Type::Class(array_map, region); + SmiConstant = Type::Constant(smi, region); + Signed32Constant = Type::Constant(signed32, region); + ObjectConstant1 = Type::Constant(object1, region); + ObjectConstant2 = Type::Constant(object2, region); + ArrayConstant1 = Type::Constant(array, region); + ArrayConstant2 = Type::Constant(array, region); + } + + TypeHandle None; + TypeHandle Any; + TypeHandle Oddball; + TypeHandle Boolean; + TypeHandle Null; + TypeHandle Undefined; + TypeHandle Number; + TypeHandle Smi; + TypeHandle Signed32; + TypeHandle Double; + TypeHandle Name; + TypeHandle UniqueName; + TypeHandle String; + TypeHandle InternalizedString; + TypeHandle Symbol; + TypeHandle Receiver; + TypeHandle Object; + TypeHandle Array; + TypeHandle Function; + TypeHandle Proxy; + + TypeHandle ObjectClass; + TypeHandle ArrayClass; + + TypeHandle SmiConstant; + TypeHandle Signed32Constant; + TypeHandle ObjectConstant1; + TypeHandle ObjectConstant2; + TypeHandle ArrayConstant1; + TypeHandle ArrayConstant2; + + Handle object_map; + Handle array_map; + + Handle smi; + Handle signed32; + Handle object1; + Handle object2; + Handle array; + + TypeHandle Union(TypeHandle t1, TypeHandle t2) { + return Type::Union(t1, t2, region_); + } + TypeHandle Intersect(TypeHandle t1, TypeHandle t2) { + return Type::Intersect(t1, t2, region_); + } + + private: + Region* region_; +}; + + // Testing auxiliaries (breaking the Type abstraction). -static bool IsBitset(Handle t) { return t->IsSmi(); } -static bool IsClass(Handle t) { return t->IsMap(); } -static bool IsConstant(Handle t) { return t->IsBox(); } -static bool IsUnion(Handle t) { return t->IsFixedArray(); } - -static int AsBitset(Handle t) { return Smi::cast(*t)->value(); } -static Map* AsClass(Handle t) { return Map::cast(*t); } -static Object* AsConstant(Handle t) { return Box::cast(*t)->value(); } -static FixedArray* AsUnion(Handle t) { return FixedArray::cast(*t); } - - -static void CheckEqual(Handle type1, Handle type2) { - CHECK_EQ(IsBitset(type1), IsBitset(type2)); - CHECK_EQ(IsClass(type1), IsClass(type2)); - CHECK_EQ(IsConstant(type1), IsConstant(type2)); - CHECK_EQ(IsUnion(type1), IsUnion(type2)); - CHECK_EQ(type1->NumClasses(), type2->NumClasses()); - CHECK_EQ(type1->NumConstants(), type2->NumConstants()); - if (IsBitset(type1)) { - CHECK_EQ(AsBitset(type1), AsBitset(type2)); - } else if (IsClass(type1)) { - CHECK_EQ(AsClass(type1), AsClass(type2)); - } else if (IsConstant(type1)) { - CHECK_EQ(AsConstant(type1), AsConstant(type2)); - } else if (IsUnion(type1)) { - CHECK_EQ(AsUnion(type1)->length(), AsUnion(type2)->length()); +struct ZoneRep { + static bool IsTagged(ZoneType* t, int tag) { + return !IsBitset(t) + && reinterpret_cast(AsTagged(t)->at(0)) == tag; } - CHECK(type1->Is(type2)); - CHECK(type2->Is(type1)); -} + static bool IsBitset(ZoneType* t) { + return reinterpret_cast(t) & 1; + } + static bool IsClass(ZoneType* t) { return IsTagged(t, 0); } + static bool IsConstant(ZoneType* t) { return IsTagged(t, 1); } + static bool IsUnion(ZoneType* t) { return IsTagged(t, 2); } + + static ZoneList* AsTagged(ZoneType* t) { + return reinterpret_cast*>(t); + } + static int AsBitset(ZoneType* t) { + return reinterpret_cast(t) >> 1; + } + static Map* AsClass(ZoneType* t) { + return *reinterpret_cast(AsTagged(t)->at(1)); + } + static Object* AsConstant(ZoneType* t) { + return *reinterpret_cast(AsTagged(t)->at(1)); + } + static ZoneList* AsUnion(ZoneType* t) { + return reinterpret_cast*>(AsTagged(t)); + } + + static Zone* Region(Zone* zone, Isolate* isolate) { return zone; } +}; + +struct HeapRep { + static bool IsBitset(Handle t) { return t->IsSmi(); } + static bool IsClass(Handle t) { return t->IsMap(); } + static bool IsConstant(Handle t) { return t->IsBox(); } + static bool IsUnion(Handle t) { return t->IsFixedArray(); } -static void CheckSub(Handle type1, Handle type2) { - CHECK(type1->Is(type2)); - CHECK(!type2->Is(type1)); - if (IsBitset(type1) && IsBitset(type2)) { - CHECK_NE(AsBitset(type1), AsBitset(type2)); + static int AsBitset(Handle t) { return Smi::cast(*t)->value(); } + static Map* AsClass(Handle t) { return Map::cast(*t); } + static Object* AsConstant(Handle t) { return Box::cast(*t)->value(); } + static FixedArray* AsUnion(Handle t) { return FixedArray::cast(*t); } + + static Isolate* Region(Zone* zone, Isolate* isolate) { return isolate; } +}; + + +template +struct Tests : Rep { + Isolate* isolate; + HandleScope scope; + Zone zone; + Types T; + + Tests() : + isolate(CcTest::i_isolate()), + scope(isolate), + zone(isolate), + T(Rep::Region(&zone, isolate), isolate) { } -} + static void CheckEqual(TypeHandle type1, TypeHandle type2) { + CHECK_EQ(Rep::IsBitset(type1), Rep::IsBitset(type2)); + CHECK_EQ(Rep::IsClass(type1), Rep::IsClass(type2)); + CHECK_EQ(Rep::IsConstant(type1), Rep::IsConstant(type2)); + CHECK_EQ(Rep::IsUnion(type1), Rep::IsUnion(type2)); + CHECK_EQ(type1->NumClasses(), type2->NumClasses()); + CHECK_EQ(type1->NumConstants(), type2->NumConstants()); + if (Rep::IsBitset(type1)) { + CHECK_EQ(Rep::AsBitset(type1), Rep::AsBitset(type2)); + } else if (Rep::IsClass(type1)) { + CHECK_EQ(Rep::AsClass(type1), Rep::AsClass(type2)); + } else if (Rep::IsConstant(type1)) { + CHECK_EQ(Rep::AsConstant(type1), Rep::AsConstant(type2)); + } else if (Rep::IsUnion(type1)) { + CHECK_EQ(Rep::AsUnion(type1)->length(), Rep::AsUnion(type2)->length()); + } + CHECK(type1->Is(type2)); + CHECK(type2->Is(type1)); + } -static void CheckUnordered(Handle type1, Handle type2) { - CHECK(!type1->Is(type2)); - CHECK(!type2->Is(type1)); - if (IsBitset(type1) && IsBitset(type2)) { - CHECK_NE(AsBitset(type1), AsBitset(type2)); + static void CheckSub(TypeHandle type1, TypeHandle type2) { + CHECK(type1->Is(type2)); + CHECK(!type2->Is(type1)); + if (Rep::IsBitset(type1) && Rep::IsBitset(type2)) { + CHECK_NE(Rep::AsBitset(type1), Rep::AsBitset(type2)); + } } -} + static void CheckUnordered(TypeHandle type1, TypeHandle type2) { + CHECK(!type1->Is(type2)); + CHECK(!type2->Is(type1)); + if (Rep::IsBitset(type1) && Rep::IsBitset(type2)) { + CHECK_NE(Rep::AsBitset(type1), Rep::AsBitset(type2)); + } + } -static void CheckOverlap(Handle type1, Handle type2) { - CHECK(type1->Maybe(type2)); - CHECK(type2->Maybe(type1)); - if (IsBitset(type1) && IsBitset(type2)) { - CHECK_NE(0, AsBitset(type1) & AsBitset(type2)); + static void CheckOverlap(TypeHandle type1, TypeHandle type2) { + CHECK(type1->Maybe(type2)); + CHECK(type2->Maybe(type1)); + if (Rep::IsBitset(type1) && Rep::IsBitset(type2)) { + CHECK_NE(0, Rep::AsBitset(type1) & Rep::AsBitset(type2)); + } + } + + static void CheckDisjoint(TypeHandle type1, TypeHandle type2) { + CHECK(!type1->Is(type2)); + CHECK(!type2->Is(type1)); + CHECK(!type1->Maybe(type2)); + CHECK(!type2->Maybe(type1)); + if (Rep::IsBitset(type1) && Rep::IsBitset(type2)) { + CHECK_EQ(0, Rep::AsBitset(type1) & Rep::AsBitset(type2)); + } } -} + void Bitset() { + CHECK(IsBitset(T.None)); + CHECK(IsBitset(T.Any)); + CHECK(IsBitset(T.String)); + CHECK(IsBitset(T.Object)); -static void CheckDisjoint(Handle type1, Handle type2) { - CHECK(!type1->Is(type2)); - CHECK(!type2->Is(type1)); - CHECK(!type1->Maybe(type2)); - CHECK(!type2->Maybe(type1)); - if (IsBitset(type1) && IsBitset(type2)) { - CHECK_EQ(0, AsBitset(type1) & AsBitset(type2)); + CHECK(IsBitset(T.Union(T.String, T.Number))); + CHECK(IsBitset(T.Union(T.String, T.Receiver))); + + CHECK_EQ(0, AsBitset(T.None)); + CHECK_EQ(AsBitset(T.Number) | AsBitset(T.String), + AsBitset(T.Union(T.String, T.Number))); + CHECK_EQ(AsBitset(T.Receiver), + AsBitset(T.Union(T.Receiver, T.Object))); } -} + void Class() { + CHECK(IsClass(T.ObjectClass)); + CHECK(IsClass(T.ArrayClass)); -class HandlifiedTypes { - public: - explicit HandlifiedTypes(Isolate* isolate) : - None(Type::None(isolate)), - Any(Type::Any(isolate)), - Oddball(Type::Oddball(isolate)), - Boolean(Type::Boolean(isolate)), - Null(Type::Null(isolate)), - Undefined(Type::Undefined(isolate)), - Number(Type::Number(isolate)), - Smi(Type::Smi(isolate)), - Signed32(Type::Signed32(isolate)), - Double(Type::Double(isolate)), - Name(Type::Name(isolate)), - UniqueName(Type::UniqueName(isolate)), - String(Type::String(isolate)), - InternalizedString(Type::InternalizedString(isolate)), - Symbol(Type::Symbol(isolate)), - Receiver(Type::Receiver(isolate)), - Object(Type::Object(isolate)), - Array(Type::Array(isolate)), - Function(Type::Function(isolate)), - Proxy(Type::Proxy(isolate)), - object_map(isolate->factory()->NewMap(JS_OBJECT_TYPE, 3 * kPointerSize)), - array_map(isolate->factory()->NewMap(JS_ARRAY_TYPE, 4 * kPointerSize)), - isolate_(isolate) { - smi = handle(Smi::FromInt(666), isolate); - signed32 = isolate->factory()->NewHeapNumber(0x40000000); - object1 = isolate->factory()->NewJSObjectFromMap(object_map); - object2 = isolate->factory()->NewJSObjectFromMap(object_map); - array = isolate->factory()->NewJSArray(20); - ObjectClass = Type::Class(object_map, isolate); - ArrayClass = Type::Class(array_map, isolate); - SmiConstant = Type::Constant(smi, isolate); - Signed32Constant = Type::Constant(signed32, isolate); - ObjectConstant1 = Type::Constant(object1, isolate); - ObjectConstant2 = Type::Constant(object2, isolate); - ArrayConstant1 = Type::Constant(array, isolate); - ArrayConstant2 = Type::Constant(array, isolate); + CHECK(*T.object_map == AsClass(T.ObjectClass)); + CHECK(*T.array_map == AsClass(T.ArrayClass)); } - Handle None; - Handle Any; - Handle Oddball; - Handle Boolean; - Handle Null; - Handle Undefined; - Handle Number; - Handle Smi; - Handle Signed32; - Handle Double; - Handle Name; - Handle UniqueName; - Handle String; - Handle InternalizedString; - Handle Symbol; - Handle Receiver; - Handle Object; - Handle Array; - Handle Function; - Handle Proxy; - - Handle ObjectClass; - Handle ArrayClass; - - Handle SmiConstant; - Handle Signed32Constant; - Handle ObjectConstant1; - Handle ObjectConstant2; - Handle ArrayConstant1; - Handle ArrayConstant2; - - Handle object_map; - Handle array_map; + void Constant() { + CHECK(IsConstant(T.SmiConstant)); + CHECK(IsConstant(T.ObjectConstant1)); + CHECK(IsConstant(T.ObjectConstant2)); + CHECK(IsConstant(T.ArrayConstant1)); + CHECK(IsConstant(T.ArrayConstant2)); + + CHECK(*T.smi == AsConstant(T.SmiConstant)); + CHECK(*T.object1 == AsConstant(T.ObjectConstant1)); + CHECK(*T.object2 == AsConstant(T.ObjectConstant2)); + CHECK(*T.object1 != AsConstant(T.ObjectConstant2)); + CHECK(*T.array == AsConstant(T.ArrayConstant1)); + CHECK(*T.array == AsConstant(T.ArrayConstant2)); + } - Handle smi; - Handle signed32; - Handle object1; - Handle object2; - Handle array; + void Is() { + // Reflexivity + CHECK(T.None->Is(T.None)); + CHECK(T.Any->Is(T.Any)); + CHECK(T.Object->Is(T.Object)); + + CHECK(T.ObjectClass->Is(T.ObjectClass)); + CHECK(T.ObjectConstant1->Is(T.ObjectConstant1)); + CHECK(T.ArrayConstant1->Is(T.ArrayConstant2)); + + // Symmetry and Transitivity + CheckSub(T.None, T.Number); + CheckSub(T.None, T.Any); + + CheckSub(T.Oddball, T.Any); + CheckSub(T.Boolean, T.Oddball); + CheckSub(T.Null, T.Oddball); + CheckSub(T.Undefined, T.Oddball); + CheckUnordered(T.Boolean, T.Null); + CheckUnordered(T.Undefined, T.Null); + CheckUnordered(T.Boolean, T.Undefined); + + CheckSub(T.Number, T.Any); + CheckSub(T.Smi, T.Number); + CheckSub(T.Signed32, T.Number); + CheckSub(T.Double, T.Number); + CheckSub(T.Smi, T.Signed32); + CheckUnordered(T.Smi, T.Double); + CheckUnordered(T.Signed32, T.Double); + + CheckSub(T.Name, T.Any); + CheckSub(T.UniqueName, T.Any); + CheckSub(T.UniqueName, T.Name); + CheckSub(T.String, T.Name); + CheckSub(T.InternalizedString, T.String); + CheckSub(T.InternalizedString, T.UniqueName); + CheckSub(T.InternalizedString, T.Name); + CheckSub(T.Symbol, T.UniqueName); + CheckSub(T.Symbol, T.Name); + CheckUnordered(T.String, T.UniqueName); + CheckUnordered(T.String, T.Symbol); + CheckUnordered(T.InternalizedString, T.Symbol); + + CheckSub(T.Receiver, T.Any); + CheckSub(T.Object, T.Any); + CheckSub(T.Object, T.Receiver); + CheckSub(T.Array, T.Object); + CheckSub(T.Function, T.Object); + CheckSub(T.Proxy, T.Receiver); + CheckUnordered(T.Object, T.Proxy); + CheckUnordered(T.Array, T.Function); + + // Structured subtyping + CheckSub(T.None, T.ObjectClass); + CheckSub(T.None, T.ObjectConstant1); + CheckSub(T.ObjectClass, T.Any); + CheckSub(T.ObjectConstant1, T.Any); + + CheckSub(T.ObjectClass, T.Object); + CheckSub(T.ArrayClass, T.Object); + CheckUnordered(T.ObjectClass, T.ArrayClass); + + CheckSub(T.SmiConstant, T.Smi); + CheckSub(T.SmiConstant, T.Signed32); + CheckSub(T.SmiConstant, T.Number); + CheckSub(T.ObjectConstant1, T.Object); + CheckSub(T.ObjectConstant2, T.Object); + CheckSub(T.ArrayConstant1, T.Object); + CheckSub(T.ArrayConstant1, T.Array); + CheckUnordered(T.ObjectConstant1, T.ObjectConstant2); + CheckUnordered(T.ObjectConstant1, T.ArrayConstant1); + + CheckUnordered(T.ObjectConstant1, T.ObjectClass); + CheckUnordered(T.ObjectConstant2, T.ObjectClass); + CheckUnordered(T.ObjectConstant1, T.ArrayClass); + CheckUnordered(T.ObjectConstant2, T.ArrayClass); + CheckUnordered(T.ArrayConstant1, T.ObjectClass); + } - Handle Union(Handle t1, Handle t2) { - return Type::Union(t1, t2, isolate_); + void Maybe() { + CheckOverlap(T.Any, T.Any); + CheckOverlap(T.Object, T.Object); + + CheckOverlap(T.Oddball, T.Any); + CheckOverlap(T.Boolean, T.Oddball); + CheckOverlap(T.Null, T.Oddball); + CheckOverlap(T.Undefined, T.Oddball); + CheckDisjoint(T.Boolean, T.Null); + CheckDisjoint(T.Undefined, T.Null); + CheckDisjoint(T.Boolean, T.Undefined); + + CheckOverlap(T.Number, T.Any); + CheckOverlap(T.Smi, T.Number); + CheckOverlap(T.Double, T.Number); + CheckDisjoint(T.Signed32, T.Double); + + CheckOverlap(T.Name, T.Any); + CheckOverlap(T.UniqueName, T.Any); + CheckOverlap(T.UniqueName, T.Name); + CheckOverlap(T.String, T.Name); + CheckOverlap(T.InternalizedString, T.String); + CheckOverlap(T.InternalizedString, T.UniqueName); + CheckOverlap(T.InternalizedString, T.Name); + CheckOverlap(T.Symbol, T.UniqueName); + CheckOverlap(T.Symbol, T.Name); + CheckOverlap(T.String, T.UniqueName); + CheckDisjoint(T.String, T.Symbol); + CheckDisjoint(T.InternalizedString, T.Symbol); + + CheckOverlap(T.Receiver, T.Any); + CheckOverlap(T.Object, T.Any); + CheckOverlap(T.Object, T.Receiver); + CheckOverlap(T.Array, T.Object); + CheckOverlap(T.Function, T.Object); + CheckOverlap(T.Proxy, T.Receiver); + CheckDisjoint(T.Object, T.Proxy); + CheckDisjoint(T.Array, T.Function); + + CheckOverlap(T.ObjectClass, T.Any); + CheckOverlap(T.ObjectConstant1, T.Any); + + CheckOverlap(T.ObjectClass, T.Object); + CheckOverlap(T.ArrayClass, T.Object); + CheckOverlap(T.ObjectClass, T.ObjectClass); + CheckOverlap(T.ArrayClass, T.ArrayClass); + CheckDisjoint(T.ObjectClass, T.ArrayClass); + + CheckOverlap(T.SmiConstant, T.Smi); + CheckOverlap(T.SmiConstant, T.Signed32); + CheckOverlap(T.SmiConstant, T.Number); + CheckDisjoint(T.SmiConstant, T.Double); + CheckOverlap(T.ObjectConstant1, T.Object); + CheckOverlap(T.ObjectConstant2, T.Object); + CheckOverlap(T.ArrayConstant1, T.Object); + CheckOverlap(T.ArrayConstant1, T.Array); + CheckOverlap(T.ArrayConstant1, T.ArrayConstant2); + CheckOverlap(T.ObjectConstant1, T.ObjectConstant1); + CheckDisjoint(T.ObjectConstant1, T.ObjectConstant2); + CheckDisjoint(T.ObjectConstant1, T.ArrayConstant1); + + CheckDisjoint(T.ObjectConstant1, T.ObjectClass); + CheckDisjoint(T.ObjectConstant2, T.ObjectClass); + CheckDisjoint(T.ObjectConstant1, T.ArrayClass); + CheckDisjoint(T.ObjectConstant2, T.ArrayClass); + CheckDisjoint(T.ArrayConstant1, T.ObjectClass); } - Handle Intersect(Handle t1, Handle t2) { - return Type::Intersect(t1, t2, isolate_); + + void Union() { + // Bitset-bitset + CHECK(IsBitset(T.Union(T.Object, T.Number))); + CHECK(IsBitset(T.Union(T.Object, T.Object))); + CHECK(IsBitset(T.Union(T.Any, T.None))); + + CheckEqual(T.Union(T.None, T.Number), T.Number); + CheckEqual(T.Union(T.Object, T.Proxy), T.Receiver); + CheckEqual(T.Union(T.Number, T.String), T.Union(T.String, T.Number)); + CheckSub(T.Union(T.Number, T.String), T.Any); + + // Class-class + CHECK(IsClass(T.Union(T.ObjectClass, T.ObjectClass))); + CHECK(IsUnion(T.Union(T.ObjectClass, T.ArrayClass))); + + CheckEqual(T.Union(T.ObjectClass, T.ObjectClass), T.ObjectClass); + CheckSub(T.None, T.Union(T.ObjectClass, T.ArrayClass)); + CheckSub(T.Union(T.ObjectClass, T.ArrayClass), T.Any); + CheckSub(T.ObjectClass, T.Union(T.ObjectClass, T.ArrayClass)); + CheckSub(T.ArrayClass, T.Union(T.ObjectClass, T.ArrayClass)); + CheckSub(T.Union(T.ObjectClass, T.ArrayClass), T.Object); + CheckUnordered(T.Union(T.ObjectClass, T.ArrayClass), T.Array); + CheckOverlap(T.Union(T.ObjectClass, T.ArrayClass), T.Array); + CheckDisjoint(T.Union(T.ObjectClass, T.ArrayClass), T.Number); + + // Constant-constant + CHECK(IsConstant(T.Union(T.ObjectConstant1, T.ObjectConstant1))); + CHECK(IsConstant(T.Union(T.ArrayConstant1, T.ArrayConstant1))); + CHECK(IsUnion(T.Union(T.ObjectConstant1, T.ObjectConstant2))); + + CheckEqual( + T.Union(T.ObjectConstant1, T.ObjectConstant1), + T.ObjectConstant1); + CheckEqual(T.Union(T.ArrayConstant1, T.ArrayConstant1), T.ArrayConstant1); + CheckEqual(T.Union(T.ArrayConstant1, T.ArrayConstant1), T.ArrayConstant2); + CheckSub(T.None, T.Union(T.ObjectConstant1, T.ObjectConstant2)); + CheckSub(T.Union(T.ObjectConstant1, T.ObjectConstant2), T.Any); + CheckSub(T.ObjectConstant1, T.Union(T.ObjectConstant1, T.ObjectConstant2)); + CheckSub(T.ObjectConstant2, T.Union(T.ObjectConstant1, T.ObjectConstant2)); + CheckSub(T.ArrayConstant2, T.Union(T.ArrayConstant1, T.ObjectConstant2)); + CheckSub(T.Union(T.ObjectConstant1, T.ObjectConstant2), T.Object); + CheckUnordered( + T.Union(T.ObjectConstant1, T.ObjectConstant2), T.ObjectClass); + CheckUnordered(T.Union(T.ObjectConstant1, T.ArrayConstant1), T.Array); + CheckOverlap(T.Union(T.ObjectConstant1, T.ArrayConstant1), T.Array); + CheckOverlap( + T.Union(T.ObjectConstant1, T.ArrayConstant1), T.ArrayConstant2); + CheckDisjoint(T.Union(T.ObjectConstant1, T.ArrayConstant1), T.Number); + CheckDisjoint(T.Union(T.ObjectConstant1, T.ArrayConstant1), T.ObjectClass); + + // Bitset-class + CHECK(IsBitset(T.Union(T.ObjectClass, T.Object))); + CHECK(IsUnion(T.Union(T.ObjectClass, T.Number))); + + CheckEqual(T.Union(T.ObjectClass, T.Object), T.Object); + CheckSub(T.None, T.Union(T.ObjectClass, T.Number)); + CheckSub(T.Union(T.ObjectClass, T.Number), T.Any); + CheckSub(T.Union(T.ObjectClass, T.Smi), T.Union(T.Object, T.Number)); + CheckSub(T.Union(T.ObjectClass, T.Array), T.Object); + CheckUnordered(T.Union(T.ObjectClass, T.String), T.Array); + CheckOverlap(T.Union(T.ObjectClass, T.String), T.Object); + CheckDisjoint(T.Union(T.ObjectClass, T.String), T.Number); + + // Bitset-constant + CHECK(IsBitset(T.Union(T.SmiConstant, T.Number))); + CHECK(IsBitset(T.Union(T.ObjectConstant1, T.Object))); + CHECK(IsUnion(T.Union(T.ObjectConstant2, T.Number))); + + CheckEqual(T.Union(T.SmiConstant, T.Number), T.Number); + CheckEqual(T.Union(T.ObjectConstant1, T.Object), T.Object); + CheckSub(T.None, T.Union(T.ObjectConstant1, T.Number)); + CheckSub(T.Union(T.ObjectConstant1, T.Number), T.Any); + CheckSub( + T.Union(T.ObjectConstant1, T.Signed32), T.Union(T.Object, T.Number)); + CheckSub(T.Union(T.ObjectConstant1, T.Array), T.Object); + CheckUnordered(T.Union(T.ObjectConstant1, T.String), T.Array); + CheckOverlap(T.Union(T.ObjectConstant1, T.String), T.Object); + CheckDisjoint(T.Union(T.ObjectConstant1, T.String), T.Number); + CheckEqual(T.Union(T.Signed32, T.Signed32Constant), T.Signed32); + + // Class-constant + CHECK(IsUnion(T.Union(T.ObjectConstant1, T.ObjectClass))); + CHECK(IsUnion(T.Union(T.ArrayClass, T.ObjectConstant2))); + + CheckSub(T.None, T.Union(T.ObjectConstant1, T.ArrayClass)); + CheckSub(T.Union(T.ObjectConstant1, T.ArrayClass), T.Any); + CheckSub(T.Union(T.ObjectConstant1, T.ArrayClass), T.Object); + CheckSub(T.ObjectConstant1, T.Union(T.ObjectConstant1, T.ArrayClass)); + CheckSub(T.ArrayClass, T.Union(T.ObjectConstant1, T.ArrayClass)); + CheckUnordered(T.ObjectClass, T.Union(T.ObjectConstant1, T.ArrayClass)); + CheckSub( + T.Union(T.ObjectConstant1, T.ArrayClass), T.Union(T.Array, T.Object)); + CheckUnordered(T.Union(T.ObjectConstant1, T.ArrayClass), T.ArrayConstant1); + CheckDisjoint(T.Union(T.ObjectConstant1, T.ArrayClass), T.ObjectConstant2); + CheckDisjoint(T.Union(T.ObjectConstant1, T.ArrayClass), T.ObjectClass); + + // Bitset-union + CHECK(IsBitset( + T.Union(T.Object, T.Union(T.ObjectConstant1, T.ObjectClass)))); + CHECK(IsUnion(T.Union(T.Union(T.ArrayClass, T.ObjectConstant2), T.Number))); + + CheckEqual( + T.Union(T.Object, T.Union(T.ObjectConstant1, T.ObjectClass)), + T.Object); + CheckEqual( + T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Number), + T.Union(T.ObjectConstant1, T.Union(T.Number, T.ArrayClass))); + CheckSub( + T.Double, + T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Number)); + CheckSub( + T.ObjectConstant1, + T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Double)); + CheckSub( + T.None, + T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Double)); + CheckSub( + T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Double), + T.Any); + CheckSub( + T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Double), + T.Union(T.ObjectConstant1, T.Union(T.Number, T.ArrayClass))); + + // Class-union + CHECK(IsUnion( + T.Union(T.Union(T.ArrayClass, T.ObjectConstant2), T.ArrayClass))); + CHECK(IsUnion( + T.Union(T.Union(T.ArrayClass, T.ObjectConstant2), T.ObjectClass))); + + CheckEqual( + T.Union(T.ObjectClass, T.Union(T.ObjectConstant1, T.ObjectClass)), + T.Union(T.ObjectClass, T.ObjectConstant1)); + CheckSub( + T.None, + T.Union(T.ObjectClass, T.Union(T.ObjectConstant1, T.ObjectClass))); + CheckSub( + T.Union(T.ObjectClass, T.Union(T.ObjectConstant1, T.ObjectClass)), + T.Any); + CheckSub( + T.Union(T.ObjectClass, T.Union(T.ObjectConstant1, T.ObjectClass)), + T.Object); + CheckEqual( + T.Union(T.Union(T.ArrayClass, T.ObjectConstant2), T.ArrayClass), + T.Union(T.ArrayClass, T.ObjectConstant2)); + + // Constant-union + CHECK(IsUnion(T.Union( + T.ObjectConstant1, T.Union(T.ObjectConstant1, T.ObjectConstant2)))); + CHECK(IsUnion(T.Union( + T.Union(T.ArrayConstant1, T.ObjectClass), T.ObjectConstant1))); + CHECK(IsUnion(T.Union( + T.Union(T.ArrayConstant1, T.ObjectConstant2), T.ObjectConstant1))); + + CheckEqual( + T.Union( + T.ObjectConstant1, T.Union(T.ObjectConstant1, T.ObjectConstant2)), + T.Union(T.ObjectConstant2, T.ObjectConstant1)); + CheckEqual( + T.Union( + T.Union(T.ArrayConstant1, T.ObjectConstant2), T.ObjectConstant1), + T.Union( + T.ObjectConstant2, T.Union(T.ArrayConstant1, T.ObjectConstant1))); + + // Union-union + CHECK(IsBitset(T.Union( + T.Union(T.Number, T.ArrayClass), + T.Union(T.Signed32, T.Array)))); + CHECK(IsUnion(T.Union( + T.Union(T.Number, T.ArrayClass), + T.Union(T.ObjectClass, T.ArrayClass)))); + + CheckEqual( + T.Union( + T.Union(T.ObjectConstant2, T.ObjectConstant1), + T.Union(T.ObjectConstant1, T.ObjectConstant2)), + T.Union(T.ObjectConstant2, T.ObjectConstant1)); + CheckEqual( + T.Union( + T.Union(T.ObjectConstant2, T.ArrayConstant1), + T.Union(T.ObjectConstant1, T.ArrayConstant2)), + T.Union( + T.Union(T.ObjectConstant1, T.ObjectConstant2), + T.ArrayConstant1)); + CheckEqual( + T.Union(T.Union(T.Number, T.ArrayClass), T.Union(T.Smi, T.Array)), + T.Union(T.Number, T.Array)); } - private: - Isolate* isolate_; + void Intersect() { + // Bitset-bitset + CHECK(IsBitset(T.Intersect(T.Object, T.Number))); + CHECK(IsBitset(T.Intersect(T.Object, T.Object))); + CHECK(IsBitset(T.Intersect(T.Any, T.None))); + + CheckEqual(T.Intersect(T.None, T.Number), T.None); + CheckEqual(T.Intersect(T.Object, T.Proxy), T.None); + CheckEqual(T.Intersect(T.Name, T.String), T.Intersect(T.String, T.Name)); + CheckEqual(T.Intersect(T.UniqueName, T.String), T.InternalizedString); + + // Class-class + CHECK(IsClass(T.Intersect(T.ObjectClass, T.ObjectClass))); + CHECK(IsBitset(T.Intersect(T.ObjectClass, T.ArrayClass))); + + CheckEqual(T.Intersect(T.ObjectClass, T.ObjectClass), T.ObjectClass); + CheckEqual(T.Intersect(T.ObjectClass, T.ArrayClass), T.None); + + // Constant-constant + CHECK(IsConstant(T.Intersect(T.ObjectConstant1, T.ObjectConstant1))); + CHECK(IsConstant(T.Intersect(T.ArrayConstant1, T.ArrayConstant2))); + CHECK(IsBitset(T.Intersect(T.ObjectConstant1, T.ObjectConstant2))); + + CheckEqual( + T.Intersect(T.ObjectConstant1, T.ObjectConstant1), T.ObjectConstant1); + CheckEqual( + T.Intersect(T.ArrayConstant1, T.ArrayConstant2), T.ArrayConstant1); + CheckEqual(T.Intersect(T.ObjectConstant1, T.ObjectConstant2), T.None); + + // Bitset-class + CHECK(IsClass(T.Intersect(T.ObjectClass, T.Object))); + CHECK(IsBitset(T.Intersect(T.ObjectClass, T.Number))); + + CheckEqual(T.Intersect(T.ObjectClass, T.Object), T.ObjectClass); + CheckEqual(T.Intersect(T.ObjectClass, T.Array), T.None); + CheckEqual(T.Intersect(T.ObjectClass, T.Number), T.None); + + // Bitset-constant + CHECK(IsBitset(T.Intersect(T.Smi, T.Number))); + CHECK(IsConstant(T.Intersect(T.SmiConstant, T.Number))); + CHECK(IsConstant(T.Intersect(T.ObjectConstant1, T.Object))); + + CheckEqual(T.Intersect(T.Smi, T.Number), T.Smi); + CheckEqual(T.Intersect(T.SmiConstant, T.Number), T.SmiConstant); + CheckEqual(T.Intersect(T.ObjectConstant1, T.Object), T.ObjectConstant1); + + // Class-constant + CHECK(IsBitset(T.Intersect(T.ObjectConstant1, T.ObjectClass))); + CHECK(IsBitset(T.Intersect(T.ArrayClass, T.ObjectConstant2))); + + CheckEqual(T.Intersect(T.ObjectConstant1, T.ObjectClass), T.None); + CheckEqual(T.Intersect(T.ArrayClass, T.ObjectConstant2), T.None); + + // Bitset-union + CHECK(IsUnion( + T.Intersect(T.Object, T.Union(T.ObjectConstant1, T.ObjectClass)))); + CHECK(IsBitset( + T.Intersect(T.Union(T.ArrayClass, T.ObjectConstant2), T.Number))); + + CheckEqual( + T.Intersect(T.Object, T.Union(T.ObjectConstant1, T.ObjectClass)), + T.Union(T.ObjectConstant1, T.ObjectClass)); + CheckEqual( + T.Intersect(T.Union(T.ArrayClass, T.ObjectConstant1), T.Number), + T.None); + + // Class-union + CHECK(IsClass( + T.Intersect(T.Union(T.ArrayClass, T.ObjectConstant2), T.ArrayClass))); + CHECK(IsClass( + T.Intersect(T.Union(T.Object, T.SmiConstant), T.ArrayClass))); + CHECK(IsBitset( + T.Intersect(T.Union(T.ObjectClass, T.ArrayConstant1), T.ArrayClass))); + + CheckEqual( + T.Intersect(T.ArrayClass, T.Union(T.ObjectConstant2, T.ArrayClass)), + T.ArrayClass); + CheckEqual( + T.Intersect(T.ArrayClass, T.Union(T.Object, T.SmiConstant)), + T.ArrayClass); + CheckEqual( + T.Intersect(T.Union(T.ObjectClass, T.ArrayConstant1), T.ArrayClass), + T.None); + + // Constant-union + CHECK(IsConstant(T.Intersect( + T.ObjectConstant1, T.Union(T.ObjectConstant1, T.ObjectConstant2)))); + CHECK(IsConstant(T.Intersect( + T.Union(T.Number, T.ObjectClass), T.SmiConstant))); + CHECK(IsBitset(T.Intersect( + T.Union(T.ArrayConstant1, T.ObjectClass), T.ObjectConstant1))); + + CheckEqual( + T.Intersect( + T.ObjectConstant1, T.Union(T.ObjectConstant1, T.ObjectConstant2)), + T.ObjectConstant1); + CheckEqual( + T.Intersect(T.SmiConstant, T.Union(T.Number, T.ObjectConstant2)), + T.SmiConstant); + CheckEqual( + T.Intersect( + T.Union(T.ArrayConstant1, T.ObjectClass), T.ObjectConstant1), + T.None); + + // Union-union + CHECK(IsUnion(T.Intersect( + T.Union(T.Number, T.ArrayClass), T.Union(T.Signed32, T.Array)))); + CHECK(IsBitset(T.Intersect( + T.Union(T.Number, T.ObjectClass), T.Union(T.Signed32, T.Array)))); + + CheckEqual( + T.Intersect( + T.Union(T.Number, T.ArrayClass), + T.Union(T.Smi, T.Array)), + T.Union(T.Smi, T.ArrayClass)); + CheckEqual( + T.Intersect( + T.Union(T.Number, T.ObjectClass), + T.Union(T.Signed32, T.Array)), + T.Signed32); + CheckEqual( + T.Intersect( + T.Union(T.ObjectConstant2, T.ObjectConstant1), + T.Union(T.ObjectConstant1, T.ObjectConstant2)), + T.Union(T.ObjectConstant2, T.ObjectConstant1)); + CheckEqual( + T.Intersect( + T.Union( + T.Union(T.ObjectConstant2, T.ObjectConstant1), T.ArrayClass), + T.Union( + T.ObjectConstant1, + T.Union(T.ArrayConstant1, T.ObjectConstant2))), + T.Union(T.ObjectConstant2, T.ObjectConstant1)); + CheckEqual( + T.Intersect( + T.Union(T.ObjectConstant2, T.ArrayConstant1), + T.Union(T.ObjectConstant1, T.ArrayConstant2)), + T.ArrayConstant1); + } }; +typedef Tests ZoneTests; +typedef Tests, Isolate, HeapRep> HeapTests; + TEST(Bitset) { CcTest::InitializeVM(); - Isolate* isolate = CcTest::i_isolate(); - HandleScope scope(isolate); - HandlifiedTypes T(isolate); - - CHECK(IsBitset(T.None)); - CHECK(IsBitset(T.Any)); - CHECK(IsBitset(T.String)); - CHECK(IsBitset(T.Object)); - - CHECK(IsBitset(T.Union(T.String, T.Number))); - CHECK(IsBitset(T.Union(T.String, T.Receiver))); - - CHECK_EQ(0, AsBitset(T.None)); - CHECK_EQ(AsBitset(T.Number) | AsBitset(T.String), - AsBitset(T.Union(T.String, T.Number))); - CHECK_EQ(AsBitset(T.Receiver), - AsBitset(T.Union(T.Receiver, T.Object))); + ZoneTests().Bitset(); + HeapTests().Bitset(); } TEST(Class) { CcTest::InitializeVM(); - Isolate* isolate = CcTest::i_isolate(); - HandleScope scope(isolate); - HandlifiedTypes T(isolate); - - CHECK(IsClass(T.ObjectClass)); - CHECK(IsClass(T.ArrayClass)); - - CHECK(*T.object_map == AsClass(T.ObjectClass)); - CHECK(*T.array_map == AsClass(T.ArrayClass)); + ZoneTests().Class(); + HeapTests().Class(); } TEST(Constant) { CcTest::InitializeVM(); - Isolate* isolate = CcTest::i_isolate(); - HandleScope scope(isolate); - HandlifiedTypes T(isolate); - - CHECK(IsConstant(T.SmiConstant)); - CHECK(IsConstant(T.ObjectConstant1)); - CHECK(IsConstant(T.ObjectConstant2)); - CHECK(IsConstant(T.ArrayConstant1)); - CHECK(IsConstant(T.ArrayConstant2)); - - CHECK(*T.smi == AsConstant(T.SmiConstant)); - CHECK(*T.object1 == AsConstant(T.ObjectConstant1)); - CHECK(*T.object2 == AsConstant(T.ObjectConstant2)); - CHECK(*T.object1 != AsConstant(T.ObjectConstant2)); - CHECK(*T.array == AsConstant(T.ArrayConstant1)); - CHECK(*T.array == AsConstant(T.ArrayConstant2)); + ZoneTests().Constant(); + HeapTests().Constant(); } TEST(Is) { CcTest::InitializeVM(); - Isolate* isolate = CcTest::i_isolate(); - HandleScope scope(isolate); - HandlifiedTypes T(isolate); - - // Reflexivity - CHECK(T.None->Is(T.None)); - CHECK(T.Any->Is(T.Any)); - CHECK(T.Object->Is(T.Object)); - - CHECK(T.ObjectClass->Is(T.ObjectClass)); - CHECK(T.ObjectConstant1->Is(T.ObjectConstant1)); - CHECK(T.ArrayConstant1->Is(T.ArrayConstant2)); - - // Symmetry and Transitivity - CheckSub(T.None, T.Number); - CheckSub(T.None, T.Any); - - CheckSub(T.Oddball, T.Any); - CheckSub(T.Boolean, T.Oddball); - CheckSub(T.Null, T.Oddball); - CheckSub(T.Undefined, T.Oddball); - CheckUnordered(T.Boolean, T.Null); - CheckUnordered(T.Undefined, T.Null); - CheckUnordered(T.Boolean, T.Undefined); - - CheckSub(T.Number, T.Any); - CheckSub(T.Smi, T.Number); - CheckSub(T.Signed32, T.Number); - CheckSub(T.Double, T.Number); - CheckSub(T.Smi, T.Signed32); - CheckUnordered(T.Smi, T.Double); - CheckUnordered(T.Signed32, T.Double); - - CheckSub(T.Name, T.Any); - CheckSub(T.UniqueName, T.Any); - CheckSub(T.UniqueName, T.Name); - CheckSub(T.String, T.Name); - CheckSub(T.InternalizedString, T.String); - CheckSub(T.InternalizedString, T.UniqueName); - CheckSub(T.InternalizedString, T.Name); - CheckSub(T.Symbol, T.UniqueName); - CheckSub(T.Symbol, T.Name); - CheckUnordered(T.String, T.UniqueName); - CheckUnordered(T.String, T.Symbol); - CheckUnordered(T.InternalizedString, T.Symbol); - - CheckSub(T.Receiver, T.Any); - CheckSub(T.Object, T.Any); - CheckSub(T.Object, T.Receiver); - CheckSub(T.Array, T.Object); - CheckSub(T.Function, T.Object); - CheckSub(T.Proxy, T.Receiver); - CheckUnordered(T.Object, T.Proxy); - CheckUnordered(T.Array, T.Function); - - // Structured subtyping - CheckSub(T.None, T.ObjectClass); - CheckSub(T.None, T.ObjectConstant1); - CheckSub(T.ObjectClass, T.Any); - CheckSub(T.ObjectConstant1, T.Any); - - CheckSub(T.ObjectClass, T.Object); - CheckSub(T.ArrayClass, T.Object); - CheckUnordered(T.ObjectClass, T.ArrayClass); - - CheckSub(T.SmiConstant, T.Smi); - CheckSub(T.SmiConstant, T.Signed32); - CheckSub(T.SmiConstant, T.Number); - CheckSub(T.ObjectConstant1, T.Object); - CheckSub(T.ObjectConstant2, T.Object); - CheckSub(T.ArrayConstant1, T.Object); - CheckSub(T.ArrayConstant1, T.Array); - CheckUnordered(T.ObjectConstant1, T.ObjectConstant2); - CheckUnordered(T.ObjectConstant1, T.ArrayConstant1); - - CheckUnordered(T.ObjectConstant1, T.ObjectClass); - CheckUnordered(T.ObjectConstant2, T.ObjectClass); - CheckUnordered(T.ObjectConstant1, T.ArrayClass); - CheckUnordered(T.ObjectConstant2, T.ArrayClass); - CheckUnordered(T.ArrayConstant1, T.ObjectClass); + ZoneTests().Is(); + HeapTests().Is(); } TEST(Maybe) { CcTest::InitializeVM(); - Isolate* isolate = CcTest::i_isolate(); - HandleScope scope(isolate); - HandlifiedTypes T(isolate); - - CheckOverlap(T.Any, T.Any); - CheckOverlap(T.Object, T.Object); - - CheckOverlap(T.Oddball, T.Any); - CheckOverlap(T.Boolean, T.Oddball); - CheckOverlap(T.Null, T.Oddball); - CheckOverlap(T.Undefined, T.Oddball); - CheckDisjoint(T.Boolean, T.Null); - CheckDisjoint(T.Undefined, T.Null); - CheckDisjoint(T.Boolean, T.Undefined); - - CheckOverlap(T.Number, T.Any); - CheckOverlap(T.Smi, T.Number); - CheckOverlap(T.Double, T.Number); - CheckDisjoint(T.Signed32, T.Double); - - CheckOverlap(T.Name, T.Any); - CheckOverlap(T.UniqueName, T.Any); - CheckOverlap(T.UniqueName, T.Name); - CheckOverlap(T.String, T.Name); - CheckOverlap(T.InternalizedString, T.String); - CheckOverlap(T.InternalizedString, T.UniqueName); - CheckOverlap(T.InternalizedString, T.Name); - CheckOverlap(T.Symbol, T.UniqueName); - CheckOverlap(T.Symbol, T.Name); - CheckOverlap(T.String, T.UniqueName); - CheckDisjoint(T.String, T.Symbol); - CheckDisjoint(T.InternalizedString, T.Symbol); - - CheckOverlap(T.Receiver, T.Any); - CheckOverlap(T.Object, T.Any); - CheckOverlap(T.Object, T.Receiver); - CheckOverlap(T.Array, T.Object); - CheckOverlap(T.Function, T.Object); - CheckOverlap(T.Proxy, T.Receiver); - CheckDisjoint(T.Object, T.Proxy); - CheckDisjoint(T.Array, T.Function); - - CheckOverlap(T.ObjectClass, T.Any); - CheckOverlap(T.ObjectConstant1, T.Any); - - CheckOverlap(T.ObjectClass, T.Object); - CheckOverlap(T.ArrayClass, T.Object); - CheckOverlap(T.ObjectClass, T.ObjectClass); - CheckOverlap(T.ArrayClass, T.ArrayClass); - CheckDisjoint(T.ObjectClass, T.ArrayClass); - - CheckOverlap(T.SmiConstant, T.Smi); - CheckOverlap(T.SmiConstant, T.Signed32); - CheckOverlap(T.SmiConstant, T.Number); - CheckDisjoint(T.SmiConstant, T.Double); - CheckOverlap(T.ObjectConstant1, T.Object); - CheckOverlap(T.ObjectConstant2, T.Object); - CheckOverlap(T.ArrayConstant1, T.Object); - CheckOverlap(T.ArrayConstant1, T.Array); - CheckOverlap(T.ArrayConstant1, T.ArrayConstant2); - CheckOverlap(T.ObjectConstant1, T.ObjectConstant1); - CheckDisjoint(T.ObjectConstant1, T.ObjectConstant2); - CheckDisjoint(T.ObjectConstant1, T.ArrayConstant1); - - CheckDisjoint(T.ObjectConstant1, T.ObjectClass); - CheckDisjoint(T.ObjectConstant2, T.ObjectClass); - CheckDisjoint(T.ObjectConstant1, T.ArrayClass); - CheckDisjoint(T.ObjectConstant2, T.ArrayClass); - CheckDisjoint(T.ArrayConstant1, T.ObjectClass); + ZoneTests().Maybe(); + HeapTests().Maybe(); } TEST(Union) { CcTest::InitializeVM(); - Isolate* isolate = CcTest::i_isolate(); - HandleScope scope(isolate); - HandlifiedTypes T(isolate); - - // Bitset-bitset - CHECK(IsBitset(T.Union(T.Object, T.Number))); - CHECK(IsBitset(T.Union(T.Object, T.Object))); - CHECK(IsBitset(T.Union(T.Any, T.None))); - - CheckEqual(T.Union(T.None, T.Number), T.Number); - CheckEqual(T.Union(T.Object, T.Proxy), T.Receiver); - CheckEqual(T.Union(T.Number, T.String), T.Union(T.String, T.Number)); - CheckSub(T.Union(T.Number, T.String), T.Any); - - // Class-class - CHECK(IsClass(T.Union(T.ObjectClass, T.ObjectClass))); - CHECK(IsUnion(T.Union(T.ObjectClass, T.ArrayClass))); - - CheckEqual(T.Union(T.ObjectClass, T.ObjectClass), T.ObjectClass); - CheckSub(T.None, T.Union(T.ObjectClass, T.ArrayClass)); - CheckSub(T.Union(T.ObjectClass, T.ArrayClass), T.Any); - CheckSub(T.ObjectClass, T.Union(T.ObjectClass, T.ArrayClass)); - CheckSub(T.ArrayClass, T.Union(T.ObjectClass, T.ArrayClass)); - CheckSub(T.Union(T.ObjectClass, T.ArrayClass), T.Object); - CheckUnordered(T.Union(T.ObjectClass, T.ArrayClass), T.Array); - CheckOverlap(T.Union(T.ObjectClass, T.ArrayClass), T.Array); - CheckDisjoint(T.Union(T.ObjectClass, T.ArrayClass), T.Number); - - // Constant-constant - CHECK(IsConstant(T.Union(T.ObjectConstant1, T.ObjectConstant1))); - CHECK(IsConstant(T.Union(T.ArrayConstant1, T.ArrayConstant1))); - CHECK(IsUnion(T.Union(T.ObjectConstant1, T.ObjectConstant2))); - - CheckEqual(T.Union(T.ObjectConstant1, T.ObjectConstant1), T.ObjectConstant1); - CheckEqual(T.Union(T.ArrayConstant1, T.ArrayConstant1), T.ArrayConstant1); - CheckEqual(T.Union(T.ArrayConstant1, T.ArrayConstant1), T.ArrayConstant2); - CheckSub(T.None, T.Union(T.ObjectConstant1, T.ObjectConstant2)); - CheckSub(T.Union(T.ObjectConstant1, T.ObjectConstant2), T.Any); - CheckSub(T.ObjectConstant1, T.Union(T.ObjectConstant1, T.ObjectConstant2)); - CheckSub(T.ObjectConstant2, T.Union(T.ObjectConstant1, T.ObjectConstant2)); - CheckSub(T.ArrayConstant2, T.Union(T.ArrayConstant1, T.ObjectConstant2)); - CheckSub(T.Union(T.ObjectConstant1, T.ObjectConstant2), T.Object); - CheckUnordered(T.Union(T.ObjectConstant1, T.ObjectConstant2), T.ObjectClass); - CheckUnordered(T.Union(T.ObjectConstant1, T.ArrayConstant1), T.Array); - CheckOverlap(T.Union(T.ObjectConstant1, T.ArrayConstant1), T.Array); - CheckOverlap(T.Union(T.ObjectConstant1, T.ArrayConstant1), T.ArrayConstant2); - CheckDisjoint(T.Union(T.ObjectConstant1, T.ArrayConstant1), T.Number); - CheckDisjoint(T.Union(T.ObjectConstant1, T.ArrayConstant1), T.ObjectClass); - - // Bitset-class - CHECK(IsBitset(T.Union(T.ObjectClass, T.Object))); - CHECK(IsUnion(T.Union(T.ObjectClass, T.Number))); - - CheckEqual(T.Union(T.ObjectClass, T.Object), T.Object); - CheckSub(T.None, T.Union(T.ObjectClass, T.Number)); - CheckSub(T.Union(T.ObjectClass, T.Number), T.Any); - CheckSub(T.Union(T.ObjectClass, T.Smi), T.Union(T.Object, T.Number)); - CheckSub(T.Union(T.ObjectClass, T.Array), T.Object); - CheckUnordered(T.Union(T.ObjectClass, T.String), T.Array); - CheckOverlap(T.Union(T.ObjectClass, T.String), T.Object); - CheckDisjoint(T.Union(T.ObjectClass, T.String), T.Number); - - // Bitset-constant - CHECK(IsBitset(T.Union(T.SmiConstant, T.Number))); - CHECK(IsBitset(T.Union(T.ObjectConstant1, T.Object))); - CHECK(IsUnion(T.Union(T.ObjectConstant2, T.Number))); - - CheckEqual(T.Union(T.SmiConstant, T.Number), T.Number); - CheckEqual(T.Union(T.ObjectConstant1, T.Object), T.Object); - CheckSub(T.None, T.Union(T.ObjectConstant1, T.Number)); - CheckSub(T.Union(T.ObjectConstant1, T.Number), T.Any); - CheckSub(T.Union(T.ObjectConstant1, T.Signed32), T.Union(T.Object, T.Number)); - CheckSub(T.Union(T.ObjectConstant1, T.Array), T.Object); - CheckUnordered(T.Union(T.ObjectConstant1, T.String), T.Array); - CheckOverlap(T.Union(T.ObjectConstant1, T.String), T.Object); - CheckDisjoint(T.Union(T.ObjectConstant1, T.String), T.Number); - CheckEqual(T.Union(T.Signed32, T.Signed32Constant), T.Signed32); - - // Class-constant - CHECK(IsUnion(T.Union(T.ObjectConstant1, T.ObjectClass))); - CHECK(IsUnion(T.Union(T.ArrayClass, T.ObjectConstant2))); - - CheckSub(T.None, T.Union(T.ObjectConstant1, T.ArrayClass)); - CheckSub(T.Union(T.ObjectConstant1, T.ArrayClass), T.Any); - CheckSub(T.Union(T.ObjectConstant1, T.ArrayClass), T.Object); - CheckSub(T.ObjectConstant1, T.Union(T.ObjectConstant1, T.ArrayClass)); - CheckSub(T.ArrayClass, T.Union(T.ObjectConstant1, T.ArrayClass)); - CheckUnordered(T.ObjectClass, T.Union(T.ObjectConstant1, T.ArrayClass)); - CheckSub( - T.Union(T.ObjectConstant1, T.ArrayClass), T.Union(T.Array, T.Object)); - CheckUnordered(T.Union(T.ObjectConstant1, T.ArrayClass), T.ArrayConstant1); - CheckDisjoint(T.Union(T.ObjectConstant1, T.ArrayClass), T.ObjectConstant2); - CheckDisjoint(T.Union(T.ObjectConstant1, T.ArrayClass), T.ObjectClass); - - // Bitset-union - CHECK(IsBitset(T.Union(T.Object, T.Union(T.ObjectConstant1, T.ObjectClass)))); - CHECK(IsUnion(T.Union(T.Union(T.ArrayClass, T.ObjectConstant2), T.Number))); - - CheckEqual( - T.Union(T.Object, T.Union(T.ObjectConstant1, T.ObjectClass)), - T.Object); - CheckEqual( - T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Number), - T.Union(T.ObjectConstant1, T.Union(T.Number, T.ArrayClass))); - CheckSub( - T.Double, - T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Number)); - CheckSub( - T.ObjectConstant1, - T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Double)); - CheckSub( - T.None, - T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Double)); - CheckSub( - T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Double), - T.Any); - CheckSub( - T.Union(T.Union(T.ArrayClass, T.ObjectConstant1), T.Double), - T.Union(T.ObjectConstant1, T.Union(T.Number, T.ArrayClass))); - - // Class-union - CHECK(IsUnion( - T.Union(T.Union(T.ArrayClass, T.ObjectConstant2), T.ArrayClass))); - CHECK(IsUnion( - T.Union(T.Union(T.ArrayClass, T.ObjectConstant2), T.ObjectClass))); - - CheckEqual( - T.Union(T.ObjectClass, T.Union(T.ObjectConstant1, T.ObjectClass)), - T.Union(T.ObjectClass, T.ObjectConstant1)); - CheckSub( - T.None, - T.Union(T.ObjectClass, T.Union(T.ObjectConstant1, T.ObjectClass))); - CheckSub( - T.Union(T.ObjectClass, T.Union(T.ObjectConstant1, T.ObjectClass)), - T.Any); - CheckSub( - T.Union(T.ObjectClass, T.Union(T.ObjectConstant1, T.ObjectClass)), - T.Object); - CheckEqual( - T.Union(T.Union(T.ArrayClass, T.ObjectConstant2), T.ArrayClass), - T.Union(T.ArrayClass, T.ObjectConstant2)); - - // Constant-union - CHECK(IsUnion(T.Union( - T.ObjectConstant1, T.Union(T.ObjectConstant1, T.ObjectConstant2)))); - CHECK(IsUnion(T.Union( - T.Union(T.ArrayConstant1, T.ObjectClass), T.ObjectConstant1))); - CHECK(IsUnion(T.Union( - T.Union(T.ArrayConstant1, T.ObjectConstant2), T.ObjectConstant1))); - - CheckEqual( - T.Union(T.ObjectConstant1, T.Union(T.ObjectConstant1, T.ObjectConstant2)), - T.Union(T.ObjectConstant2, T.ObjectConstant1)); - CheckEqual( - T.Union(T.Union(T.ArrayConstant1, T.ObjectConstant2), T.ObjectConstant1), - T.Union(T.ObjectConstant2, T.Union(T.ArrayConstant1, T.ObjectConstant1))); - - // Union-union - CHECK(IsBitset(T.Union( - T.Union(T.Number, T.ArrayClass), T.Union(T.Signed32, T.Array)))); - CHECK(IsUnion(T.Union( - T.Union(T.Number, T.ArrayClass), T.Union(T.ObjectClass, T.ArrayClass)))); - - CheckEqual( - T.Union( - T.Union(T.ObjectConstant2, T.ObjectConstant1), - T.Union(T.ObjectConstant1, T.ObjectConstant2)), - T.Union(T.ObjectConstant2, T.ObjectConstant1)); - CheckEqual( - T.Union( - T.Union(T.ObjectConstant2, T.ArrayConstant1), - T.Union(T.ObjectConstant1, T.ArrayConstant2)), - T.Union(T.Union(T.ObjectConstant1, T.ObjectConstant2), T.ArrayConstant1)); - CheckEqual( - T.Union(T.Union(T.Number, T.ArrayClass), T.Union(T.Smi, T.Array)), - T.Union(T.Number, T.Array)); + ZoneTests().Union(); + HeapTests().Union(); } TEST(Intersect) { CcTest::InitializeVM(); - Isolate* isolate = CcTest::i_isolate(); - HandleScope scope(isolate); - HandlifiedTypes T(isolate); - - // Bitset-bitset - CHECK(IsBitset(T.Intersect(T.Object, T.Number))); - CHECK(IsBitset(T.Intersect(T.Object, T.Object))); - CHECK(IsBitset(T.Intersect(T.Any, T.None))); - - CheckEqual(T.Intersect(T.None, T.Number), T.None); - CheckEqual(T.Intersect(T.Object, T.Proxy), T.None); - CheckEqual(T.Intersect(T.Name, T.String), T.Intersect(T.String, T.Name)); - CheckEqual(T.Intersect(T.UniqueName, T.String), T.InternalizedString); - - // Class-class - CHECK(IsClass(T.Intersect(T.ObjectClass, T.ObjectClass))); - CHECK(IsBitset(T.Intersect(T.ObjectClass, T.ArrayClass))); - - CheckEqual(T.Intersect(T.ObjectClass, T.ObjectClass), T.ObjectClass); - CheckEqual(T.Intersect(T.ObjectClass, T.ArrayClass), T.None); - - // Constant-constant - CHECK(IsConstant(T.Intersect(T.ObjectConstant1, T.ObjectConstant1))); - CHECK(IsConstant(T.Intersect(T.ArrayConstant1, T.ArrayConstant2))); - CHECK(IsBitset(T.Intersect(T.ObjectConstant1, T.ObjectConstant2))); - - CheckEqual( - T.Intersect(T.ObjectConstant1, T.ObjectConstant1), T.ObjectConstant1); - CheckEqual( - T.Intersect(T.ArrayConstant1, T.ArrayConstant2), T.ArrayConstant1); - CheckEqual(T.Intersect(T.ObjectConstant1, T.ObjectConstant2), T.None); - - // Bitset-class - CHECK(IsClass(T.Intersect(T.ObjectClass, T.Object))); - CHECK(IsBitset(T.Intersect(T.ObjectClass, T.Number))); - - CheckEqual(T.Intersect(T.ObjectClass, T.Object), T.ObjectClass); - CheckEqual(T.Intersect(T.ObjectClass, T.Array), T.None); - CheckEqual(T.Intersect(T.ObjectClass, T.Number), T.None); - - // Bitset-constant - CHECK(IsBitset(T.Intersect(T.Smi, T.Number))); - CHECK(IsConstant(T.Intersect(T.SmiConstant, T.Number))); - CHECK(IsConstant(T.Intersect(T.ObjectConstant1, T.Object))); - - CheckEqual(T.Intersect(T.Smi, T.Number), T.Smi); - CheckEqual(T.Intersect(T.SmiConstant, T.Number), T.SmiConstant); - CheckEqual(T.Intersect(T.ObjectConstant1, T.Object), T.ObjectConstant1); - - // Class-constant - CHECK(IsBitset(T.Intersect(T.ObjectConstant1, T.ObjectClass))); - CHECK(IsBitset(T.Intersect(T.ArrayClass, T.ObjectConstant2))); - - CheckEqual(T.Intersect(T.ObjectConstant1, T.ObjectClass), T.None); - CheckEqual(T.Intersect(T.ArrayClass, T.ObjectConstant2), T.None); - - // Bitset-union - CHECK(IsUnion( - T.Intersect(T.Object, T.Union(T.ObjectConstant1, T.ObjectClass)))); - CHECK(IsBitset( - T.Intersect(T.Union(T.ArrayClass, T.ObjectConstant2), T.Number))); - - CheckEqual( - T.Intersect(T.Object, T.Union(T.ObjectConstant1, T.ObjectClass)), - T.Union(T.ObjectConstant1, T.ObjectClass)); - CheckEqual( - T.Intersect(T.Union(T.ArrayClass, T.ObjectConstant1), T.Number), - T.None); - - // Class-union - CHECK(IsClass( - T.Intersect(T.Union(T.ArrayClass, T.ObjectConstant2), T.ArrayClass))); - CHECK(IsClass( - T.Intersect(T.Union(T.Object, T.SmiConstant), T.ArrayClass))); - CHECK(IsBitset( - T.Intersect(T.Union(T.ObjectClass, T.ArrayConstant1), T.ArrayClass))); - - CheckEqual( - T.Intersect(T.ArrayClass, T.Union(T.ObjectConstant2, T.ArrayClass)), - T.ArrayClass); - CheckEqual( - T.Intersect(T.ArrayClass, T.Union(T.Object, T.SmiConstant)), - T.ArrayClass); - CheckEqual( - T.Intersect(T.Union(T.ObjectClass, T.ArrayConstant1), T.ArrayClass), - T.None); - - // Constant-union - CHECK(IsConstant(T.Intersect( - T.ObjectConstant1, T.Union(T.ObjectConstant1, T.ObjectConstant2)))); - CHECK(IsConstant(T.Intersect( - T.Union(T.Number, T.ObjectClass), T.SmiConstant))); - CHECK(IsBitset(T.Intersect( - T.Union(T.ArrayConstant1, T.ObjectClass), T.ObjectConstant1))); - - CheckEqual( - T.Intersect( - T.ObjectConstant1, T.Union(T.ObjectConstant1, T.ObjectConstant2)), - T.ObjectConstant1); - CheckEqual( - T.Intersect(T.SmiConstant, T.Union(T.Number, T.ObjectConstant2)), - T.SmiConstant); - CheckEqual( - T.Intersect(T.Union(T.ArrayConstant1, T.ObjectClass), T.ObjectConstant1), - T.None); - - // Union-union - CHECK(IsUnion(T.Intersect( - T.Union(T.Number, T.ArrayClass), T.Union(T.Signed32, T.Array)))); - CHECK(IsBitset(T.Intersect( - T.Union(T.Number, T.ObjectClass), T.Union(T.Signed32, T.Array)))); - - CheckEqual( - T.Intersect( - T.Union(T.Number, T.ArrayClass), - T.Union(T.Smi, T.Array)), - T.Union(T.Smi, T.ArrayClass)); - CheckEqual( - T.Intersect( - T.Union(T.Number, T.ObjectClass), - T.Union(T.Signed32, T.Array)), - T.Signed32); - CheckEqual( - T.Intersect( - T.Union(T.ObjectConstant2, T.ObjectConstant1), - T.Union(T.ObjectConstant1, T.ObjectConstant2)), - T.Union(T.ObjectConstant2, T.ObjectConstant1)); - CheckEqual( - T.Intersect( - T.Union(T.Union(T.ObjectConstant2, T.ObjectConstant1), T.ArrayClass), - T.Union( - T.ObjectConstant1, T.Union(T.ArrayConstant1, T.ObjectConstant2))), - T.Union(T.ObjectConstant2, T.ObjectConstant1)); - CheckEqual( - T.Intersect( - T.Union(T.ObjectConstant2, T.ArrayConstant1), - T.Union(T.ObjectConstant1, T.ArrayConstant2)), - T.ArrayConstant1); + ZoneTests().Intersect(); + HeapTests().Intersect(); } -- 2.7.4