Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(663)

Unified Diff: src/types.cc

Issue 17335003: Introduce Type::Intersect function (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Tweak comment Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/types.h ('k') | test/cctest/test-types.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/types.cc
diff --git a/src/types.cc b/src/types.cc
index 20e8a4c994541fc18f10e3cdbece64843645acd8..22a108b7206b0bd657ae57e90af4c20a11770190 100644
--- a/src/types.cc
+++ b/src/types.cc
@@ -243,6 +243,7 @@ bool Type::Is(Type* that) {
// 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) {
@@ -267,13 +268,6 @@ bool Type::Maybe(Type* that) {
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()) {
Handle<Unioned> unioned = this->as_union();
@@ -294,6 +288,14 @@ bool Type::Maybe(Type* that) {
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 @@ bool Type::InUnion(Handle<Unioned> unioned, int current_size) {
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;
@@ -374,6 +376,79 @@ Type* Type::Union(Handle<Type> type1, Handle<Type> type2) {
}
+// 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) {
return type->is_bitset()
? from_bitset(type->as_bitset() | kUndefined)
« no previous file with comments | « src/types.h ('k') | test/cctest/test-types.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698