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.