Revert "Implement zone-allocated types"
authorrossberg@chromium.org <rossberg@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 10 Jan 2014 15:33:37 +0000 (15:33 +0000)
committerrossberg@chromium.org <rossberg@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Fri, 10 Jan 2014 15:33:37 +0000 (15:33 +0000)
This reverts commit 4308974b16d1ee67d9f64d797c5ea64ffaab51df.

TBR=machenbach@chromium.org
BUG=

Review URL: https://codereview.chromium.org/133353005

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18545 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/list-inl.h
src/objects.cc
src/objects.h
src/types.cc
src/types.h
test/cctest/test-types.cc

index 7799ca4ccfef44a6a30936ecaa502fd4d480b664..143c830ee92ad3d11fe62372dc2a6947557ef8c3 100644 (file)
@@ -166,7 +166,6 @@ void List<T, P>::Clear() {
 
 template<typename T, class P>
 void List<T, P>::Rewind(int pos) {
-  ASSERT(pos <= length_);
   length_ = pos;
 }
 
index 429676a6ca222ddf0c388c630d0ddf8e9d7ae97c..539d4afb01bac1da3bfd1487e9fe545503531852 100644 (file)
@@ -7857,14 +7857,6 @@ MaybeObject* PolymorphicCodeCacheHashTable::Put(MapHandleList* maps,
 }
 
 
-void FixedArray::Shrink(int new_length) {
-  ASSERT(new_length <= length());
-  if (new_length < length()) {
-    RightTrimFixedArray<FROM_MUTATOR>(GetHeap(), this, length() - new_length);
-  }
-}
-
-
 MaybeObject* FixedArray::AddKeysFromJSArray(JSArray* array) {
   ElementsAccessor* accessor = array->GetElementsAccessor();
   MaybeObject* maybe_result =
index 3488a3143830e828e18538c4864da30b011bf0b9..1dc54b206e39cc72cf133d4b006d65352f09098f 100644 (file)
@@ -2941,9 +2941,6 @@ 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,
index 9354965a7b7a57475a7568b08b2adaa9eee24411..2aa60817e5f4f30e221085507ef3ae497a846e8e 100644 (file)
@@ -38,7 +38,7 @@ int TypeImpl<Config>::NumClasses() {
   } else if (this->IsUnion()) {
     UnionedHandle unioned = this->AsUnion();
     int result = 0;
-    for (int i = 0; i < Config::union_length(unioned); ++i) {
+    for (int i = 0; i < unioned->length(); ++i) {
       if (Config::union_get(unioned, i)->IsClass()) ++result;
     }
     return result;
@@ -55,7 +55,7 @@ int TypeImpl<Config>::NumConstants() {
   } else if (this->IsUnion()) {
     UnionedHandle unioned = this->AsUnion();
     int result = 0;
-    for (int i = 0; i < Config::union_length(unioned); ++i) {
+    for (int i = 0; i < unioned->length(); ++i) {
       if (Config::union_get(unioned, i)->IsConstant()) ++result;
     }
     return result;
@@ -118,7 +118,7 @@ void TypeImpl<Config>::Iterator<T>::Advance() {
   ++index_;
   if (type_->IsUnion()) {
     UnionedHandle unioned = type_->AsUnion();
-    for (; index_ < Config::union_length(unioned); ++index_) {
+    for (; index_ < unioned->length(); ++index_) {
       if (matches(Config::union_get(unioned, index_))) return;
     }
   } else if (index_ == 0 && matches(type_)) {
@@ -136,7 +136,7 @@ int TypeImpl<Config>::LubBitset() {
   } else if (this->IsUnion()) {
     UnionedHandle unioned = this->AsUnion();
     int bitset = kNone;
-    for (int i = 0; i < Config::union_length(unioned); ++i) {
+    for (int i = 0; i < unioned->length(); ++i) {
       bitset |= Config::union_get(unioned, i)->LubBitset();
     }
     return bitset;
@@ -299,7 +299,7 @@ bool TypeImpl<Config>::SlowIs(TypeImpl* that) {
   // (T1 \/ ... \/ Tn) <= T  <=>  (T1 <= T) /\ ... /\ (Tn <= T)
   if (this->IsUnion()) {
     UnionedHandle unioned = this->AsUnion();
-    for (int i = 0; i < Config::union_length(unioned); ++i) {
+    for (int i = 0; i < unioned->length(); ++i) {
       TypeHandle this_i = Config::union_get(unioned, i);
       if (!this_i->Is(that)) return false;
     }
@@ -311,7 +311,7 @@ bool TypeImpl<Config>::SlowIs(TypeImpl* that) {
   ASSERT(!this->IsUnion());
   if (that->IsUnion()) {
     UnionedHandle unioned = that->AsUnion();
-    for (int i = 0; i < Config::union_length(unioned); ++i) {
+    for (int i = 0; i < unioned->length(); ++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<Config>::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 < Config::union_length(unioned); ++i) {
+    for (int i = 0; i < unioned->length(); ++i) {
       TypeHandle this_i = Config::union_get(unioned, i);
       if (this_i->Maybe(that)) return true;
     }
@@ -356,7 +356,7 @@ bool TypeImpl<Config>::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 < Config::union_length(unioned); ++i) {
+    for (int i = 0; i < unioned->length(); ++i) {
       TypeHandle that_i = Config::union_get(unioned, i);
       if (this->Maybe(that_i)) return true;
     }
@@ -389,21 +389,18 @@ bool TypeImpl<Config>::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<class Config>
-int TypeImpl<Config>::ExtendUnion(
-    UnionedHandle result, TypeHandle type, int current_size) {
+int TypeImpl<Config>::ExtendUnion(UnionedHandle result, int current_size) {
   int old_size = current_size;
-  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) {
+  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) {
       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)) {
-        Config::union_set(result, current_size++, type);
+        result->set(current_size++, *type);
       }
     }
   }
@@ -436,50 +433,51 @@ typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Union(
   // Slow case: may need to produce a Unioned object.
   int size = type1->IsBitset() || type2->IsBitset() ? 1 : 0;
   if (!type1->IsBitset()) {
-    size += (type1->IsUnion() ? Config::union_length(type1->AsUnion()) : 1);
+    size += (type1->IsUnion() ? type1->AsUnion()->length() : 1);
   }
   if (!type2->IsBitset()) {
-    size += (type2->IsUnion() ? Config::union_length(type2->AsUnion()) : 1);
+    size += (type2->IsUnion() ? type2->AsUnion()->length() : 1);
   }
   ASSERT(size >= 2);
   UnionedHandle unioned = Config::union_create(size, region);
   size = 0;
 
   int bitset = type1->GlbBitset() | type2->GlbBitset();
-  if (bitset != kNone) {
-    Config::union_set(unioned, size++, Config::from_bitset(bitset, region));
-  }
-  size = ExtendUnion(unioned, type1, size);
-  size = ExtendUnion(unioned, type2, size);
+  if (bitset != kNone) unioned->set(size++, Config::from_bitset(bitset));
+  size = type1->ExtendUnion(unioned, size);
+  size = type2->ExtendUnion(unioned, size);
 
   if (size == 1) {
     return Config::union_get(unioned, 0);
-  } else {
-    Config::union_shrink(unioned, size);
+  } else if (size == unioned->length()) {
     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 type which are also in other, store at unioned,
+// Get non-bitsets from this which are also in that, store at unioned,
 // starting at index. Returns updated index.
 template<class Config>
 int TypeImpl<Config>::ExtendIntersection(
-    UnionedHandle result, TypeHandle type, TypeHandle other, int current_size) {
+    UnionedHandle result, TypeHandle that, int current_size) {
   int old_size = current_size;
-  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) {
+  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) {
       TypeHandle type = Config::union_get(unioned, i);
       ASSERT(i == 0 ||
              !(type->IsBitset() || type->Is(Config::union_get(unioned, 0))));
-      if (!type->IsBitset() && type->Is(other) &&
+      if (!type->IsBitset() && type->Is(that) &&
           !type->InUnion(result, old_size)) {
-        Config::union_set(result, current_size++, type);
+        result->set(current_size++, *type);
       }
     }
   }
@@ -512,10 +510,10 @@ typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Intersect(
   // Slow case: may need to produce a Unioned object.
   int size = 0;
   if (!type1->IsBitset()) {
-    size = (type1->IsUnion() ? Config::union_length(type1->AsUnion()) : 2);
+    size = (type1->IsUnion() ? type1->AsUnion()->length() : 2);
   }
   if (!type2->IsBitset()) {
-    int size2 = (type2->IsUnion() ? Config::union_length(type2->AsUnion()) : 2);
+    int size2 = (type2->IsUnion() ? type2->AsUnion()->length() : 2);
     size = (size == 0 ? size2 : Min(size, size2));
   }
   ASSERT(size >= 2);
@@ -523,20 +521,22 @@ typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Intersect(
   size = 0;
 
   int bitset = type1->GlbBitset() & type2->GlbBitset();
-  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 (bitset != kNone) unioned->set(size++, Config::from_bitset(bitset));
+  size = type1->ExtendIntersection(unioned, type2, size);
+  size = type2->ExtendIntersection(unioned, type1, size);
 
   if (size == 0) {
     return None(region);
   } else if (size == 1) {
     return Config::union_get(unioned, 0);
-  } else {
-    Config::union_shrink(unioned, size);
+  } else if (size == unioned->length()) {
     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<Config>::TypePrint(FILE* out) {
   } else if (this->IsUnion()) {
     PrintF(out, "(");
     UnionedHandle unioned = this->AsUnion();
-    for (int i = 0; i < Config::union_length(unioned); ++i) {
+    for (int i = 0; i < unioned->length(); ++i) {
       TypeHandle type_i = Config::union_get(unioned, i);
       if (i > 0) PrintF(out, " | ");
       type_i->TypePrint(out);
@@ -612,10 +612,6 @@ void TypeImpl<Config>::TypePrint(FILE* out) {
 #endif
 
 
-template class TypeImpl<ZoneTypeConfig>;
-template class TypeImpl<ZoneTypeConfig>::Iterator<i::Map>;
-template class TypeImpl<ZoneTypeConfig>::Iterator<i::Object>;
-
 template class TypeImpl<HeapTypeConfig>;
 template class TypeImpl<HeapTypeConfig>::Iterator<i::Map>;
 template class TypeImpl<HeapTypeConfig>::Iterator<i::Object>;
index 7dcf6f6bdc0599b8590d7503bbdc5675e6a92bfc..4d8557e68b35696566e3efe19b293dbb9305767c 100644 (file)
@@ -137,24 +137,22 @@ namespace internal {
 //   typedef Region;
 //   template<class> struct Handle { typedef type; }  // No template typedefs...
 //   static Handle<Type>::type handle(Type* type);    // !is_bitset(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<i::Map> as_class(Type*);
-//   static i::Handle<i::Object> as_constant(Type*);
-//   static Handle<Unioned>::type as_union(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<i::Map> as_class(Type* type);
+//   static i::Handle<i::Object> as_constant(Type* type);
+//   static Handle<Unioned>::type as_union(Type* type);
 //   static Type* from_bitset(int bitset);
-//   static Handle<Type>::type from_bitset(int bitset, Region*);
-//   static Handle<Type>::type from_class(i::Handle<i::Map>, Region*)
-//   static Handle<Type>::type from_constant(i::Handle<i::Object>, Region*);
-//   static Handle<Type>::type from_union(Handle<Unioned>::type);
-//   static Handle<Unioned>::type union_create(int size, Region*);
-//   static void union_shrink(Handle<Unioned>::type, int size);
-//   static Handle<Type>::type union_get(Handle<Unioned>::type, int);
-//   static void union_set(Handle<Unioned>::type, int, Handle<Type>::type);
-//   static int union_length(Handle<Unioned>::type);
+//   static Handle<Type>::type from_bitset(int bitset, Region* region);
+//   static Handle<Type>::type from_class(i::Handle<i::Map> map, Region* region)
+//   static Handle<Type>::type from_constant(
+//                               i::Handle<i::Object> value, Region* region);
+//   static Handle<Type>::type from_union(Handle<Unioned>::T unioned);
+//   static Handle<Unioned>::type union_create(int size, Region* region);
+//   static Handle<Type>::type union_get(Handle<Unioned>::T unioned, int i);
 // }
 template<class Config>
 class TypeImpl : public Config::Base {
@@ -185,17 +183,14 @@ class TypeImpl : public Config::Base {
   }
 
   bool Is(TypeImpl* that) { return this == that || this->SlowIs(that); }
-  template<class TypeHandle>
   bool Is(TypeHandle that) { return this->Is(*that); }
   bool Maybe(TypeImpl* that);
-  template<class TypeHandle>
   bool Maybe(TypeHandle that) { return this->Maybe(*that); }
 
   // State-dependent versions of Of and Is that consider subtyping between
   // a constant and its map class.
   static TypeHandle OfCurrently(i::Handle<i::Object> value, Region* region);
   bool IsCurrently(TypeImpl* that);
-  template<class TypeHandle>
   bool IsCurrently(TypeHandle that)  { return this->IsCurrently(*that); }
 
   bool IsClass() { return Config::is_class(this); }
@@ -237,7 +232,7 @@ class TypeImpl : public Config::Base {
     return Iterator<i::Object>(Config::handle(this));
   }
 
-  static TypeImpl* cast(typename Config::Base* object) {
+  static TypeImpl* cast(i::Object* object) {
     TypeImpl* t = static_cast<TypeImpl*>(object);
     ASSERT(t->IsBitset() || t->IsClass() || t->IsConstant() || t->IsUnion());
     return t;
@@ -281,10 +276,9 @@ class TypeImpl : public Config::Base {
   static int LubBitset(i::Map* map);
 
   bool InUnion(UnionedHandle unioned, 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);
+  int ExtendUnion(UnionedHandle unioned, int current_size);
+  int ExtendIntersection(
+      UnionedHandle unioned, TypeHandle type, int current_size);
 
 #ifdef OBJECT_PRINT
   static const char* bitset_name(int bitset);
@@ -292,141 +286,6 @@ 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<void*> 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<void*>(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<Tag>(reinterpret_cast<intptr_t>(tagged->at(0)));
-  }
-  template<class T>
-  static T tagged_get(Tagged* tagged, int i) {
-    return reinterpret_cast<T>(tagged->at(i + 1));
-  }
-  template<class T>
-  static void tagged_set(Tagged* tagged, int i, T value) {
-    tagged->at(i + 1) = reinterpret_cast<T>(value);
-  }
-  static int tagged_length(Tagged* tagged) {
-    return tagged->length() - 1;
-  }
-
- public:
-  typedef TypeImpl<ZoneTypeConfig> Type;
-  class Base {};
-  typedef i::ZoneList<Type*> Unioned;
-  typedef i::Zone Region;
-  template<class T> 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<intptr_t>(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<intptr_t>(type) >> 1;
-  }
-  static Tagged* as_tagged(Type* type) {
-    ASSERT(is_tagged(type));
-    return reinterpret_cast<Tagged*>(type);
-  }
-  static i::Handle<i::Map> as_class(Type* type) {
-    ASSERT(is_class(type));
-    return i::Handle<i::Map>(tagged_get<i::Map**>(as_tagged(type), 0));
-  }
-  static i::Handle<i::Object> as_constant(Type* type) {
-    ASSERT(is_constant(type));
-    return i::Handle<i::Object>(tagged_get<i::Object**>(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<Unioned*>(tagged);
-  }
-
-  static Type* from_bitset(int bitset) {
-    return reinterpret_cast<Type*>((bitset << 1) | 1);
-  }
-  static Type* from_bitset(int bitset, Zone* Zone) {
-    return from_bitset(bitset);
-  }
-  static Type* from_tagged(Tagged* tagged) {
-    return reinterpret_cast<Type*>(tagged);
-  }
-  static Type* from_class(i::Handle<i::Map> 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<i::Object> 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<Tagged*>(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<Type*>(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<HeapTypeConfig> Type;
   typedef i::Object Base;
@@ -468,6 +327,8 @@ struct HeapTypeConfig {
   }
   static i::Handle<Type> from_constant(
       i::Handle<i::Object> value, Isolate* isolate) {
+    ASSERT(isolate || value->IsHeapObject());
+    if (!isolate) isolate = i::HeapObject::cast(*value)->GetIsolate();
     i::Handle<Box> box = isolate->factory()->NewBox(value);
     return i::Handle<Type>::cast(i::Handle<Object>::cast(box));
   }
@@ -478,25 +339,13 @@ struct HeapTypeConfig {
   static i::Handle<Unioned> union_create(int size, Isolate* isolate) {
     return isolate->factory()->NewFixedArray(size);
   }
-  static void union_shrink(i::Handle<Unioned> unioned, int size) {
-    unioned->Shrink(size);
-  }
   static i::Handle<Type> union_get(i::Handle<Unioned> unioned, int i) {
     Type* type = static_cast<Type*>(unioned->get(i));
     ASSERT(!is_union(type));
     return i::handle(type, unioned->GetIsolate());
   }
-  static void union_set(
-      i::Handle<Unioned> unioned, int i, i::Handle<Type> type) {
-    ASSERT(!is_union(*type));
-    unioned->set(i, *type);
-  }
-  static int union_length(i::Handle<Unioned> unioned) {
-    return unioned->length();
-  }
 };
 
-typedef TypeImpl<ZoneTypeConfig> ZoneType;
 typedef TypeImpl<HeapTypeConfig> Type;
 
 
@@ -550,7 +399,6 @@ struct BoundsImpl {
   }
 };
 
-typedef BoundsImpl<ZoneTypeConfig> ZoneBounds;
 typedef BoundsImpl<HeapTypeConfig> Bounds;
 
 
index 8b105dd530b9bac644d70482445aecef19f218cf..adcc156940734cd3ece867c762d4dc0fe343aaa4 100644 (file)
 
 using namespace v8::internal;
 
-template<class Type, class TypeHandle, class Region>
-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<i::Map> object_map;
-  Handle<i::Map> array_map;
-
-  Handle<i::Smi> smi;
-  Handle<i::HeapNumber> signed32;
-  Handle<i::JSObject> object1;
-  Handle<i::JSObject> object2;
-  Handle<i::JSArray> 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).
-struct ZoneRep {
-  static bool IsTagged(ZoneType* t, int tag) {
-    return !IsBitset(t)
-        && reinterpret_cast<intptr_t>(AsTagged(t)->at(0)) == tag;
-  }
-  static bool IsBitset(ZoneType* t) {
-    return reinterpret_cast<intptr_t>(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<void*>* AsTagged(ZoneType* t) {
-    return reinterpret_cast<ZoneList<void*>*>(t);
-  }
-  static int AsBitset(ZoneType* t) {
-    return reinterpret_cast<intptr_t>(t) >> 1;
+static bool IsBitset(Handle<Type> t) { return t->IsSmi(); }
+static bool IsClass(Handle<Type> t) { return t->IsMap(); }
+static bool IsConstant(Handle<Type> t) { return t->IsBox(); }
+static bool IsUnion(Handle<Type> t) { return t->IsFixedArray(); }
+
+static int AsBitset(Handle<Type> t) { return Smi::cast(*t)->value(); }
+static Map* AsClass(Handle<Type> t) { return Map::cast(*t); }
+static Object* AsConstant(Handle<Type> t) { return Box::cast(*t)->value(); }
+static FixedArray* AsUnion(Handle<Type> t) { return FixedArray::cast(*t); }
+
+
+static void CheckEqual(Handle<Type> type1, Handle<Type> 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());
   }
-  static Map* AsClass(ZoneType* t) {
-    return *reinterpret_cast<Map**>(AsTagged(t)->at(1));
-  }
-  static Object* AsConstant(ZoneType* t) {
-    return *reinterpret_cast<Object**>(AsTagged(t)->at(1));
-  }
-  static ZoneList<ZoneType*>* AsUnion(ZoneType* t) {
-    return reinterpret_cast<ZoneList<ZoneType*>*>(AsTagged(t));
-  }
-
-  static Zone* Region(Zone* zone, Isolate* isolate) { return zone; }
-};
-
-
-struct HeapRep {
-  static bool IsBitset(Handle<Type> t) { return t->IsSmi(); }
-  static bool IsClass(Handle<Type> t) { return t->IsMap(); }
-  static bool IsConstant(Handle<Type> t) { return t->IsBox(); }
-  static bool IsUnion(Handle<Type> t) { return t->IsFixedArray(); }
-
-  static int AsBitset(Handle<Type> t) { return Smi::cast(*t)->value(); }
-  static Map* AsClass(Handle<Type> t) { return Map::cast(*t); }
-  static Object* AsConstant(Handle<Type> t) { return Box::cast(*t)->value(); }
-  static FixedArray* AsUnion(Handle<Type> t) { return FixedArray::cast(*t); }
-
-  static Isolate* Region(Zone* zone, Isolate* isolate) { return isolate; }
-};
-
-
-template<class Type, class TypeHandle, class Region, class Rep>
-struct Tests : Rep {
-  Isolate* isolate;
-  HandleScope scope;
-  Zone zone;
-  Types<Type, TypeHandle, Region> T;
+  CHECK(type1->Is(type2));
+  CHECK(type2->Is(type1));
+}
 
-  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 CheckSub(Handle<Type> type1, Handle<Type> 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 CheckUnordered(Handle<Type> type1, Handle<Type> type2) {
+  CHECK(!type1->Is(type2));
+  CHECK(!type2->Is(type1));
+  if (IsBitset(type1) && IsBitset(type2)) {
+    CHECK_NE(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));
-    }
+static void CheckOverlap(Handle<Type> type1, Handle<Type> type2) {
+  CHECK(type1->Maybe(type2));
+  CHECK(type2->Maybe(type1));
+  if (IsBitset(type1) && IsBitset(type2)) {
+    CHECK_NE(0, AsBitset(type1) & AsBitset(type2));
   }
+}
 
-  void Bitset() {
-    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)));
+static void CheckDisjoint(Handle<Type> type1, Handle<Type> 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));
   }
+}
 
-  void Class() {
-    CHECK(IsClass(T.ObjectClass));
-    CHECK(IsClass(T.ArrayClass));
 
-    CHECK(*T.object_map == AsClass(T.ObjectClass));
-    CHECK(*T.array_map == AsClass(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);
   }
 
-  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<Type> None;
+  Handle<Type> Any;
+  Handle<Type> Oddball;
+  Handle<Type> Boolean;
+  Handle<Type> Null;
+  Handle<Type> Undefined;
+  Handle<Type> Number;
+  Handle<Type> Smi;
+  Handle<Type> Signed32;
+  Handle<Type> Double;
+  Handle<Type> Name;
+  Handle<Type> UniqueName;
+  Handle<Type> String;
+  Handle<Type> InternalizedString;
+  Handle<Type> Symbol;
+  Handle<Type> Receiver;
+  Handle<Type> Object;
+  Handle<Type> Array;
+  Handle<Type> Function;
+  Handle<Type> Proxy;
+
+  Handle<Type> ObjectClass;
+  Handle<Type> ArrayClass;
+
+  Handle<Type> SmiConstant;
+  Handle<Type> Signed32Constant;
+  Handle<Type> ObjectConstant1;
+  Handle<Type> ObjectConstant2;
+  Handle<Type> ArrayConstant1;
+  Handle<Type> ArrayConstant2;
+
+  Handle<Map> object_map;
+  Handle<Map> array_map;
 
-  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<i::Smi> smi;
+  Handle<HeapNumber> signed32;
+  Handle<JSObject> object1;
+  Handle<JSObject> object2;
+  Handle<JSArray> array;
 
-  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<Type> Union(Handle<Type> t1, Handle<Type> t2) {
+    return Type::Union(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));
+  Handle<Type> Intersect(Handle<Type> t1, Handle<Type> t2) {
+    return Type::Intersect(t1, t2, 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);
-  }
+ private:
+  Isolate* isolate_;
 };
 
-typedef Tests<ZoneType, ZoneType*, Zone, ZoneRep> ZoneTests;
-typedef Tests<Type, Handle<Type>, Isolate, HeapRep> HeapTests;
-
 
 TEST(Bitset) {
   CcTest::InitializeVM();
-  ZoneTests().Bitset();
-  HeapTests().Bitset();
+  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)));
 }
 
 
 TEST(Class) {
   CcTest::InitializeVM();
-  ZoneTests().Class();
-  HeapTests().Class();
+  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));
 }
 
 
 TEST(Constant) {
   CcTest::InitializeVM();
-  ZoneTests().Constant();
-  HeapTests().Constant();
+  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));
 }
 
 
 TEST(Is) {
   CcTest::InitializeVM();
-  ZoneTests().Is();
-  HeapTests().Is();
+  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);
 }
 
 
 TEST(Maybe) {
   CcTest::InitializeVM();
-  ZoneTests().Maybe();
-  HeapTests().Maybe();
+  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);
 }
 
 
 TEST(Union) {
   CcTest::InitializeVM();
-  ZoneTests().Union();
-  HeapTests().Union();
+  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));
 }
 
 
 TEST(Intersect) {
   CcTest::InitializeVM();
-  ZoneTests().Intersect();
-  HeapTests().Intersect();
+  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);
 }