Revision: 15224
Author:   [email protected]
Date:     Thu Jun 20 02:10:10 2013
Log:      Introduce Type::Intersect function

Also, fix bugs in Type::Union and Type::Maybe.

(This subsumes the in-flight fix for Union in https://codereview.chromium.org/16925008/, including test cases).

[email protected]
BUG=

Review URL: https://codereview.chromium.org/17335003
http://code.google.com/p/v8/source/detail?r=15224

Modified:
 /branches/bleeding_edge/src/types.cc
 /branches/bleeding_edge/src/types.h
 /branches/bleeding_edge/test/cctest/test-types.cc

=======================================
--- /branches/bleeding_edge/src/types.cc        Wed Jun 12 10:20:37 2013
+++ /branches/bleeding_edge/src/types.cc        Thu Jun 20 02:10:10 2013
@@ -243,6 +243,7 @@

   // T <= (T1 \/ ... \/ Tn)  <=>  (T <= T1) \/ ... \/ (T <= Tn)
   // (iff T is not a union)
+  ASSERT(!this->is_union());
   if (that->is_union()) {
     Handle<Unioned> unioned = that->as_union();
     for (int i = 0; i < unioned->length(); ++i) {
@@ -266,13 +267,6 @@
   if (that->is_bitset()) {
     return (this->LubBitset() & that->as_bitset()) != 0;
   }
-
-  if (this->is_class()) {
-    return that->is_class() && *this->as_class() == *that->as_class();
-  }
-  if (this->is_constant()) {
- return that->is_constant() && *this->as_constant() == *that->as_constant();
-  }

// (T1 \/ ... \/ Tn) overlaps T <=> (T1 overlaps T) \/ ... \/ (Tn overlaps T)
   if (this->is_union()) {
@@ -293,6 +287,14 @@
     }
     return false;
   }
+
+  ASSERT(!that->is_union());
+  if (this->is_class()) {
+    return that->is_class() && *this->as_class() == *that->as_class();
+  }
+  if (this->is_constant()) {
+ return that->is_constant() && *this->as_constant() == *that->as_constant();
+  }

   return false;
 }
@@ -302,12 +304,12 @@
   ASSERT(!this->is_union());
   for (int i = 0; i < current_size; ++i) {
     Handle<Type> type = union_get(unioned, i);
-    if (type->is_bitset() ? this->Is(type) : this == *type) return true;
+    if (this->Is(type)) return true;
   }
   return false;
 }

-// Get non-bitsets from this which are not subsumed by that, store at unioned, +// Get non-bitsets from this which are not subsumed by union, store at unioned,
 // starting at index. Returns updated index.
 int Type::ExtendUnion(Handle<Unioned> result, int current_size) {
   int old_size = current_size;
@@ -372,6 +374,79 @@
   for (int i = 0; i < size; ++i) result->set(i, unioned->get(i));
   return from_handle(result);
 }
+
+
+// Get non-bitsets from this which are also in that, store at unioned,
+// starting at index. Returns updated index.
+int Type::ExtendIntersection(
+    Handle<Unioned> result, Handle<Type> that, int current_size) {
+  int old_size = current_size;
+  if (this->is_class() || this->is_constant()) {
+    if (this->Is(that) && !this->InUnion(result, old_size))
+      result->set(current_size++, this);
+  } else if (this->is_union()) {
+    Handle<Unioned> unioned = this->as_union();
+    for (int i = 0; i < unioned->length(); ++i) {
+      Handle<Type> type = union_get(unioned, i);
+ ASSERT(i == 0 || !(type->is_bitset() || type->Is(union_get(unioned, 0))));
+      if (type->is_bitset()) continue;
+      if (type->Is(that) && !type->InUnion(result, old_size))
+        result->set(current_size++, *type);
+    }
+  }
+  return current_size;
+}
+
+
+// Intersection is O(1) on simple bit unions, but O(n*m) on structured unions.
+// TODO(rossberg): Should we use object sets somehow? Is it worth it?
+Type* Type::Intersect(Handle<Type> type1, Handle<Type> type2) {
+  // Fast case: bit sets.
+  if (type1->is_bitset() && type2->is_bitset()) {
+    return from_bitset(type1->as_bitset() & type2->as_bitset());
+  }
+
+  // Semi-fast case: Unioned objects are neither involved nor produced.
+  if (!(type1->is_union() || type2->is_union())) {
+    if (type1->Is(type2)) return *type1;
+    if (type2->Is(type1)) return *type2;
+  }
+
+  // Slow case: may need to produce a Unioned object.
+  Isolate* isolate = NULL;
+  int size = 0;
+  if (!type1->is_bitset()) {
+    isolate = HeapObject::cast(*type1)->GetIsolate();
+    size = (type1->is_union() ? type1->as_union()->length() : 2);
+  }
+  if (!type2->is_bitset()) {
+    isolate = HeapObject::cast(*type2)->GetIsolate();
+    int size2 = (type2->is_union() ? type2->as_union()->length() : 2);
+    size = (size == 0 ? size2 : Min(size, size2));
+  }
+  ASSERT(isolate != NULL);
+  ASSERT(size >= 2);
+  Handle<Unioned> unioned = isolate->factory()->NewFixedArray(size);
+  size = 0;
+
+  int bitset = type1->GlbBitset() & type2->GlbBitset();
+  if (bitset != kNone) unioned->set(size++, from_bitset(bitset));
+  size = type1->ExtendIntersection(unioned, type2, size);
+  size = type2->ExtendIntersection(unioned, type1, size);
+
+  if (size == 0) {
+    return None();
+  } else if (size == 1) {
+    return *union_get(unioned, 0);
+  } else if (size == unioned->length()) {
+    return from_handle(unioned);
+  }
+
+  // There were dropped cases. Copy to smaller union.
+  Handle<Unioned> result = isolate->factory()->NewFixedArray(size);
+  for (int i = 0; i < size; ++i) result->set(i, unioned->get(i));
+  return from_handle(result);
+}


 Type* Type::Optional(Handle<Type> type) {
=======================================
--- /branches/bleeding_edge/src/types.h Wed Jun 12 10:20:37 2013
+++ /branches/bleeding_edge/src/types.h Thu Jun 20 02:10:10 2013
@@ -86,6 +86,7 @@
 // Internally, all 'primitive' types, and their unions, are represented as
 // bitsets via smis. Class is a heap pointer to the respective map. Only
// Constant's, or unions containing Class'es or Constant's, require allocation. +// Note that the bitset representation is closed under both Union and Intersect.
 //
// The type representation is heap-allocated, so cannot (currently) be used in
 // a parallel compilation context.
@@ -129,6 +130,7 @@
   }

   static Type* Union(Handle<Type> type1, Handle<Type> type2);
+  static Type* Intersect(Handle<Type> type1, Handle<Type> type2);
   static Type* Optional(Handle<Type> type);  // type \/ Undefined

   bool Is(Type* that);
@@ -248,6 +250,8 @@
   int GlbBitset();  // greatest lower bound that's a bitset
   bool InUnion(Handle<Unioned> unioned, int current_size);
   int ExtendUnion(Handle<Unioned> unioned, int current_size);
+  int ExtendIntersection(
+      Handle<Unioned> unioned, Handle<Type> type, int current_size);
 };

 } }  // namespace v8::internal
=======================================
--- /branches/bleeding_edge/test/cctest/test-types.cc Wed Jun 12 10:20:37 2013 +++ /branches/bleeding_edge/test/cctest/test-types.cc Thu Jun 20 02:10:10 2013
@@ -40,6 +40,62 @@
 static Map* AsClass(Type* type) { return Map::cast(type); }
 static Object* AsConstant(Type* type) { return Box::cast(type)->value(); }
 static FixedArray* AsUnion(Type* type) { return FixedArray::cast(type); }
+
+
+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());
+  }
+  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 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(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));
+  }
+}
+
+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));
+  }
+}
+

 class HandlifiedTypes {
  public:
@@ -76,7 +132,8 @@
     Integer31Constant = handle(Type::Constant(smi, isolate), isolate);
     ObjectConstant1 = handle(Type::Constant(object1), isolate);
     ObjectConstant2 = handle(Type::Constant(object2), isolate);
-    ArrayConstant = handle(Type::Constant(array), isolate);
+    ArrayConstant1 = handle(Type::Constant(array), isolate);
+    ArrayConstant2 = handle(Type::Constant(array), isolate);
   }

   Handle<Type> None;
@@ -106,7 +163,8 @@
   Handle<Type> Integer31Constant;
   Handle<Type> ObjectConstant1;
   Handle<Type> ObjectConstant2;
-  Handle<Type> ArrayConstant;
+  Handle<Type> ArrayConstant1;
+  Handle<Type> ArrayConstant2;

   Handle<Map> object_map;
   Handle<Map> array_map;
@@ -119,6 +177,9 @@
   Handle<Type> Union(Handle<Type> type1, Handle<Type> type2) {
     return handle(Type::Union(type1, type2), isolate_);
   }
+  Handle<Type> Intersect(Handle<Type> type1, Handle<Type> type2) {
+    return handle(Type::Intersect(type1, type2), isolate_);
+  }

  private:
   Isolate* isolate_;
@@ -173,32 +234,18 @@
   CHECK(IsConstant(*T.Integer31Constant));
   CHECK(IsConstant(*T.ObjectConstant1));
   CHECK(IsConstant(*T.ObjectConstant2));
-  CHECK(IsConstant(*T.ArrayConstant));
+  CHECK(IsConstant(*T.ArrayConstant1));
+  CHECK(IsConstant(*T.ArrayConstant2));

   CHECK(*T.smi == AsConstant(*T.Integer31Constant));
   CHECK(*T.object1 == AsConstant(*T.ObjectConstant1));
   CHECK(*T.object2 == AsConstant(*T.ObjectConstant2));
   CHECK(*T.object1 != AsConstant(*T.ObjectConstant2));
-  CHECK(*T.array == AsConstant(*T.ArrayConstant));
+  CHECK(*T.array == AsConstant(*T.ArrayConstant1));
+  CHECK(*T.array == AsConstant(*T.ArrayConstant2));
 }


-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 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));
-  }
-}
-
 TEST(Is) {
   CcTest::InitializeVM();
   Isolate* isolate = Isolate::Current();
@@ -212,6 +259,7 @@

   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);
@@ -265,36 +313,18 @@
   CheckSub(T.Integer31Constant, T.Number);
   CheckSub(T.ObjectConstant1, T.Object);
   CheckSub(T.ObjectConstant2, T.Object);
-  CheckSub(T.ArrayConstant, T.Object);
-  CheckSub(T.ArrayConstant, T.Array);
+  CheckSub(T.ArrayConstant1, T.Object);
+  CheckSub(T.ArrayConstant1, T.Array);
   CheckUnordered(T.ObjectConstant1, T.ObjectConstant2);
-  CheckUnordered(T.ObjectConstant1, T.ArrayConstant);
+  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.ArrayConstant, T.ObjectClass);
-}
-
-
-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));
-  }
+  CheckUnordered(T.ArrayConstant1, T.ObjectClass);
 }

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

 TEST(Maybe) {
   CcTest::InitializeVM();
@@ -352,37 +382,20 @@
   CheckDisjoint(T.Integer31Constant, T.Double);
   CheckOverlap(T.ObjectConstant1, T.Object);
   CheckOverlap(T.ObjectConstant2, T.Object);
-  CheckOverlap(T.ArrayConstant, T.Object);
-  CheckOverlap(T.ArrayConstant, T.Array);
+  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.ArrayConstant);
+  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.ArrayConstant, T.ObjectClass);
+  CheckDisjoint(T.ArrayConstant1, T.ObjectClass);
 }

-
-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));
-  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());
-  }
-  CHECK(type1->Is(type2));
-  CHECK(type2->Is(type1));
-}

 TEST(Union) {
   CcTest::InitializeVM();
@@ -414,17 +427,22 @@

   // Constant-constant
   CHECK(IsConstant(Type::Union(T.ObjectConstant1, T.ObjectConstant1)));
+  CHECK(IsConstant(Type::Union(T.ArrayConstant1, T.ArrayConstant1)));
   CHECK(IsUnion(Type::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.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.ArrayConstant), T.Array);
-  CheckOverlap(T.Union(T.ObjectConstant1, T.ArrayConstant), T.Array);
-  CheckDisjoint(T.Union(T.ObjectConstant1, T.ArrayConstant), T.Number);
- CheckDisjoint(T.Union(T.ObjectConstant1, T.ArrayConstant), 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(Type::Union(T.ObjectClass, T.Object)));
@@ -463,7 +481,7 @@
   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.ArrayConstant); + 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);

@@ -512,30 +530,177 @@
   CHECK(IsUnion(Type::Union(
       T.ObjectConstant1, T.Union(T.ObjectConstant1, T.ObjectConstant2))));
   CHECK(IsUnion(Type::Union(
-      T.Union(T.ArrayConstant, T.ObjectClass), T.ObjectConstant1)));
+      T.Union(T.ArrayConstant1, T.ObjectClass), T.ObjectConstant1)));
   CHECK(IsUnion(Type::Union(
-      T.Union(T.ArrayConstant, T.ObjectConstant2), T.ObjectConstant1)));
+      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.ArrayConstant, T.ObjectConstant2), T.ObjectConstant1), - T.Union(T.ObjectConstant2, T.Union(T.ArrayConstant, T.ObjectConstant1))); + T.Union(T.Union(T.ArrayConstant1, T.ObjectConstant2), T.ObjectConstant1), + T.Union(T.ObjectConstant2, T.Union(T.ArrayConstant1, T.ObjectConstant1)));

   // Union-union
   CHECK(IsBitset(Type::Union(
       T.Union(T.Number, T.ArrayClass), T.Union(T.Integer32, T.Array))));
+  CHECK(IsUnion(Type::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.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.ArrayConstant),
-              T.Union(T.ObjectConstant1, T.ArrayConstant)),
- T.Union(T.Union(T.ObjectConstant1, T.ObjectConstant2), T.ArrayConstant));
+      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.Integer31, T.Array)),
       T.Union(T.Number, T.Array));
 }
+
+
+TEST(Intersect) {
+  CcTest::InitializeVM();
+  Isolate* isolate = Isolate::Current();
+  HandleScope scope(isolate);
+  HandlifiedTypes T(isolate);
+
+  // Bitset-bitset
+  CHECK(IsBitset(Type::Intersect(T.Object, T.Number)));
+  CHECK(IsBitset(Type::Intersect(T.Object, T.Object)));
+  CHECK(IsBitset(Type::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(Type::Intersect(T.ObjectClass, T.ObjectClass)));
+  CHECK(IsBitset(Type::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(Type::Intersect(T.ObjectConstant1, T.ObjectConstant1)));
+  CHECK(IsConstant(Type::Intersect(T.ArrayConstant1, T.ArrayConstant2)));
+  CHECK(IsBitset(Type::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(Type::Intersect(T.ObjectClass, T.Object)));
+  CHECK(IsBitset(Type::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(Type::Intersect(T.Integer31, T.Number)));
+  CHECK(IsConstant(Type::Intersect(T.Integer31Constant, T.Number)));
+  CHECK(IsConstant(Type::Intersect(T.ObjectConstant1, T.Object)));
+
+  CheckEqual(T.Intersect(T.Integer31, T.Number), T.Integer31);
+ CheckEqual(T.Intersect(T.Integer31Constant, T.Number), T.Integer31Constant);
+  CheckEqual(T.Intersect(T.ObjectConstant1, T.Object), T.ObjectConstant1);
+
+  // Class-constant
+  CHECK(IsBitset(Type::Intersect(T.ObjectConstant1, T.ObjectClass)));
+  CHECK(IsBitset(Type::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(
+ Type::Intersect(T.Object, T.Union(T.ObjectConstant1, T.ObjectClass))));
+  CHECK(IsBitset(
+ Type::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(
+ Type::Intersect(T.Union(T.ArrayClass, T.ObjectConstant2), T.ArrayClass)));
+  CHECK(IsClass(
+ Type::Intersect(T.Union(T.Object, T.Integer31Constant), T.ArrayClass)));
+  CHECK(IsBitset(
+ Type::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.Integer31Constant)),
+      T.ArrayClass);
+  CheckEqual(
+      T.Intersect(T.Union(T.ObjectClass, T.ArrayConstant1), T.ArrayClass),
+      T.None);
+
+  // Constant-union
+  CHECK(IsConstant(Type::Intersect(
+      T.ObjectConstant1, T.Union(T.ObjectConstant1, T.ObjectConstant2))));
+  CHECK(IsConstant(Type::Intersect(
+      T.Union(T.Number, T.ObjectClass), T.Integer31Constant)));
+  CHECK(IsBitset(Type::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.Integer31Constant, T.Union(T.Number, T.ObjectConstant2)),
+      T.Integer31Constant);
+  CheckEqual(
+ T.Intersect(T.Union(T.ArrayConstant1, T.ObjectClass), T.ObjectConstant1),
+      T.None);
+
+  // Union-union
+  CHECK(IsUnion(Type::Intersect(
+      T.Union(T.Number, T.ArrayClass), T.Union(T.Integer32, T.Array))));
+  CHECK(IsBitset(Type::Intersect(
+      T.Union(T.Number, T.ObjectClass), T.Union(T.Integer32, T.Array))));
+
+  CheckEqual(
+      T.Intersect(
+          T.Union(T.Number, T.ArrayClass),
+          T.Union(T.Integer31, T.Array)),
+      T.Union(T.Integer31, T.ArrayClass));
+  CheckEqual(
+      T.Intersect(
+          T.Union(T.Number, T.ObjectClass),
+          T.Union(T.Integer32, T.Array)),
+      T.Integer32);
+  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);
+}

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to