Implement structural function and array types
authorrossberg@chromium.org <rossberg@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 16 Apr 2014 13:44:26 +0000 (13:44 +0000)
committerrossberg@chromium.org <rossberg@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 16 Apr 2014 13:44:26 +0000 (13:44 +0000)
Just wanted to add two constructors to a datatype, how ugly can it get?

R=bmeurer@chromium.org, jarin@chromium.org
BUG=

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

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

15 files changed:
src/accessors.cc
src/arm/stub-cache-arm.cc
src/arm64/stub-cache-arm64.cc
src/hydrogen.cc
src/hydrogen.h
src/ia32/stub-cache-ia32.cc
src/ic.cc
src/objects-debug.cc
src/objects-inl.h
src/stub-cache.cc
src/types-inl.h
src/types.cc
src/types.h
src/x64/stub-cache-x64.cc
test/cctest/test-types.cc

index e11738cc392b998a4323965ccc1484b6083fc2cc..cfac1c8f9cef877356510673ea1bffbe97b43c3a 100644 (file)
@@ -126,7 +126,7 @@ bool Accessors::IsJSObjectFieldAccessor(typename T::TypeHandle type,
   }
 
   if (!type->IsClass()) return false;
-  Handle<Map> map = type->AsClass();
+  Handle<Map> map = type->AsClass()->Map();
 
   switch (map->instance_type()) {
     case JS_ARRAY_TYPE:
index ebbfce683c3dfecdbad1317d2f69bcd7daafdfa8..6875dcf5ab14de0c3ee2ce2a04f229cebc1e57b7 100644 (file)
@@ -432,7 +432,7 @@ void StoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm,
   } else if (representation.IsHeapObject()) {
     HeapType* field_type = descriptors->GetFieldType(descriptor);
     if (field_type->IsClass()) {
-      __ CheckMap(value_reg, scratch1, field_type->AsClass(),
+      __ CheckMap(value_reg, scratch1, field_type->AsClass()->Map(),
                   miss_label, DO_SMI_CHECK);
     } else {
       ASSERT(HeapType::Any()->Is(field_type));
@@ -601,7 +601,7 @@ void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
   } else if (representation.IsHeapObject()) {
     HeapType* field_type = lookup->GetFieldType();
     if (field_type->IsClass()) {
-      __ CheckMap(value_reg, scratch1, field_type->AsClass(),
+      __ CheckMap(value_reg, scratch1, field_type->AsClass()->Map(),
                   miss_label, DO_SMI_CHECK);
     } else {
       ASSERT(HeapType::Any()->Is(field_type));
@@ -850,7 +850,9 @@ Register StubCompiler::CheckPrototypes(Handle<HeapType> type,
   int depth = 0;
 
   Handle<JSObject> current = Handle<JSObject>::null();
-  if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant());
+  if (type->IsConstant()) {
+    current = Handle<JSObject>::cast(type->AsConstant()->Value());
+  }
   Handle<JSObject> prototype = Handle<JSObject>::null();
   Handle<Map> current_map = receiver_map;
   Handle<Map> holder_map(holder->map());
index e5383f166dbe21ff085ce286e3c69c8461851974..bf128409816b211b4385890089030c69e6dae2bc 100644 (file)
@@ -394,7 +394,7 @@ void StoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm,
   } else if (representation.IsHeapObject()) {
     HeapType* field_type = descriptors->GetFieldType(descriptor);
     if (field_type->IsClass()) {
-      __ CheckMap(value_reg, scratch1, field_type->AsClass(),
+      __ CheckMap(value_reg, scratch1, field_type->AsClass()->Map(),
                   miss_label, DO_SMI_CHECK);
     } else {
       ASSERT(HeapType::Any()->Is(field_type));
@@ -550,7 +550,7 @@ void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
   } else if (representation.IsHeapObject()) {
     HeapType* field_type = lookup->GetFieldType();
     if (field_type->IsClass()) {
-      __ CheckMap(value_reg, scratch1, field_type->AsClass(),
+      __ CheckMap(value_reg, scratch1, field_type->AsClass()->Map(),
                   miss_label, DO_SMI_CHECK);
     } else {
       ASSERT(HeapType::Any()->Is(field_type));
@@ -802,7 +802,7 @@ Register StubCompiler::CheckPrototypes(Handle<HeapType> type,
 
   Handle<JSObject> current = Handle<JSObject>::null();
   if (type->IsConstant()) {
-    current = Handle<JSObject>::cast(type->AsConstant());
+    current = Handle<JSObject>::cast(type->AsConstant()->Value());
   }
   Handle<JSObject> prototype = Handle<JSObject>::null();
   Handle<Map> current_map = receiver_map;
index 7a9dc90cc43e18d317324fcab7a35600edc2c77a..833dc5186a0908be197f8c1d57d839f2bde71281 100644 (file)
@@ -4926,7 +4926,7 @@ void HOptimizedGraphBuilder::VisitVariableProxy(VariableProxy* expr) {
         Handle<PropertyCell> cell(global->GetPropertyCell(&lookup));
         if (cell->type()->IsConstant()) {
           PropertyCell::AddDependentCompilationInfo(cell, top_info());
-          Handle<Object> constant_object = cell->type()->AsConstant();
+          Handle<Object> constant_object = cell->type()->AsConstant()->Value();
           if (constant_object->IsConsString()) {
             constant_object =
                 String::Flatten(Handle<String>::cast(constant_object));
@@ -4999,7 +4999,7 @@ void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) {
 static bool CanInlinePropertyAccess(Type* type) {
   if (type->Is(Type::NumberOrString())) return true;
   if (!type->IsClass()) return false;
-  Handle<Map> map = type->AsClass();
+  Handle<Map> map = type->AsClass()->Map();
   return map->IsJSObjectMap() &&
       !map->is_dictionary_map() &&
       !map->has_named_interceptor();
@@ -5991,7 +5991,7 @@ void HOptimizedGraphBuilder::HandleGlobalVariableAssignment(
     Handle<GlobalObject> global(current_info()->global_object());
     Handle<PropertyCell> cell(global->GetPropertyCell(&lookup));
     if (cell->type()->IsConstant()) {
-      Handle<Object> constant = cell->type()->AsConstant();
+      Handle<Object> constant = cell->type()->AsConstant()->Value();
       if (value->IsConstant()) {
         HConstant* c_value = HConstant::cast(value);
         if (!constant.is_identical_to(c_value->handle(isolate()))) {
@@ -9943,7 +9943,7 @@ HControlInstruction* HOptimizedGraphBuilder::BuildCompareInstruction(
       HValue* operand_to_check =
           left->block()->block_id() < right->block()->block_id() ? left : right;
       if (combined_type->IsClass()) {
-        Handle<Map> map = combined_type->AsClass();
+        Handle<Map> map = combined_type->AsClass()->Map();
         AddCheckMap(operand_to_check, map);
         HCompareObjectEqAndBranch* result =
             New<HCompareObjectEqAndBranch>(left, right);
index b7915e695cafe1fd5b44f1e7955c7e5193b9e057..c561ab11943a0f924108e369b2f26d8b7e05fd4f 100644 (file)
@@ -2380,7 +2380,7 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
         context = context->native_context();
         return handle(context->string_function()->initial_map());
       } else {
-        return type_->AsClass();
+        return type_->AsClass()->Map();
       }
     }
     Type* type() const { return type_; }
index 209bfa6d815d2461dc776f16c9f624b8245f6a79..9c8269259fb42f5dc20a9dd21c76d1ded64785ab 100644 (file)
@@ -530,7 +530,8 @@ void StoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm,
   } else if (representation.IsHeapObject()) {
     HeapType* field_type = descriptors->GetFieldType(descriptor);
     if (field_type->IsClass()) {
-      __ CheckMap(value_reg, field_type->AsClass(), miss_label, DO_SMI_CHECK);
+      __ CheckMap(value_reg, field_type->AsClass()->Map(),
+                  miss_label, DO_SMI_CHECK);
     } else {
       ASSERT(HeapType::Any()->Is(field_type));
       __ JumpIfSmi(value_reg, miss_label);
@@ -706,7 +707,8 @@ void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
   } else if (representation.IsHeapObject()) {
     HeapType* field_type = lookup->GetFieldType();
     if (field_type->IsClass()) {
-      __ CheckMap(value_reg, field_type->AsClass(), miss_label, DO_SMI_CHECK);
+      __ CheckMap(value_reg, field_type->AsClass()->Map(),
+                  miss_label, DO_SMI_CHECK);
     } else {
       ASSERT(HeapType::Any()->Is(field_type));
       __ JumpIfSmi(value_reg, miss_label);
@@ -836,7 +838,8 @@ Register StubCompiler::CheckPrototypes(Handle<HeapType> type,
   int depth = 0;
 
   Handle<JSObject> current = Handle<JSObject>::null();
-  if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant());
+  if (type->IsConstant()) current =
+      Handle<JSObject>::cast(type->AsConstant()->Value());
   Handle<JSObject> prototype = Handle<JSObject>::null();
   Handle<Map> current_map = receiver_map;
   Handle<Map> holder_map(holder->map());
index ecf0e9a8d68eca7fb8e611118f2aefc7f58eeeed..86bef05e221120a5de4bc06d9c0dffd2990de96e 100644 (file)
--- a/src/ic.cc
+++ b/src/ic.cc
@@ -680,7 +680,8 @@ bool IC::UpdatePolymorphicIC(Handle<HeapType> type,
 
   for (int i = 0; i < number_of_types; i++) {
     Handle<HeapType> current_type = types.at(i);
-    if (current_type->IsClass() && current_type->AsClass()->is_deprecated()) {
+    if (current_type->IsClass() &&
+        current_type->AsClass()->Map()->is_deprecated()) {
       // Filter out deprecated maps to ensure their instances get migrated.
       ++deprecated_types;
     } else if (type->NowIs(current_type)) {
@@ -691,8 +692,8 @@ bool IC::UpdatePolymorphicIC(Handle<HeapType> type,
     } else if (handler_to_overwrite == -1 &&
                current_type->IsClass() &&
                type->IsClass() &&
-               IsTransitionOfMonomorphicTarget(*current_type->AsClass(),
-                                               *type->AsClass())) {
+               IsTransitionOfMonomorphicTarget(*current_type->AsClass()->Map(),
+                                               *type->AsClass()->Map())) {
       handler_to_overwrite = i;
     }
   }
@@ -734,10 +735,11 @@ Handle<Map> IC::TypeToMap(HeapType* type, Isolate* isolate) {
     return isolate->factory()->heap_number_map();
   if (type->Is(HeapType::Boolean())) return isolate->factory()->boolean_map();
   if (type->IsConstant()) {
-    return handle(Handle<JSGlobalObject>::cast(type->AsConstant())->map());
+    return handle(
+        Handle<JSGlobalObject>::cast(type->AsConstant()->Value())->map());
   }
   ASSERT(type->IsClass());
-  return type->AsClass();
+  return type->AsClass()->Map();
 }
 
 
index 2ff70586ea1076fed934ac97bea3de9285765813..40132cbf6b050f5da85ce18b2dcf02184f512615 100644 (file)
@@ -301,7 +301,7 @@ void JSObject::JSObjectVerify() {
         if (r.IsHeapObject()) ASSERT(value->IsHeapObject());
         HeapType* field_type = descriptors->GetFieldType(i);
         if (field_type->IsClass()) {
-          Map* map = *field_type->AsClass();
+          Map* map = *field_type->AsClass()->Map();
           CHECK(!map->is_stable() || HeapObject::cast(value)->map() == map);
         } else if (r.IsNone()) {
           CHECK(field_type->Is(HeapType::None()));
index 96433eae3adab80fe318cfc91c78c407ddcde75b..023caa5ddf93f7a2fdf595121a0581553a23440f 100644 (file)
@@ -87,13 +87,6 @@ PropertyDetails PropertyDetails::AsDeleted() const {
   }
 
 
-#define FIXED_TYPED_ARRAY_CAST_ACCESSOR(type)   \
-  template<>                                    \
-  type* type::cast(Object* object) {            \
-    SLOW_ASSERT(object->Is##type());            \
-    return reinterpret_cast<type*>(object);     \
-  }
-
 #define INT_ACCESSORS(holder, name, offset)                             \
   int holder::name() { return READ_INT_FIELD(this, offset); }           \
   void holder::set_##name(int value) { WRITE_INT_FIELD(this, offset, value); }
index e7bf0692272ed40cf7645cb9d6c403b5d5da1d39..91d31ea3077b3feba48290ea5de6e1b470fff1b7 100644 (file)
@@ -901,7 +901,7 @@ void LoadStubCompiler::NonexistentHandlerFrontend(Handle<HeapType> type,
   // check that the global property cell is empty.
   if (last_map->IsJSGlobalObjectMap()) {
     Handle<JSGlobalObject> global = last.is_null()
-        ? Handle<JSGlobalObject>::cast(type->AsConstant())
+        ? Handle<JSGlobalObject>::cast(type->AsConstant()->Value())
         : Handle<JSGlobalObject>::cast(last);
     GenerateCheckPropertyCell(masm(), global, name, scratch2(), &miss);
   }
index ad1107b68cb0c3421c19f8343745268b3ff842d8..96ec3b97a02580add006cd0565726db8b1fa52df 100644 (file)
 namespace v8 {
 namespace internal {
 
+// -------------------------------------------------------------------------- //
+// TypeImpl
+
+template<class Config>
+TypeImpl<Config>::Iterator<i::Map> TypeImpl<Config>::Classes() {
+  if (this->IsBitset()) return Iterator<i::Map>();
+  return Iterator<i::Map>(Config::handle(this));
+}
+
+
+template<class Config>
+TypeImpl<Config>::Iterator<i::Object> TypeImpl<Config>::Constants() {
+  if (this->IsBitset()) return Iterator<i::Object>();
+  return Iterator<i::Object>(Config::handle(this));
+}
+
+
+template<class Config>
+TypeImpl<Config>* TypeImpl<Config>::cast(typename Config::Base* object) {
+  TypeImpl* t = static_cast<TypeImpl*>(object);
+  ASSERT(t->IsBitset() || t->IsClass() || t->IsConstant() ||
+         t->IsUnion() || t->IsArray() || t->IsFunction());
+  return t;
+}
+
+
 template<class Config>
 bool TypeImpl<Config>::NowContains(i::Object* value) {
   DisallowHeapAllocation no_allocation;
@@ -27,12 +53,23 @@ bool TypeImpl<Config>::NowContains(i::Object* value) {
 }
 
 
+// -------------------------------------------------------------------------- //
+// ZoneTypeConfig
+
 // static
-Type* ZoneTypeConfig::handle(Type* type) {
+template<class T>
+T* ZoneTypeConfig::handle(T* type) {
   return type;
 }
 
 
+// static
+template<class T>
+T* ZoneTypeConfig::cast(Type* type) {
+  return static_cast<T*>(type);
+}
+
+
 // static
 bool ZoneTypeConfig::is_bitset(Type* type) {
   return reinterpret_cast<intptr_t>(type) & 1;
@@ -40,20 +77,20 @@ bool ZoneTypeConfig::is_bitset(Type* type) {
 
 
 // static
-bool ZoneTypeConfig::is_struct(Type* type) {
-  return !is_bitset(type);
+bool ZoneTypeConfig::is_struct(Type* type, int tag) {
+  return !is_bitset(type) && struct_tag(as_struct(type)) == tag;
 }
 
 
 // static
 bool ZoneTypeConfig::is_class(Type* type) {
-  return is_struct(type) && struct_tag(as_struct(type)) == Type::kClassTag;
+  return is_struct(type, Type::StructuralType::kClassTag);
 }
 
 
 // static
 bool ZoneTypeConfig::is_constant(Type* type) {
-  return is_struct(type) && struct_tag(as_struct(type)) == Type::kConstantTag;
+  return is_struct(type, Type::StructuralType::kConstantTag);
 }
 
 
@@ -66,7 +103,7 @@ int ZoneTypeConfig::as_bitset(Type* type) {
 
 // static
 ZoneTypeConfig::Struct* ZoneTypeConfig::as_struct(Type* type) {
-  ASSERT(is_struct(type));
+  ASSERT(!is_bitset(type));
   return reinterpret_cast<Struct*>(type);
 }
 
@@ -107,7 +144,7 @@ ZoneTypeConfig::Type* ZoneTypeConfig::from_struct(Struct* structured) {
 // static
 ZoneTypeConfig::Type* ZoneTypeConfig::from_class(
     i::Handle<i::Map> map, int lub, Zone* zone) {
-  Struct* structured = struct_create(Type::kClassTag, 2, zone);
+  Struct* structured = struct_create(Type::StructuralType::kClassTag, 2, zone);
   structured[2] = from_bitset(lub);
   structured[3] = map.location();
   return from_struct(structured);
@@ -117,7 +154,8 @@ ZoneTypeConfig::Type* ZoneTypeConfig::from_class(
 // static
 ZoneTypeConfig::Type* ZoneTypeConfig::from_constant(
     i::Handle<i::Object> value, int lub, Zone* zone) {
-  Struct* structured = struct_create(Type::kConstantTag, 2, zone);
+  Struct* structured =
+      struct_create(Type::StructuralType::kConstantTag, 2, zone);
   structured[2] = from_bitset(lub);
   structured[3] = value.location();
   return from_struct(structured);
@@ -174,14 +212,24 @@ int ZoneTypeConfig::lub_bitset(Type* type) {
   return as_bitset(struct_get(as_struct(type), 0));
 }
 
+
 // -------------------------------------------------------------------------- //
+// HeapTypeConfig
 
 // static
-i::Handle<HeapTypeConfig::Type> HeapTypeConfig::handle(Type* type) {
+template<class T>
+i::Handle<T> HeapTypeConfig::handle(T* type) {
   return i::handle(type, i::HeapObject::cast(type)->GetIsolate());
 }
 
 
+// static
+template<class T>
+i::Handle<T> HeapTypeConfig::cast(i::Handle<Type> type) {
+  return i::Handle<T>::cast(type);
+}
+
+
 // static
 bool HeapTypeConfig::is_bitset(Type* type) {
   return type->IsSmi();
@@ -201,14 +249,14 @@ bool HeapTypeConfig::is_constant(Type* type) {
 
 
 // static
-bool HeapTypeConfig::is_struct(Type* type) {
-  return type->IsFixedArray();
+bool HeapTypeConfig::is_struct(Type* type, int tag) {
+  return type->IsFixedArray() && struct_tag(as_struct(type)) == tag;
 }
 
 
 // static
 int HeapTypeConfig::as_bitset(Type* type) {
-  return Smi::cast(type)->value();
+  return i::Smi::cast(type)->value();
 }
 
 
index 4ddc14bb32f3410812f6d533477fb3fb462bb790..0e016e4fe10185fd7f8235a7195666c4529c9975 100644 (file)
@@ -15,10 +15,10 @@ int TypeImpl<Config>::NumClasses() {
   if (this->IsClass()) {
     return 1;
   } else if (this->IsUnion()) {
-    StructHandle unioned = this->AsUnion();
+    UnionHandle unioned = handle(this->AsUnion());
     int result = 0;
-    for (int i = 0; i < Config::struct_length(unioned); ++i) {
-      if (Config::struct_get(unioned, i)->IsClass()) ++result;
+    for (int i = 0; i < unioned->Length(); ++i) {
+      if (unioned->Get(i)->IsClass()) ++result;
     }
     return result;
   } else {
@@ -32,10 +32,10 @@ int TypeImpl<Config>::NumConstants() {
   if (this->IsConstant()) {
     return 1;
   } else if (this->IsUnion()) {
-    StructHandle unioned = this->AsUnion();
+    UnionHandle unioned = handle(this->AsUnion());
     int result = 0;
-    for (int i = 0; i < Config::struct_length(unioned); ++i) {
-      if (Config::struct_get(unioned, i)->IsConstant()) ++result;
+    for (int i = 0; i < unioned->Length(); ++i) {
+      if (unioned->Get(i)->IsConstant()) ++result;
     }
     return result;
   } else {
@@ -48,8 +48,7 @@ template<class Config> template<class T>
 typename TypeImpl<Config>::TypeHandle
 TypeImpl<Config>::Iterator<T>::get_type() {
   ASSERT(!Done());
-  return type_->IsUnion()
-      ? Config::struct_get(type_->AsUnion(), index_) : type_;
+  return type_->IsUnion() ? type_->AsUnion()->Get(index_) : type_;
 }
 
 
@@ -67,7 +66,7 @@ struct TypeImplIteratorAux<Config, i::Map> {
     return type->IsClass();
   }
   static i::Handle<i::Map> current(typename TypeImpl<Config>::TypeHandle type) {
-    return type->AsClass();
+    return type->AsClass()->Map();
   }
 };
 
@@ -78,7 +77,7 @@ struct TypeImplIteratorAux<Config, i::Object> {
   }
   static i::Handle<i::Object> current(
       typename TypeImpl<Config>::TypeHandle type) {
-    return type->AsConstant();
+    return type->AsConstant()->Value();
   }
 };
 
@@ -97,9 +96,9 @@ template<class Config> template<class T>
 void TypeImpl<Config>::Iterator<T>::Advance() {
   ++index_;
   if (type_->IsUnion()) {
-    StructHandle unioned = type_->AsUnion();
-    for (; index_ < Config::struct_length(unioned); ++index_) {
-      if (matches(Config::struct_get(unioned, index_))) return;
+    UnionHandle unioned = handle(type_->AsUnion());
+    for (; index_ < unioned->Length(); ++index_) {
+      if (matches(unioned->Get(index_))) return;
     }
   } else if (index_ == 0 && matches(type_)) {
     return;
@@ -108,30 +107,51 @@ void TypeImpl<Config>::Iterator<T>::Advance() {
 }
 
 
+// Get the largest bitset subsumed by this type.
+template<class Config>
+int TypeImpl<Config>::BitsetType::Glb(TypeImpl* type) {
+  if (type->IsBitset()) {
+    return type->AsBitset();
+  } else if (type->IsUnion()) {
+    // All but the first are non-bitsets and thus would yield kNone anyway.
+    return type->AsUnion()->Get(0)->BitsetGlb();
+  } else {
+    return kNone;
+  }
+}
+
+
 // Get the smallest bitset subsuming this type.
 template<class Config>
-int TypeImpl<Config>::LubBitset() {
-  if (this->IsBitset()) {
-    return this->AsBitset();
-  } else if (this->IsUnion()) {
-    StructHandle unioned = this->AsUnion();
+int TypeImpl<Config>::BitsetType::Lub(TypeImpl* type) {
+  if (type->IsBitset()) {
+    return type->AsBitset();
+  } else if (type->IsUnion()) {
+    UnionHandle unioned = handle(type->AsUnion());
     int bitset = kNone;
-    for (int i = 0; i < Config::struct_length(unioned); ++i) {
-      bitset |= Config::struct_get(unioned, i)->LubBitset();
+    for (int i = 0; i < unioned->Length(); ++i) {
+      bitset |= unioned->Get(i)->BitsetLub();
     }
     return bitset;
-  } else if (this->IsClass()) {
-    int bitset = Config::lub_bitset(this);
-    return bitset ? bitset : LubBitset(*this->AsClass());
+  } else if (type->IsClass()) {
+    int bitset = Config::lub_bitset(type);
+    return bitset ? bitset : Lub(*type->AsClass()->Map());
+  } else if (type->IsConstant()) {
+    int bitset = Config::lub_bitset(type);
+    return bitset ? bitset : Lub(*type->AsConstant()->Value());
+  } else if (type->IsArray()) {
+    return kArray;
+  } else if (type->IsFunction()) {
+    return kFunction;
   } else {
-    int bitset = Config::lub_bitset(this);
-    return bitset ? bitset : LubBitset(*this->AsConstant());
+    UNREACHABLE();
+    return kNone;
   }
 }
 
 
 template<class Config>
-int TypeImpl<Config>::LubBitset(i::Object* value) {
+int TypeImpl<Config>::BitsetType::Lub(i::Object* value) {
   if (value->IsSmi()) return kSignedSmall & kTaggedInt;
   i::Map* map = i::HeapObject::cast(value)->map();
   if (map->instance_type() == HEAP_NUMBER_TYPE) {
@@ -141,12 +161,12 @@ int TypeImpl<Config>::LubBitset(i::Object* value) {
         value->ToInt32(&i) ? (Smi::IsValid(i) ? kSignedSmall : kOtherSigned32) :
         value->ToUint32(&u) ? kUnsigned32 : kFloat);
   }
-  return LubBitset(map);
+  return Lub(map);
 }
 
 
 template<class Config>
-int TypeImpl<Config>::LubBitset(i::Map* map) {
+int TypeImpl<Config>::BitsetType::Lub(i::Map* map) {
   switch (map->instance_type()) {
     case STRING_TYPE:
     case ASCII_STRING_TYPE:
@@ -235,20 +255,6 @@ int TypeImpl<Config>::LubBitset(i::Map* map) {
 }
 
 
-// Get the largest bitset subsumed by this type.
-template<class Config>
-int TypeImpl<Config>::GlbBitset() {
-  if (this->IsBitset()) {
-    return this->AsBitset();
-  } else if (this->IsUnion()) {
-    // All but the first are non-bitsets and thus would yield kNone anyway.
-    return Config::struct_get(this->AsUnion(), 0)->GlbBitset();
-  } else {
-    return kNone;
-  }
-}
-
-
 // Most precise _current_ type of a value (usually its class).
 template<class Config>
 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::NowOf(
@@ -267,22 +273,43 @@ bool TypeImpl<Config>::SlowIs(TypeImpl* that) {
   // Fast path for bitsets.
   if (this->IsNone()) return true;
   if (that->IsBitset()) {
-    return (this->LubBitset() | that->AsBitset()) == that->AsBitset();
+    return (BitsetType::Lub(this) | that->AsBitset()) == that->AsBitset();
   }
 
   if (that->IsClass()) {
-    return this->IsClass() && *this->AsClass() == *that->AsClass();
+    return this->IsClass()
+        && *this->AsClass()->Map() == *that->AsClass()->Map();
   }
   if (that->IsConstant()) {
-    return this->IsConstant() && *this->AsConstant() == *that->AsConstant();
+    return this->IsConstant()
+        && *this->AsConstant()->Value() == *that->AsConstant()->Value();
+  }
+  if (that->IsArray()) {
+    return this->IsArray()
+        && this->AsArray()->Element()->Equals(that->AsArray()->Element());
+  }
+  if (that->IsFunction()) {
+    // We currently do not allow for any variance here, in order to keep
+    // Union and Intersect operations simple.
+    if (!this->IsFunction()) return false;
+    FunctionType* this_fun = this->AsFunction();
+    FunctionType* that_fun = that->AsFunction();
+    if (this_fun->Arity() != that_fun->Arity() ||
+        !this_fun->Result()->Equals(that_fun->Result()) ||
+        !that_fun->Receiver()->Equals(this_fun->Receiver())) {
+      return false;
+    }
+    for (int i = 0; i < this_fun->Arity(); ++i) {
+      if (!that_fun->Parameter(i)->Equals(this_fun->Parameter(i))) return false;
+    }
+    return true;
   }
 
   // (T1 \/ ... \/ Tn) <= T  <=>  (T1 <= T) /\ ... /\ (Tn <= T)
   if (this->IsUnion()) {
-    StructHandle unioned = this->AsUnion();
-    for (int i = 0; i < Config::struct_length(unioned); ++i) {
-      TypeHandle this_i = Config::struct_get(unioned, i);
-      if (!this_i->Is(that)) return false;
+    UnionHandle unioned = handle(this->AsUnion());
+    for (int i = 0; i < unioned->Length(); ++i) {
+      if (!unioned->Get(i)->Is(that)) return false;
     }
     return true;
   }
@@ -291,10 +318,9 @@ bool TypeImpl<Config>::SlowIs(TypeImpl* that) {
   // (iff T is not a union)
   ASSERT(!this->IsUnion());
   if (that->IsUnion()) {
-    StructHandle unioned = that->AsUnion();
-    for (int i = 0; i < Config::struct_length(unioned); ++i) {
-      TypeHandle that_i = Config::struct_get(unioned, i);
-      if (this->Is(that_i)) return true;
+    UnionHandle unioned = handle(that->AsUnion());
+    for (int i = 0; i < unioned->Length(); ++i) {
+      if (this->Is(unioned->Get(i))) return true;
       if (this->IsBitset()) break;  // Fast fail, only first field is a bitset.
     }
     return false;
@@ -311,7 +337,7 @@ bool TypeImpl<Config>::NowIs(TypeImpl* that) {
   // but fuzzing does not cover that!
   DisallowHeapAllocation no_allocation;
   if (this->IsConstant()) {
-    i::Object* object = *this->AsConstant();
+    i::Object* object = *this->AsConstant()->Value();
     if (object->IsHeapObject()) {
       i::Map* map = i::HeapObject::cast(object)->map();
       for (Iterator<i::Map> it = that->Classes(); !it.Done(); it.Advance()) {
@@ -328,37 +354,44 @@ template<class Config>
 bool TypeImpl<Config>::Maybe(TypeImpl* that) {
   // (T1 \/ ... \/ Tn) overlaps T <=> (T1 overlaps T) \/ ... \/ (Tn overlaps T)
   if (this->IsUnion()) {
-    StructHandle unioned = this->AsUnion();
-    for (int i = 0; i < Config::struct_length(unioned); ++i) {
-      TypeHandle this_i = Config::struct_get(unioned, i);
-      if (this_i->Maybe(that)) return true;
+    UnionHandle unioned = handle(this->AsUnion());
+    for (int i = 0; i < unioned->Length(); ++i) {
+      if (unioned->Get(i)->Maybe(that)) return true;
     }
     return false;
   }
 
   // T overlaps (T1 \/ ... \/ Tn) <=> (T overlaps T1) \/ ... \/ (T overlaps Tn)
   if (that->IsUnion()) {
-    StructHandle unioned = that->AsUnion();
-    for (int i = 0; i < Config::struct_length(unioned); ++i) {
-      TypeHandle that_i = Config::struct_get(unioned, i);
-      if (this->Maybe(that_i)) return true;
+    UnionHandle unioned = handle(that->AsUnion());
+    for (int i = 0; i < unioned->Length(); ++i) {
+      if (this->Maybe(unioned->Get(i))) return true;
     }
     return false;
   }
 
   ASSERT(!this->IsUnion() && !that->IsUnion());
   if (this->IsBitset()) {
-    return IsInhabited(this->AsBitset() & that->LubBitset());
+    return BitsetType::IsInhabited(this->AsBitset() & that->BitsetLub());
   }
   if (that->IsBitset()) {
-    return IsInhabited(this->LubBitset() & that->AsBitset());
+    return BitsetType::IsInhabited(this->BitsetLub() & that->AsBitset());
   }
-
   if (this->IsClass()) {
-    return that->IsClass() && *this->AsClass() == *that->AsClass();
+    return that->IsClass()
+        && *this->AsClass()->Map() == *that->AsClass()->Map();
   }
   if (this->IsConstant()) {
-    return that->IsConstant() && *this->AsConstant() == *that->AsConstant();
+    return that->IsConstant()
+        && *this->AsConstant()->Value() == *that->AsConstant()->Value();
+  }
+  if (this->IsArray()) {
+    // There is no variance!
+    return this->Equals(that);
+  }
+  if (this->IsFunction()) {
+    // There is no variance!
+    return this->Equals(that);
   }
 
   return false;
@@ -370,16 +403,15 @@ bool TypeImpl<Config>::Contains(i::Object* value) {
   for (Iterator<i::Object> it = this->Constants(); !it.Done(); it.Advance()) {
     if (*it.Current() == value) return true;
   }
-  return Config::from_bitset(LubBitset(value))->Is(this);
+  return BitsetType::New(BitsetType::Lub(value))->Is(this);
 }
 
 
 template<class Config>
-bool TypeImpl<Config>::InUnion(StructHandle unioned, int current_size) {
+bool TypeImpl<Config>::InUnion(UnionHandle unioned, int current_size) {
   ASSERT(!this->IsUnion());
   for (int i = 0; i < current_size; ++i) {
-    TypeHandle type = Config::struct_get(unioned, i);
-    if (this->Is(type)) return true;
+    if (this->Is(unioned->Get(i))) return true;
   }
   return false;
 }
@@ -389,22 +421,24 @@ bool TypeImpl<Config>::InUnion(StructHandle unioned, int current_size) {
 // starting at index. Returns updated index.
 template<class Config>
 int TypeImpl<Config>::ExtendUnion(
-    StructHandle result, TypeHandle type, int current_size) {
+    UnionHandle result, TypeHandle type, int current_size) {
   int old_size = current_size;
-  if (type->IsClass() || type->IsConstant()) {
-    if (!type->InUnion(result, old_size)) {
-      Config::struct_set(result, current_size++, type);
-    }
-  } else if (type->IsUnion()) {
-    StructHandle unioned = type->AsUnion();
-    for (int i = 0; i < Config::struct_length(unioned); ++i) {
-      TypeHandle type = Config::struct_get(unioned, i);
-      ASSERT(i == 0 ||
-             !(type->IsBitset() || type->Is(Config::struct_get(unioned, 0))));
+  if (type->IsUnion()) {
+    UnionHandle unioned = handle(type->AsUnion());
+    for (int i = 0; i < unioned->Length(); ++i) {
+      TypeHandle type = unioned->Get(i);
+      ASSERT(i == 0 || !(type->IsBitset() || type->Is(unioned->Get(0))));
       if (!type->IsBitset() && !type->InUnion(result, old_size)) {
-        Config::struct_set(result, current_size++, type);
+        result->Set(current_size++, type);
       }
     }
+  } else if (!type->IsBitset()) {
+    // For all structural types, subtyping implies equivalence.
+    ASSERT(type->IsClass() || type->IsConstant() ||
+           type->IsArray() || type->IsFunction());
+    if (!type->InUnion(result, old_size)) {
+      result->Set(current_size++, type);
+    }
   }
   return current_size;
 }
@@ -416,7 +450,7 @@ typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Union(
     TypeHandle type1, TypeHandle type2, Region* region) {
   // Fast case: bit sets.
   if (type1->IsBitset() && type2->IsBitset()) {
-    return Config::from_bitset(type1->AsBitset() | type2->AsBitset(), region);
+    return BitsetType::New(type1->AsBitset() | type2->AsBitset(), region);
   }
 
   // Fast case: top or bottom types.
@@ -432,28 +466,28 @@ typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Union(
   // Slow case: may need to produce a Unioned object.
   int size = 0;
   if (!type1->IsBitset()) {
-    size += (type1->IsUnion() ? Config::struct_length(type1->AsUnion()) : 1);
+    size += (type1->IsUnion() ? type1->AsUnion()->Length() : 1);
   }
   if (!type2->IsBitset()) {
-    size += (type2->IsUnion() ? Config::struct_length(type2->AsUnion()) : 1);
+    size += (type2->IsUnion() ? type2->AsUnion()->Length() : 1);
   }
-  int bitset = type1->GlbBitset() | type2->GlbBitset();
-  if (bitset != kNone) ++size;
+  int bitset = type1->BitsetGlb() | type2->BitsetGlb();
+  if (bitset != BitsetType::kNone) ++size;
   ASSERT(size >= 1);
-  StructHandle unioned = Config::struct_create(kUnionTag, size, region);
 
+  UnionHandle unioned = UnionType::New(size, region);
   size = 0;
-  if (bitset != kNone) {
-    Config::struct_set(unioned, size++, Config::from_bitset(bitset, region));
+  if (bitset != BitsetType::kNone) {
+    unioned->Set(size++, BitsetType::New(bitset, region));
   }
   size = ExtendUnion(unioned, type1, size);
   size = ExtendUnion(unioned, type2, size);
 
   if (size == 1) {
-    return Config::struct_get(unioned, 0);
+    return unioned->Get(0);
   } else {
-    Config::struct_shrink(unioned, size);
-    return Config::from_struct(unioned);
+    unioned->Shrink(size);
+    return unioned;
   }
 }
 
@@ -462,36 +496,37 @@ typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Union(
 // starting at index. Returns updated index.
 template<class Config>
 int TypeImpl<Config>::ExtendIntersection(
-    StructHandle result, TypeHandle type, TypeHandle other, int current_size) {
+    UnionHandle result, TypeHandle type, TypeHandle other, int current_size) {
   int old_size = current_size;
-  if (type->IsClass() || type->IsConstant()) {
-    if (type->Is(other) && !type->InUnion(result, old_size)) {
-      Config::struct_set(result, current_size++, type);
-    }
-  } else if (type->IsUnion()) {
-    StructHandle unioned = type->AsUnion();
-    for (int i = 0; i < Config::struct_length(unioned); ++i) {
-      TypeHandle type = Config::struct_get(unioned, i);
-      ASSERT(i == 0 ||
-             !(type->IsBitset() || type->Is(Config::struct_get(unioned, 0))));
+  if (type->IsUnion()) {
+    UnionHandle unioned = handle(type->AsUnion());
+    for (int i = 0; i < unioned->Length(); ++i) {
+      TypeHandle type = unioned->Get(i);
+      ASSERT(i == 0 || !(type->IsBitset() || type->Is(unioned->Get(0))));
       if (!type->IsBitset() && type->Is(other) &&
           !type->InUnion(result, old_size)) {
-        Config::struct_set(result, current_size++, type);
+        result->Set(current_size++, type);
       }
     }
+  } else if (!type->IsBitset()) {
+    // For all structural types, subtyping implies equivalence.
+    ASSERT(type->IsClass() || type->IsConstant() ||
+           type->IsArray() || type->IsFunction());
+    if (type->Is(other) && !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?
 template<class Config>
 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Intersect(
     TypeHandle type1, TypeHandle type2, Region* region) {
   // Fast case: bit sets.
   if (type1->IsBitset() && type2->IsBitset()) {
-    return Config::from_bitset(type1->AsBitset() & type2->AsBitset(), region);
+    return BitsetType::New(type1->AsBitset() & type2->AsBitset(), region);
   }
 
   // Fast case: top or bottom types.
@@ -507,19 +542,19 @@ 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::struct_length(type1->AsUnion()) : 1);
+    size += (type1->IsUnion() ? type1->AsUnion()->Length() : 1);
   }
   if (!type2->IsBitset()) {
-    size += (type2->IsUnion() ? Config::struct_length(type2->AsUnion()) : 1);
+    size += (type2->IsUnion() ? type2->AsUnion()->Length() : 1);
   }
-  int bitset = type1->GlbBitset() & type2->GlbBitset();
-  if (bitset != kNone) ++size;
+  int bitset = type1->BitsetGlb() & type2->BitsetGlb();
+  if (bitset != BitsetType::kNone) ++size;
   ASSERT(size >= 1);
-  StructHandle unioned = Config::struct_create(kUnionTag, size, region);
 
+  UnionHandle unioned = UnionType::New(size, region);
   size = 0;
-  if (bitset != kNone) {
-    Config::struct_set(unioned, size++, Config::from_bitset(bitset, region));
+  if (bitset != BitsetType::kNone) {
+    unioned->Set(size++, BitsetType::New(bitset, region));
   }
   size = ExtendIntersection(unioned, type1, type2, size);
   size = ExtendIntersection(unioned, type2, type1, size);
@@ -527,10 +562,10 @@ typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Intersect(
   if (size == 0) {
     return None(region);
   } else if (size == 1) {
-    return Config::struct_get(unioned, 0);
+    return unioned->Get(0);
   } else {
-    Config::struct_shrink(unioned, size);
-    return Config::from_struct(unioned);
+    unioned->Shrink(size);
+    return unioned;
   }
 }
 
@@ -540,21 +575,34 @@ template<class OtherType>
 typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Convert(
     typename OtherType::TypeHandle type, Region* region) {
   if (type->IsBitset()) {
-    return Config::from_bitset(type->AsBitset(), region);
+    return BitsetType::New(type->AsBitset(), region);
   } else if (type->IsClass()) {
-    return Config::from_class(type->AsClass(), type->LubBitset(), region);
+    return ClassType::New(type->AsClass()->Map(), region);
   } else if (type->IsConstant()) {
-    return Config::from_constant(type->AsConstant(), type->LubBitset(), region);
-  } else {
-    ASSERT(type->IsUnion());
-    typename OtherType::StructHandle unioned = type->AsUnion();
-    int length = OtherType::StructLength(unioned);
-    StructHandle new_unioned = Config::struct_create(kUnionTag, length, region);
+    return ConstantType::New(type->AsConstant()->Value(), region);
+  } else if (type->IsUnion()) {
+    int length = type->AsUnion()->Length();
+    UnionHandle unioned = UnionType::New(length, region);
     for (int i = 0; i < length; ++i) {
-      Config::struct_set(new_unioned, i,
-          Convert<OtherType>(OtherType::StructGet(unioned, i), region));
+      unioned->Set(i, Convert<OtherType>(type->AsUnion()->Get(i), region));
+    }
+    return unioned;
+  } else if (type->IsArray()) {
+    return ArrayType::New(
+        Convert<OtherType>(type->AsArray()->Element(), region), region);
+  } else if (type->IsFunction()) {
+    FunctionHandle function = FunctionType::New(
+        Convert<OtherType>(type->AsFunction()->Result(), region),
+        Convert<OtherType>(type->AsFunction()->Receiver(), region),
+        type->AsFunction()->Arity(), region);
+    for (int i = 0; i < function->Arity(); ++i) {
+      function->InitParameter(i,
+          Convert<OtherType>(type->AsFunction()->Parameter(i), region));
     }
-    return Config::from_struct(new_unioned);
+    return function;
+  } else {
+    UNREACHABLE();
+    return None(region);
   }
 }
 
@@ -578,7 +626,7 @@ void TypeImpl<Config>::TypePrint(PrintDimension dim) {
 
 
 template<class Config>
-const char* TypeImpl<Config>::bitset_name(int bitset) {
+const char* TypeImpl<Config>::BitsetType::Name(int bitset) {
   switch (bitset) {
     case kAny & kRepresentation: return "Any";
     #define PRINT_COMPOSED_TYPE(type, value) \
@@ -598,8 +646,8 @@ const char* TypeImpl<Config>::bitset_name(int bitset) {
 
 
 template<class Config>
-void TypeImpl<Config>::BitsetTypePrint(FILE* out, int bitset) {
-  const char* name = bitset_name(bitset);
+void TypeImpl<Config>::BitsetType::BitsetTypePrint(FILE* out, int bitset) {
+  const char* name = Name(bitset);
   if (name != NULL) {
     PrintF(out, "%s", name);
   } else {
@@ -620,7 +668,7 @@ void TypeImpl<Config>::BitsetTypePrint(FILE* out, int bitset) {
       if ((bitset & subset) == subset) {
         if (!is_first) PrintF(out, " | ");
         is_first = false;
-        PrintF(out, "%s", bitset_name(subset));
+        PrintF(out, "%s", Name(subset));
         bitset -= subset;
       }
     }
@@ -636,34 +684,53 @@ void TypeImpl<Config>::TypePrint(FILE* out, PrintDimension dim) {
     int bitset = this->AsBitset();
     switch (dim) {
       case BOTH_DIMS:
-        BitsetTypePrint(out, bitset & kSemantic);
+        BitsetType::BitsetTypePrint(out, bitset & BitsetType::kSemantic);
         PrintF(out, "/");
-        BitsetTypePrint(out, bitset & kRepresentation);
+        BitsetType::BitsetTypePrint(out, bitset & BitsetType::kRepresentation);
         break;
       case SEMANTIC_DIM:
-        BitsetTypePrint(out, bitset & kSemantic);
+        BitsetType::BitsetTypePrint(out, bitset & BitsetType::kSemantic);
         break;
       case REPRESENTATION_DIM:
-        BitsetTypePrint(out, bitset & kRepresentation);
+        BitsetType::BitsetTypePrint(out, bitset & BitsetType::kRepresentation);
         break;
     }
   } else if (this->IsConstant()) {
-    PrintF(out, "Constant(%p : ", static_cast<void*>(*this->AsConstant()));
-    Config::from_bitset(this->LubBitset())->TypePrint(out, dim);
+    PrintF(out, "Constant(%p : ",
+        static_cast<void*>(*this->AsConstant()->Value()));
+    BitsetType::New(BitsetType::Lub(this))->TypePrint(out, dim);
     PrintF(out, ")");
   } else if (this->IsClass()) {
-    PrintF(out, "Class(%p < ", static_cast<void*>(*this->AsClass()));
-    Config::from_bitset(this->LubBitset())->TypePrint(out, dim);
+    PrintF(out, "Class(%p < ", static_cast<void*>(*this->AsClass()->Map()));
+    BitsetType::New(BitsetType::Lub(this))->TypePrint(out, dim);
     PrintF(out, ")");
   } else if (this->IsUnion()) {
     PrintF(out, "(");
-    StructHandle unioned = this->AsUnion();
-    for (int i = 0; i < Config::struct_length(unioned); ++i) {
-      TypeHandle type_i = Config::struct_get(unioned, i);
+    UnionHandle unioned = handle(this->AsUnion());
+    for (int i = 0; i < unioned->Length(); ++i) {
+      TypeHandle type_i = unioned->Get(i);
       if (i > 0) PrintF(out, " | ");
       type_i->TypePrint(out, dim);
     }
     PrintF(out, ")");
+  } else if (this->IsArray()) {
+    PrintF(out, "[");
+    AsArray()->Element()->TypePrint(out, dim);
+    PrintF(out, "]");
+  } else if (this->IsFunction()) {
+    if (!this->AsFunction()->Receiver()->IsAny()) {
+      this->AsFunction()->Receiver()->TypePrint(out, dim);
+      PrintF(out, ".");
+    }
+    PrintF(out, "(");
+    for (int i = 0; i < this->AsFunction()->Arity(); ++i) {
+      if (i > 0) PrintF(out, ", ");
+      this->AsFunction()->Parameter(i)->TypePrint(out, dim);
+    }
+    PrintF(out, ")->");
+    this->AsFunction()->Result()->TypePrint(out, dim);
+  } else {
+    UNREACHABLE();
   }
 }
 
index 3a3bc3bd08ba392790fff82d2e5cb5192fa233c8..363d45f410039b1af48e8e6ebc2ebe3fc5947d07 100644 (file)
@@ -43,7 +43,11 @@ namespace internal {
 //
 //   Class(map) < T   iff instance_type(map) < T
 //   Constant(x) < T  iff instance_type(map(x)) < T
+//   Array(T) < Array
+//   Function(R, S, T0, T1, ...) < Function
 //
+// Both structural Array and Function types are invariant in all parameters.
+// Relaxing this would make Union and Intersect operations more involved.
 // Note that Constant(x) < Class(map(x)) does _not_ hold, since x's map can
 // change! (Its instance type cannot, however.)
 // TODO(rossberg): the latter is not currently true for proxies, because of fix,
@@ -92,7 +96,7 @@ namespace internal {
 // lattice. That is intentional. It should always be possible to refine the
 // lattice (e.g., splitting up number types further) without invalidating any
 // existing assumptions or tests.
-// Consequently, do not use pointer equality for type tests, always use Is!
+// Consequently, do not normally use Equals for type tests, always use Is!
 //
 // The NowIs operator implements state-sensitive subtying, as described above.
 // Any compilation decision based on such temporary properties requires runtime
@@ -189,15 +193,17 @@ namespace internal {
 
 
 // struct Config {
+//   typedef TypeImpl<Config> Type;
 //   typedef Base;
 //   typedef Struct;
 //   typedef Region;
 //   template<class> struct Handle { typedef type; }  // No template typedefs...
-//   static Handle<Type>::type handle(Type* type);    // !is_bitset(type)
+//   template<class T> static Handle<T>::type handle(T* t);  // !is_bitset(t)
+//   template<class T> static Handle<T>::type cast(Handle<Type>::type);
 //   static bool is_bitset(Type*);
 //   static bool is_class(Type*);
 //   static bool is_constant(Type*);
-//   static bool is_struct(Type*);
+//   static bool is_struct(Type*, int tag);
 //   static int as_bitset(Type*);
 //   static i::Handle<i::Map> as_class(Type*);
 //   static i::Handle<i::Object> as_constant(Type*);
@@ -206,7 +212,7 @@ namespace internal {
 //   static Handle<Type>::type from_bitset(int bitset, Region*);
 //   static Handle<Type>::type from_class(i::Handle<Map>, int lub, Region*);
 //   static Handle<Type>::type from_constant(i::Handle<Object>, int, Region*);
-//   static Handle<Type>::type from_struct(Handle<Struct>::type);
+//   static Handle<Type>::type from_struct(Handle<Struct>::type, int tag);
 //   static Handle<Struct>::type struct_create(int tag, int length, Region*);
 //   static void struct_shrink(Handle<Struct>::type, int length);
 //   static int struct_tag(Handle<Struct>::type);
@@ -218,36 +224,73 @@ namespace internal {
 template<class Config>
 class TypeImpl : public Config::Base {
  public:
+  class BitsetType;      // Internal
+  class StructuralType;  // Internal
+  class UnionType;       // Internal
+
+  class ClassType;
+  class ConstantType;
+  class ArrayType;
+  class FunctionType;
+
   typedef typename Config::template Handle<TypeImpl>::type TypeHandle;
+  typedef typename Config::template Handle<ClassType>::type ClassHandle;
+  typedef typename Config::template Handle<ConstantType>::type ConstantHandle;
+  typedef typename Config::template Handle<ArrayType>::type ArrayHandle;
+  typedef typename Config::template Handle<FunctionType>::type FunctionHandle;
+  typedef typename Config::template Handle<UnionType>::type UnionHandle;
   typedef typename Config::Region Region;
 
-  #define DEFINE_TYPE_CONSTRUCTOR(type, value)                        \
-    static TypeImpl* type() { return Config::from_bitset(k##type); }  \
-    static TypeHandle type(Region* region) {                          \
-      return Config::from_bitset(k##type, region);                    \
+  #define DEFINE_TYPE_CONSTRUCTOR(type, value)                                \
+    static TypeImpl* type() { return BitsetType::New(BitsetType::k##type); }  \
+    static TypeHandle type(Region* region) {                                  \
+      return BitsetType::New(BitsetType::k##type, region);                    \
     }
   BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR)
   #undef DEFINE_TYPE_CONSTRUCTOR
 
   static TypeHandle Class(i::Handle<i::Map> map, Region* region) {
-    return Config::from_class(map, LubBitset(*map), region);
+    return ClassType::New(map, region);
   }
   static TypeHandle Constant(i::Handle<i::Object> value, Region* region) {
-    return Config::from_constant(value, LubBitset(*value), region);
+    return ConstantType::New(value, region);
+  }
+  static TypeHandle Array(TypeHandle element, Region* region) {
+    return ArrayType::New(element, region);
+  }
+  static FunctionHandle Function(
+      TypeHandle result, TypeHandle receiver, int arity, Region* region) {
+    return FunctionType::New(result, receiver, arity, region);
+  }
+  static TypeHandle Function(TypeHandle result, Region* region) {
+    return Function(result, Any(region), 0, region);
+  }
+  static TypeHandle Function(
+      TypeHandle result, TypeHandle param0, Region* region) {
+    FunctionHandle function = Function(result, Any(region), 1, region);
+    function->InitParameter(0, param0);
+    return function;
+  }
+  static TypeHandle Function(
+      TypeHandle result, TypeHandle param0, TypeHandle param1, Region* region) {
+    FunctionHandle function = Function(result, Any(region), 2, region);
+    function->InitParameter(0, param0);
+    function->InitParameter(1, param1);
+    return function;
   }
 
   static TypeHandle Union(TypeHandle type1, TypeHandle type2, Region* reg);
   static TypeHandle Intersect(TypeHandle type1, TypeHandle type2, Region* reg);
 
   static TypeHandle Of(i::Object* value, Region* region) {
-    return Config::from_bitset(LubBitset(value), region);
+    return Config::from_bitset(BitsetType::Lub(value), region);
   }
   static TypeHandle Of(i::Handle<i::Object> value, Region* region) {
     return Of(*value, region);
   }
 
   bool IsInhabited() {
-    return !this->IsBitset() || IsInhabited(this->AsBitset());
+    return !this->IsBitset() || BitsetType::IsInhabited(this->AsBitset());
   }
 
   bool Is(TypeImpl* that) { return this == that || this->SlowIs(that); }
@@ -258,6 +301,10 @@ class TypeImpl : public Config::Base {
   template<class TypeHandle>
   bool Maybe(TypeHandle that) { return this->Maybe(*that); }
 
+  bool Equals(TypeImpl* that) { return this->Is(that) && that->Is(this); }
+  template<class TypeHandle>
+  bool Equals(TypeHandle that) { return this->Equals(*that); }
+
   // Equivalent to Constant(value)->Is(this), but avoiding allocation.
   bool Contains(i::Object* val);
   bool Contains(i::Handle<i::Object> val) { return this->Contains(*val); }
@@ -276,127 +323,256 @@ class TypeImpl : public Config::Base {
 
   bool IsClass() { return Config::is_class(this); }
   bool IsConstant() { return Config::is_constant(this); }
-  i::Handle<i::Map> AsClass() { return Config::as_class(this); }
-  i::Handle<i::Object> AsConstant() { return Config::as_constant(this); }
+  bool IsArray() { return Config::is_struct(this, StructuralType::kArrayTag); }
+  bool IsFunction() {
+    return Config::is_struct(this, StructuralType::kFunctionTag);
+  }
+
+  ClassType* AsClass() { return ClassType::cast(this); }
+  ConstantType* AsConstant() { return ConstantType::cast(this); }
+  ArrayType* AsArray() { return ArrayType::cast(this); }
+  FunctionType* AsFunction() { return FunctionType::cast(this); }
 
   int NumClasses();
   int NumConstants();
 
+  template<class T> class Iterator;
+  inline Iterator<i::Map> Classes();
+  inline Iterator<i::Object> Constants();
+
+  static inline TypeImpl* cast(typename Config::Base* object);
+
+  template<class OtherTypeImpl>
+  static TypeHandle Convert(
+      typename OtherTypeImpl::TypeHandle type, Region* region);
+
+  enum PrintDimension { BOTH_DIMS, SEMANTIC_DIM, REPRESENTATION_DIM };
+  void TypePrint(PrintDimension = BOTH_DIMS);
+  void TypePrint(FILE* out, PrintDimension = BOTH_DIMS);
+
+ protected:
+  template<class> friend class Iterator;
+  template<class> friend class TypeImpl;
+
   template<class T>
-  class Iterator {
-   public:
-    bool Done() const { return index_ < 0; }
-    i::Handle<T> Current();
-    void Advance();
-
-   private:
-    template<class> friend class TypeImpl;
-
-    Iterator() : index_(-1) {}
-    explicit Iterator(TypeHandle type) : type_(type), index_(-1) {
-      Advance();
-    }
+  static typename Config::template Handle<T>::type handle(T* type) {
+    return Config::handle(type);
+  }
+
+  bool IsNone() { return this == None(); }
+  bool IsAny() { return this == Any(); }
+  bool IsBitset() { return Config::is_bitset(this); }
+  bool IsUnion() { return Config::is_struct(this, StructuralType::kUnionTag); }
+
+  int AsBitset() {
+    ASSERT(this->IsBitset());
+    return static_cast<BitsetType*>(this)->Bitset();
+  }
+  UnionType* AsUnion() { return UnionType::cast(this); }
+
+  bool SlowIs(TypeImpl* that);
 
-    inline bool matches(TypeHandle type);
-    inline TypeHandle get_type();
+  bool InUnion(UnionHandle unioned, int current_size);
+  static int ExtendUnion(
+      UnionHandle unioned, TypeHandle t, int current_size);
+  static int ExtendIntersection(
+      UnionHandle unioned, TypeHandle t, TypeHandle other, int current_size);
+
+  int BitsetGlb() { return BitsetType::Glb(this); }
+  int BitsetLub() { return BitsetType::Lub(this); }
+};
+
+
+template<class Config>
+class TypeImpl<Config>::BitsetType : public TypeImpl<Config> {
+ private:
+  friend class TypeImpl<Config>;
 
-    TypeHandle type_;
-    int index_;
+  enum {
+    #define DECLARE_TYPE(type, value) k##type = (value),
+    BITSET_TYPE_LIST(DECLARE_TYPE)
+    #undef DECLARE_TYPE
+    kUnusedEOL = 0
   };
 
-  Iterator<i::Map> Classes() {
-    if (this->IsBitset()) return Iterator<i::Map>();
-    return Iterator<i::Map>(Config::handle(this));
+  int Bitset() { return Config::as_bitset(this); }
+
+  static BitsetType* New(int bitset) {
+    return static_cast<BitsetType*>(Config::from_bitset(bitset));
   }
-  Iterator<i::Object> Constants() {
-    if (this->IsBitset()) return Iterator<i::Object>();
-    return Iterator<i::Object>(Config::handle(this));
+  static TypeHandle New(int bitset, Region* region) {
+    return Config::from_bitset(bitset, region);
   }
 
-  static TypeImpl* cast(typename Config::Base* object) {
-    TypeImpl* t = static_cast<TypeImpl*>(object);
-    ASSERT(t->IsBitset() || t->IsClass() || t->IsConstant() || t->IsUnion());
-    return t;
+  static bool IsInhabited(int bitset) {
+    return (bitset & kRepresentation) && (bitset & kSemantic);
   }
 
-  template<class OtherTypeImpl>
-  static TypeHandle Convert(
-      typename OtherTypeImpl::TypeHandle type, Region* region);
+  static int Glb(TypeImpl* type);  // greatest lower bound that's a bitset
+  static int Lub(TypeImpl* type);  // least upper bound that's a bitset
+  static int Lub(i::Object* value);
+  static int Lub(i::Map* map);
 
-  enum PrintDimension { BOTH_DIMS, SEMANTIC_DIM, REPRESENTATION_DIM };
-  void TypePrint(PrintDimension = BOTH_DIMS);
-  void TypePrint(FILE* out, PrintDimension = BOTH_DIMS);
+  static const char* Name(int bitset);
+  static void BitsetTypePrint(FILE* out, int bitset);
+};
 
- private:
-  template<class> friend class Iterator;
+
+// Internal
+// A structured type contains a tag and a variable number of type fields.
+template<class Config>
+class TypeImpl<Config>::StructuralType : public TypeImpl<Config> {
+ protected:
   template<class> friend class TypeImpl;
-  friend struct ZoneTypeConfig;
+  friend struct ZoneTypeConfig;  // For tags.
   friend struct HeapTypeConfig;
 
   enum Tag {
     kClassTag,
     kConstantTag,
+    kArrayTag,
+    kFunctionTag,
     kUnionTag
   };
 
-  // A structured type contains a tag an a variable number of type fields.
-  // A union is a structured type with the following invariants:
-  // - its length is at least 2
-  // - at most one field is a bitset, and it must go into index 0
-  // - no field is a union
-  typedef typename Config::Struct Struct;
-  typedef typename Config::template Handle<Struct>::type StructHandle;
+  int Length() {
+    return Config::struct_length(Config::as_struct(this));
+  }
+  TypeHandle Get(int i) {
+    return Config::struct_get(Config::as_struct(this), i);
+  }
+  void Set(int i, TypeHandle type) {
+    Config::struct_set(Config::as_struct(this), i, type);
+  }
+  void Shrink(int length) {
+    Config::struct_shrink(Config::as_struct(this), length);
+  }
+
+  static TypeHandle New(Tag tag, int length, Region* region) {
+    return Config::from_struct(Config::struct_create(tag, length, region));
+  }
+};
 
-  enum {
-    #define DECLARE_TYPE(type, value) k##type = (value),
-    BITSET_TYPE_LIST(DECLARE_TYPE)
-    #undef DECLARE_TYPE
-    kUnusedEOL = 0
-  };
 
-  bool IsNone() { return this == None(); }
-  bool IsAny() { return this == Any(); }
-  bool IsBitset() { return Config::is_bitset(this); }
-  bool IsStruct(Tag tag) {
-    return Config::is_struct(this)
-        && Config::struct_tag(Config::as_struct(this)) == tag;
+template<class Config>
+class TypeImpl<Config>::ClassType : public TypeImpl<Config> {
+ public:
+  i::Handle<i::Map> Map() { return Config::as_class(this); }
+
+  static ClassHandle New(i::Handle<i::Map> map, Region* region) {
+    return Config::template cast<ClassType>(
+        Config::from_class(map, BitsetType::Lub(*map), region));
   }
-  bool IsUnion() { return IsStruct(kUnionTag); }
 
-  int AsBitset() { return Config::as_bitset(this); }
-  StructHandle AsStruct(Tag tag) {
-    ASSERT(IsStruct(tag));
-    return Config::as_struct(this);
+  static ClassType* cast(TypeImpl* type) {
+    ASSERT(type->IsClass());
+    return static_cast<ClassType*>(type);
   }
-  StructHandle AsUnion() { return AsStruct(kUnionTag); }
+};
+
 
-  static int StructLength(StructHandle structured) {
-    return Config::struct_length(structured);
+template<class Config>
+class TypeImpl<Config>::ConstantType : public TypeImpl<Config> {
+ public:
+  i::Handle<i::Object> Value() { return Config::as_constant(this); }
+
+  static ConstantHandle New(i::Handle<i::Object> value, Region* region) {
+    return Config::template cast<ConstantType>(
+        Config::from_constant(value, BitsetType::Lub(*value), region));
   }
-  static TypeHandle StructGet(StructHandle structured, int i) {
-    return Config::struct_get(structured, i);
+
+  static ConstantType* cast(TypeImpl* type) {
+    ASSERT(type->IsConstant());
+    return static_cast<ConstantType*>(type);
   }
+};
 
-  bool SlowIs(TypeImpl* that);
 
-  static bool IsInhabited(int bitset) {
-    return (bitset & kRepresentation) && (bitset & kSemantic);
+// Internal
+// A union is a structured type with the following invariants:
+// - its length is at least 2
+// - at most one field is a bitset, and it must go into index 0
+// - no field is a union
+template<class Config>
+class TypeImpl<Config>::UnionType : public StructuralType {
+ public:
+  static UnionHandle New(int length, Region* region) {
+    return Config::template cast<UnionType>(
+        StructuralType::New(StructuralType::kUnionTag, length, region));
   }
 
-  int LubBitset();  // least upper bound that's a bitset
-  int GlbBitset();  // greatest lower bound that's a bitset
+  static UnionType* cast(TypeImpl* type) {
+    ASSERT(type->IsUnion());
+    return static_cast<UnionType*>(type);
+  }
+};
 
-  static int LubBitset(i::Object* value);
-  static int LubBitset(i::Map* map);
 
-  bool InUnion(StructHandle unioned, int current_size);
-  static int ExtendUnion(
-      StructHandle unioned, TypeHandle t, int current_size);
-  static int ExtendIntersection(
-      StructHandle unioned, TypeHandle t, TypeHandle other, int current_size);
+template<class Config>
+class TypeImpl<Config>::ArrayType : public StructuralType {
+ public:
+  TypeHandle Element() { return this->Get(0); }
 
-  static const char* bitset_name(int bitset);
-  static void BitsetTypePrint(FILE* out, int bitset);
+  static ArrayHandle New(TypeHandle element, Region* region) {
+    ArrayHandle type = Config::template cast<ArrayType>(
+        StructuralType::New(StructuralType::kArrayTag, 1, region));
+    type->Set(0, element);
+    return type;
+  }
+
+  static ArrayType* cast(TypeImpl* type) {
+    ASSERT(type->IsArray());
+    return static_cast<ArrayType*>(type);
+  }
+};
+
+
+template<class Config>
+class TypeImpl<Config>::FunctionType : public StructuralType {
+ public:
+  int Arity() { return this->Length() - 2; }
+  TypeHandle Result() { return this->Get(0); }
+  TypeHandle Receiver() { return this->Get(1); }
+  TypeHandle Parameter(int i) { return this->Get(2 + i); }
+
+  void InitParameter(int i, TypeHandle type) { this->Set(2 + i, type); }
+
+  static FunctionHandle New(
+      TypeHandle result, TypeHandle receiver, int arity, Region* region) {
+    FunctionHandle type = Config::template cast<FunctionType>(
+        StructuralType::New(StructuralType::kFunctionTag, 2 + arity, region));
+    type->Set(0, result);
+    type->Set(1, receiver);
+    return type;
+  }
+
+  static FunctionType* cast(TypeImpl* type) {
+    ASSERT(type->IsFunction());
+    return static_cast<FunctionType*>(type);
+  }
+};
+
+
+template<class Config> template<class T>
+class TypeImpl<Config>::Iterator {
+ public:
+  bool Done() const { return index_ < 0; }
+  i::Handle<T> Current();
+  void Advance();
+
+ private:
+  template<class> friend class TypeImpl;
+
+  Iterator() : index_(-1) {}
+  explicit Iterator(TypeHandle type) : type_(type), index_(-1) {
+    Advance();
+  }
+
+  inline bool matches(TypeHandle type);
+  inline TypeHandle get_type();
+
+  TypeHandle type_;
+  int index_;
 };
 
 
@@ -409,27 +585,33 @@ struct ZoneTypeConfig {
   typedef i::Zone Region;
   template<class T> struct Handle { typedef T* type; };
 
-  static inline Type* handle(Type* type);
+  template<class T> static inline T* handle(T* type);
+  template<class T> static inline T* cast(Type* type);
+
   static inline bool is_bitset(Type* type);
   static inline bool is_class(Type* type);
   static inline bool is_constant(Type* type);
-  static inline bool is_struct(Type* type);
+  static inline bool is_struct(Type* type, int tag);
+
   static inline int as_bitset(Type* type);
   static inline Struct* as_struct(Type* type);
   static inline i::Handle<i::Map> as_class(Type* type);
   static inline i::Handle<i::Object> as_constant(Type* type);
+
   static inline Type* from_bitset(int bitset);
   static inline Type* from_bitset(int bitset, Zone* zone);
   static inline Type* from_struct(Struct* structured);
   static inline Type* from_class(i::Handle<i::Map> map, int lub, Zone* zone);
   static inline Type* from_constant(
       i::Handle<i::Object> value, int lub, Zone* zone);
+
   static inline Struct* struct_create(int tag, int length, Zone* zone);
   static inline void struct_shrink(Struct* structured, int length);
   static inline int struct_tag(Struct* structured);
   static inline int struct_length(Struct* structured);
   static inline Type* struct_get(Struct* structured, int i);
   static inline void struct_set(Struct* structured, int i, Type* type);
+
   static inline int lub_bitset(Type* type);
 };
 
@@ -445,15 +627,19 @@ struct HeapTypeConfig {
   typedef i::Isolate Region;
   template<class T> struct Handle { typedef i::Handle<T> type; };
 
-  static inline i::Handle<Type> handle(Type* type);
+  template<class T> static inline i::Handle<T> handle(T* type);
+  template<class T> static inline i::Handle<T> cast(i::Handle<Type> type);
+
   static inline bool is_bitset(Type* type);
   static inline bool is_class(Type* type);
   static inline bool is_constant(Type* type);
-  static inline bool is_struct(Type* type);
+  static inline bool is_struct(Type* type, int tag);
+
   static inline int as_bitset(Type* type);
   static inline i::Handle<i::Map> as_class(Type* type);
   static inline i::Handle<i::Object> as_constant(Type* type);
   static inline i::Handle<Struct> as_struct(Type* type);
+
   static inline Type* from_bitset(int bitset);
   static inline i::Handle<Type> from_bitset(int bitset, Isolate* isolate);
   static inline i::Handle<Type> from_class(
@@ -461,6 +647,7 @@ struct HeapTypeConfig {
   static inline i::Handle<Type> from_constant(
       i::Handle<i::Object> value, int lub, Isolate* isolate);
   static inline i::Handle<Type> from_struct(i::Handle<Struct> structured);
+
   static inline i::Handle<Struct> struct_create(
       int tag, int length, Isolate* isolate);
   static inline void struct_shrink(i::Handle<Struct> structured, int length);
@@ -469,6 +656,7 @@ struct HeapTypeConfig {
   static inline i::Handle<Type> struct_get(i::Handle<Struct> structured, int i);
   static inline void struct_set(
       i::Handle<Struct> structured, int i, i::Handle<Type> type);
+
   static inline int lub_bitset(Type* type);
 };
 
index 88e7f38c487f5ee1bd99d108348a7cf44e724f0f..0981114ec404c100760795ba8ae82c403f33bba3 100644 (file)
@@ -496,7 +496,8 @@ void StoreStubCompiler::GenerateStoreTransition(MacroAssembler* masm,
   } else if (representation.IsHeapObject()) {
     HeapType* field_type = descriptors->GetFieldType(descriptor);
     if (field_type->IsClass()) {
-      __ CheckMap(value_reg, field_type->AsClass(), miss_label, DO_SMI_CHECK);
+      __ CheckMap(value_reg, field_type->AsClass()->Map(),
+                  miss_label, DO_SMI_CHECK);
     } else {
       ASSERT(HeapType::Any()->Is(field_type));
       __ JumpIfSmi(value_reg, miss_label);
@@ -646,7 +647,8 @@ void StoreStubCompiler::GenerateStoreField(MacroAssembler* masm,
   } else if (representation.IsHeapObject()) {
     HeapType* field_type = lookup->GetFieldType();
     if (field_type->IsClass()) {
-      __ CheckMap(value_reg, field_type->AsClass(), miss_label, DO_SMI_CHECK);
+      __ CheckMap(value_reg, field_type->AsClass()->Map(),
+                  miss_label, DO_SMI_CHECK);
     } else {
       ASSERT(HeapType::Any()->Is(field_type));
       __ JumpIfSmi(value_reg, miss_label);
@@ -753,7 +755,9 @@ Register StubCompiler::CheckPrototypes(Handle<HeapType> type,
   int depth = 0;
 
   Handle<JSObject> current = Handle<JSObject>::null();
-  if (type->IsConstant()) current = Handle<JSObject>::cast(type->AsConstant());
+  if (type->IsConstant()) {
+    current = Handle<JSObject>::cast(type->AsConstant()->Value());
+  }
   Handle<JSObject> prototype = Handle<JSObject>::null();
   Handle<Map> current_map = receiver_map;
   Handle<Map> holder_map(holder->map());
index 62ec698ec32bfe610690dcb1c4bdef1bcc02f1ef..59a8f0851a47e44e0539513d7e87da433ec84af2 100644 (file)
@@ -43,7 +43,9 @@ struct ZoneRep {
   static bool IsBitset(Type* t) { return reinterpret_cast<intptr_t>(t) & 1; }
   static bool IsClass(Type* t) { return IsStruct(t, 0); }
   static bool IsConstant(Type* t) { return IsStruct(t, 1); }
-  static bool IsUnion(Type* t) { return IsStruct(t, 2); }
+  static bool IsArray(Type* t) { return IsStruct(t, 2); }
+  static bool IsFunction(Type* t) { return IsStruct(t, 3); }
+  static bool IsUnion(Type* t) { return IsStruct(t, 4); }
 
   static Struct* AsStruct(Type* t) {
     return reinterpret_cast<Struct*>(t);
@@ -77,7 +79,9 @@ struct HeapRep {
   static bool IsBitset(Handle<HeapType> t) { return t->IsSmi(); }
   static bool IsClass(Handle<HeapType> t) { return t->IsMap(); }
   static bool IsConstant(Handle<HeapType> t) { return t->IsBox(); }
-  static bool IsUnion(Handle<HeapType> t) { return IsStruct(t, 2); }
+  static bool IsArray(Handle<HeapType> t) { return IsStruct(t, 2); }
+  static bool IsFunction(Handle<HeapType> t) { return IsStruct(t, 3); }
+  static bool IsUnion(Handle<HeapType> t) { return IsStruct(t, 4); }
 
   static Struct* AsStruct(Handle<HeapType> t) { return FixedArray::cast(*t); }
   static int AsBitset(Handle<HeapType> t) { return Smi::cast(*t)->value(); }
@@ -139,11 +143,31 @@ class Types {
       types.push_back(Type::Constant(*it, region));
     }
 
+    FloatArray = Type::Array(Float, region);
+    StringArray = Type::Array(String, region);
+    AnyArray = Type::Array(Any, region);
+
+    SignedFunction1 = Type::Function(SignedSmall, SignedSmall, region);
+    NumberFunction1 = Type::Function(Number, Number, region);
+    NumberFunction2 = Type::Function(Number, Number, Number, region);
+    MethodFunction = Type::Function(String, Object, 0, region);
+
     for (int i = 0; i < 50; ++i) {
       types.push_back(Fuzz());
     }
   }
 
+  Handle<i::Map> object_map;
+  Handle<i::Map> array_map;
+  Handle<i::Map> uninitialized_map;
+
+  Handle<i::Smi> smi;
+  Handle<i::HeapNumber> signed32;
+  Handle<i::JSObject> object1;
+  Handle<i::JSObject> object2;
+  Handle<i::JSArray> array;
+  Handle<i::Oddball> uninitialized;
+
   #define DECLARE_TYPE(name, value) TypeHandle name;
   BITSET_TYPE_LIST(DECLARE_TYPE)
   #undef DECLARE_TYPE
@@ -159,16 +183,14 @@ class Types {
   TypeHandle ArrayConstant;
   TypeHandle UninitializedConstant;
 
-  Handle<i::Map> object_map;
-  Handle<i::Map> array_map;
-  Handle<i::Map> uninitialized_map;
+  TypeHandle FloatArray;
+  TypeHandle StringArray;
+  TypeHandle AnyArray;
 
-  Handle<i::Smi> smi;
-  Handle<i::HeapNumber> signed32;
-  Handle<i::JSObject> object1;
-  Handle<i::JSObject> object2;
-  Handle<i::JSArray> array;
-  Handle<i::Oddball> uninitialized;
+  TypeHandle SignedFunction1;
+  TypeHandle NumberFunction1;
+  TypeHandle NumberFunction2;
+  TypeHandle MethodFunction;
 
   typedef std::vector<TypeHandle> TypeVector;
   typedef std::vector<Handle<i::Map> > MapVector;
@@ -193,6 +215,24 @@ class Types {
     return Type::Class(map, region_);
   }
 
+  TypeHandle Array1(TypeHandle element) {
+    return Type::Array(element, region_);
+  }
+
+  TypeHandle Function0(TypeHandle result, TypeHandle receiver) {
+    return Type::Function(result, receiver, 0, region_);
+  }
+
+  TypeHandle Function1(TypeHandle result, TypeHandle receiver, TypeHandle arg) {
+    TypeHandle type = Type::Function(result, receiver, 1, region_);
+    type->AsFunction()->InitParameter(0, arg);
+    return type;
+  }
+
+  TypeHandle Function2(TypeHandle result, TypeHandle arg1, TypeHandle arg2) {
+    return Type::Function(result, arg1, arg2, region_);
+  }
+
   TypeHandle Union(TypeHandle t1, TypeHandle t2) {
     return Type::Union(t1, t2, region_);
   }
@@ -205,6 +245,10 @@ class Types {
     return Type::template Convert<Type2>(t, region_);
   }
 
+  TypeHandle Random() {
+    return types[rng_.NextInt(static_cast<int>(types.size()))];
+  }
+
   TypeHandle Fuzz(int depth = 5) {
     switch (rng_.NextInt(depth == 0 ? 3 : 20)) {
       case 0: {  // bitset
@@ -228,6 +272,17 @@ class Types {
         int i = rng_.NextInt(static_cast<int>(values.size()));
         return Type::Constant(values[i], region_);
       }
+      case 3:  // array
+        return Type::Array(Fuzz(depth / 2), region_);
+      case 4:
+      case 5:
+      case 6: {  // function
+        TypeHandle type = Type::Function(
+            Fuzz(depth / 2), Fuzz(depth / 2), rand() % 3, region_);
+        for (int i = 0; i < type->AsFunction()->Arity(); ++i) {
+          type->AsFunction()->InitParameter(i, Fuzz(depth - 1));
+        }
+      }
       default: {  // union
         int n = rng_.NextInt(10);
         TypeHandle type = None;
@@ -406,7 +461,7 @@ struct Tests : Rep {
     for (MapIterator mt = T.maps.begin(); mt != T.maps.end(); ++mt) {
       Handle<i::Map> map = *mt;
       TypeHandle type = T.Class(map);
-      CHECK(*map == *type->AsClass());
+      CHECK(*map == *type->AsClass()->Map());
     }
 
     // Functionality & Injectivity: Class(M1) = Class(M2) iff M1 = M2
@@ -433,10 +488,10 @@ struct Tests : Rep {
     for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
       Handle<i::Object> value = *vt;
       TypeHandle type = T.Constant(value);
-      CHECK(*value == *type->AsConstant());
+      CHECK(*value == *type->AsConstant()->Value());
     }
 
-    // Functionality & Injectivity: Constant(V1) = Constant(v2) iff V1 = V2
+    // Functionality & Injectivity: Constant(V1) = Constant(V2) iff V1 = V2
     for (ValueIterator vt1 = T.values.begin(); vt1 != T.values.end(); ++vt1) {
       for (ValueIterator vt2 = T.values.begin(); vt2 != T.values.end(); ++vt2) {
         Handle<i::Object> value1 = *vt1;
@@ -448,6 +503,102 @@ struct Tests : Rep {
     }
   }
 
+  void Array() {
+    // Constructor
+    for (int i = 0; i < 20; ++i) {
+      TypeHandle type = T.Random();
+      TypeHandle array = T.Array1(type);
+      CHECK(this->IsArray(array));
+    }
+
+    // Attributes
+    for (int i = 0; i < 20; ++i) {
+      TypeHandle type = T.Random();
+      TypeHandle array = T.Array1(type);
+      CheckEqual(type, array->AsArray()->Element());
+    }
+
+    // Functionality & Injectivity: Array(T1) = Array(T2) iff T1 = T2
+    for (int i = 0; i < 20; ++i) {
+      for (int j = 0; j < 20; ++j) {
+        TypeHandle type1 = T.Random();
+        TypeHandle type2 = T.Random();
+        TypeHandle array1 = T.Array1(type1);
+        TypeHandle array2 = T.Array1(type2);
+        CHECK(Equal(array1, array2) == Equal(type1, type2));
+      }
+    }
+  }
+
+  void Function() {
+    // Constructors
+    for (int i = 0; i < 20; ++i) {
+      for (int j = 0; j < 20; ++j) {
+        for (int k = 0; k < 20; ++k) {
+          TypeHandle type1 = T.Random();
+          TypeHandle type2 = T.Random();
+          TypeHandle type3 = T.Random();
+          TypeHandle function0 = T.Function0(type1, type2);
+          TypeHandle function1 = T.Function1(type1, type2, type3);
+          TypeHandle function2 = T.Function2(type1, type2, type3);
+          CHECK(function0->IsFunction());
+          CHECK(function1->IsFunction());
+          CHECK(function2->IsFunction());
+        }
+      }
+    }
+
+    // Attributes
+    for (int i = 0; i < 20; ++i) {
+      for (int j = 0; j < 20; ++j) {
+        for (int k = 0; k < 20; ++k) {
+          TypeHandle type1 = T.Random();
+          TypeHandle type2 = T.Random();
+          TypeHandle type3 = T.Random();
+          TypeHandle function0 = T.Function0(type1, type2);
+          TypeHandle function1 = T.Function1(type1, type2, type3);
+          TypeHandle function2 = T.Function2(type1, type2, type3);
+          CHECK_EQ(0, function0->AsFunction()->Arity());
+          CHECK_EQ(1, function1->AsFunction()->Arity());
+          CHECK_EQ(2, function2->AsFunction()->Arity());
+          CheckEqual(type1, function0->AsFunction()->Result());
+          CheckEqual(type1, function1->AsFunction()->Result());
+          CheckEqual(type1, function2->AsFunction()->Result());
+          CheckEqual(type2, function0->AsFunction()->Receiver());
+          CheckEqual(type2, function1->AsFunction()->Receiver());
+          CheckEqual(T.Any, function2->AsFunction()->Receiver());
+          CheckEqual(type3, function1->AsFunction()->Parameter(0));
+          CheckEqual(type2, function2->AsFunction()->Parameter(0));
+          CheckEqual(type3, function2->AsFunction()->Parameter(1));
+        }
+      }
+    }
+
+    // Functionality & Injectivity: Function(Ts1) = Function(Ts2) iff Ts1 = Ts2
+    for (int i = 0; i < 20; ++i) {
+      for (int j = 0; j < 20; ++j) {
+        for (int k = 0; k < 20; ++k) {
+          TypeHandle type1 = T.Random();
+          TypeHandle type2 = T.Random();
+          TypeHandle type3 = T.Random();
+          TypeHandle function01 = T.Function0(type1, type2);
+          TypeHandle function02 = T.Function0(type1, type3);
+          TypeHandle function03 = T.Function0(type3, type2);
+          TypeHandle function11 = T.Function1(type1, type2, type2);
+          TypeHandle function12 = T.Function1(type1, type2, type3);
+          TypeHandle function21 = T.Function2(type1, type2, type2);
+          TypeHandle function22 = T.Function2(type1, type2, type3);
+          TypeHandle function23 = T.Function2(type1, type3, type2);
+          CHECK(Equal(function01, function02) == Equal(type2, type3));
+          CHECK(Equal(function01, function03) == Equal(type1, type3));
+          CHECK(Equal(function11, function12) == Equal(type2, type3));
+          CHECK(Equal(function21, function22) == Equal(type2, type3));
+          CHECK(Equal(function21, function23) == Equal(type2, type3));
+        }
+      }
+    }
+  }
+
   void Of() {
     // Constant(V)->Is(Of(V))
     for (ValueIterator vt = T.values.begin(); vt != T.values.end(); ++vt) {
@@ -641,6 +792,7 @@ struct Tests : Rep {
     // Structural types
     CheckSub(T.ObjectClass, T.Object);
     CheckSub(T.ArrayClass, T.Object);
+    CheckSub(T.ArrayClass, T.Array);
     CheckSub(T.UninitializedClass, T.Internal);
     CheckUnordered(T.ObjectClass, T.ArrayClass);
     CheckUnordered(T.UninitializedClass, T.Null);
@@ -664,6 +816,15 @@ struct Tests : Rep {
     CheckUnordered(T.ObjectConstant1, T.ArrayClass);
     CheckUnordered(T.ObjectConstant2, T.ArrayClass);
     CheckUnordered(T.ArrayConstant, T.ObjectClass);
+
+    CheckSub(T.FloatArray, T.Array);
+    CheckSub(T.FloatArray, T.Object);
+    CheckUnordered(T.StringArray, T.AnyArray);
+
+    CheckSub(T.MethodFunction, T.Function);
+    CheckSub(T.NumberFunction1, T.Object);
+    CheckUnordered(T.SignedFunction1, T.NumberFunction1);
+    CheckUnordered(T.NumberFunction1, T.NumberFunction2);
   }
 
   void NowIs() {
@@ -992,9 +1153,19 @@ struct Tests : Rep {
     CheckDisjoint(T.ObjectConstant1, T.ArrayClass, T.Semantic);
     CheckDisjoint(T.ObjectConstant2, T.ArrayClass, T.Semantic);
     CheckDisjoint(T.ArrayConstant, T.ObjectClass, T.Semantic);
+
+    CheckOverlap(T.FloatArray, T.Array, T.Semantic);
+    CheckDisjoint(T.FloatArray, T.AnyArray, T.Semantic);
+    CheckDisjoint(T.FloatArray, T.StringArray, T.Semantic);
+
+    CheckOverlap(T.MethodFunction, T.Function, T.Semantic);
+    CheckDisjoint(T.SignedFunction1, T.NumberFunction1, T.Semantic);
+    CheckDisjoint(T.SignedFunction1, T.NumberFunction2, T.Semantic);
+    CheckDisjoint(T.NumberFunction1, T.NumberFunction2, T.Semantic);
+    CheckDisjoint(T.SignedFunction1, T.MethodFunction, T.Semantic);
   }
 
-  void Union() {
+  void Union1() {
     // Identity: Union(T, None) = T
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
       TypeHandle type = *it;
@@ -1063,7 +1234,9 @@ struct Tests : Rep {
         if (type1->Is(type2)) CheckEqual(union12, type2);
       }
     }
+  }
 
+  void Union2() {
     // Monotonicity: T1->Is(T2) implies Union(T1, T3)->Is(Union(T2, T3))
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
@@ -1122,6 +1295,28 @@ struct Tests : Rep {
     CheckDisjoint(
         T.Union(T.ObjectConstant1, T.ArrayConstant), T.ObjectClass, T.Semantic);
 
+    // Bitset-array
+    CHECK(this->IsBitset(T.Union(T.AnyArray, T.Array)));
+    CHECK(this->IsUnion(T.Union(T.FloatArray, T.Number)));
+
+    CheckEqual(T.Union(T.AnyArray, T.Array), T.Array);
+    CheckSub(T.None, T.Union(T.FloatArray, T.Number));
+    CheckSub(T.Union(T.FloatArray, T.Number), T.Any);
+    CheckUnordered(T.Union(T.AnyArray, T.String), T.Array);
+    CheckOverlap(T.Union(T.FloatArray, T.String), T.Object, T.Semantic);
+    CheckDisjoint(T.Union(T.FloatArray, T.String), T.Number, T.Semantic);
+
+    // Bitset-function
+    CHECK(this->IsBitset(T.Union(T.MethodFunction, T.Function)));
+    CHECK(this->IsUnion(T.Union(T.NumberFunction1, T.Number)));
+
+    CheckEqual(T.Union(T.MethodFunction, T.Function), T.Function);
+    CheckSub(T.None, T.Union(T.MethodFunction, T.Number));
+    CheckSub(T.Union(T.MethodFunction, T.Number), T.Any);
+    CheckUnordered(T.Union(T.NumberFunction1, T.String), T.Function);
+    CheckOverlap(T.Union(T.NumberFunction2, T.String), T.Object, T.Semantic);
+    CheckDisjoint(T.Union(T.NumberFunction1, T.String), T.Number, T.Semantic);
+
     // Bitset-class
     CheckSub(
         T.Union(T.ObjectClass, T.SignedSmall), T.Union(T.Object, T.Number));
@@ -1177,6 +1372,18 @@ struct Tests : Rep {
         T.Union(
             T.ObjectConstant2, T.Union(T.ArrayConstant, T.ObjectConstant1)));
 
+    // Array-union
+    CheckEqual(
+        T.Union(T.AnyArray, T.Union(T.FloatArray, T.AnyArray)),
+        T.Union(T.AnyArray, T.FloatArray));
+    CheckSub(T.Union(T.AnyArray, T.FloatArray), T.Array);
+
+    // Function-union
+    CheckEqual(
+        T.Union(T.NumberFunction1, T.NumberFunction2),
+        T.Union(T.NumberFunction2, T.NumberFunction1));
+    CheckSub(T.Union(T.SignedFunction1, T.MethodFunction), T.Function);
+
     // Union-union
     CheckEqual(
         T.Union(
@@ -1190,7 +1397,7 @@ struct Tests : Rep {
         T.Union(T.Number, T.Array));
   }
 
-  void Intersect() {
+  void Intersect1() {
     // Identity: Intersect(T, Any) = T
     for (TypeIterator it = T.types.begin(); it != T.types.end(); ++it) {
       TypeHandle type = *it;
@@ -1260,7 +1467,9 @@ struct Tests : Rep {
         if (type1->Is(type2)) CheckEqual(intersect12, type1);
       }
     }
+  }
 
+  void Intersect2() {
     // Monotonicity: T1->Is(T2) implies Intersect(T1, T3)->Is(Intersect(T2, T3))
     for (TypeIterator it1 = T.types.begin(); it1 != T.types.end(); ++it1) {
       for (TypeIterator it2 = T.types.begin(); it2 != T.types.end(); ++it2) {
@@ -1308,9 +1517,13 @@ struct Tests : Rep {
     CheckSub(T.Intersect(T.ObjectClass, T.Array), T.Representation);
     CheckSub(T.Intersect(T.ObjectClass, T.Number), T.Representation);
 
-    // Class-constant
-    CheckEqual(T.Intersect(T.ObjectConstant1, T.ObjectClass), T.None);
-    CheckEqual(T.Intersect(T.ArrayClass, T.ObjectConstant2), T.None);
+    // Bitset-array
+    CheckEqual(T.Intersect(T.FloatArray, T.Object), T.FloatArray);
+    CheckSub(T.Intersect(T.AnyArray, T.Function), T.Representation);
+
+    // Bitset-function
+    CheckEqual(T.Intersect(T.MethodFunction, T.Object), T.MethodFunction);
+    CheckSub(T.Intersect(T.NumberFunction1, T.Array), T.Representation);
 
     // Bitset-union
     CheckEqual(
@@ -1320,6 +1533,32 @@ struct Tests : Rep {
         T.Intersect(T.Union(T.ArrayClass, T.ObjectConstant1), T.Number),
         T.None);
 
+    // Class-constant
+    CheckEqual(T.Intersect(T.ObjectConstant1, T.ObjectClass), T.None);
+    CheckEqual(T.Intersect(T.ArrayClass, T.ObjectConstant2), T.None);
+
+    // Array-union
+    CheckEqual(
+        T.Intersect(T.FloatArray, T.Union(T.FloatArray, T.ArrayClass)),
+        T.FloatArray);
+    CheckEqual(
+        T.Intersect(T.AnyArray, T.Union(T.Object, T.SmiConstant)),
+        T.AnyArray);
+    CheckEqual(
+        T.Intersect(T.Union(T.AnyArray, T.ArrayConstant), T.FloatArray),
+        T.None);
+
+    // Function-union
+    CheckEqual(
+        T.Intersect(T.MethodFunction, T.Union(T.String, T.MethodFunction)),
+        T.MethodFunction);
+    CheckEqual(
+        T.Intersect(T.NumberFunction1, T.Union(T.Object, T.SmiConstant)),
+        T.NumberFunction1);
+    CheckEqual(
+        T.Intersect(T.Union(T.MethodFunction, T.Name), T.NumberFunction2),
+        T.None);
+
     // Class-union
     CheckEqual(
         T.Intersect(T.ArrayClass, T.Union(T.ObjectConstant2, T.ArrayClass)),
@@ -1387,27 +1626,41 @@ typedef Tests<Type, Type*, Zone, ZoneRep> ZoneTests;
 typedef Tests<HeapType, Handle<HeapType>, Isolate, HeapRep> HeapTests;
 
 
-TEST(Bitset) {
+TEST(BitsetType) {
   CcTest::InitializeVM();
   ZoneTests().Bitset();
   HeapTests().Bitset();
 }
 
 
-TEST(Class) {
+TEST(ClassType) {
   CcTest::InitializeVM();
   ZoneTests().Class();
   HeapTests().Class();
 }
 
 
-TEST(Constant) {
+TEST(ConstantType) {
   CcTest::InitializeVM();
   ZoneTests().Constant();
   HeapTests().Constant();
 }
 
 
+TEST(ArrayType) {
+  CcTest::InitializeVM();
+  ZoneTests().Array();
+  HeapTests().Array();
+}
+
+
+TEST(FunctionType) {
+  CcTest::InitializeVM();
+  ZoneTests().Function();
+  HeapTests().Function();
+}
+
+
 TEST(Of) {
   CcTest::InitializeVM();
   ZoneTests().Of();
@@ -1457,17 +1710,31 @@ TEST(Maybe) {
 }
 
 
-TEST(Union) {
+TEST(Union1) {
+  CcTest::InitializeVM();
+  ZoneTests().Union1();
+  HeapTests().Union1();
+}
+
+
+TEST(Union2) {
+  CcTest::InitializeVM();
+  ZoneTests().Union2();
+  HeapTests().Union2();
+}
+
+
+TEST(Intersect1) {
   CcTest::InitializeVM();
-  ZoneTests().Union();
-  HeapTests().Union();
+  ZoneTests().Intersect1();
+  HeapTests().Intersect1();
 }
 
 
-TEST(Intersect) {
+TEST(Intersect2) {
   CcTest::InitializeVM();
-  ZoneTests().Intersect();
-  HeapTests().Intersect();
+  ZoneTests().Intersect2();
+  HeapTests().Intersect2();
 }