| Index: src/types.cc
 | 
| diff --git a/src/types.cc b/src/types.cc
 | 
| index 485ba885187364ed2b99098865eec3197b2c47dc..2aa60817e5f4f30e221085507ef3ae497a846e8e 100644
 | 
| --- a/src/types.cc
 | 
| +++ b/src/types.cc
 | 
| @@ -31,14 +31,15 @@
 | 
|  namespace v8 {
 | 
|  namespace internal {
 | 
|  
 | 
| -int Type::NumClasses() {
 | 
| -  if (is_class()) {
 | 
| +template<class Config>
 | 
| +int TypeImpl<Config>::NumClasses() {
 | 
| +  if (this->IsClass()) {
 | 
|      return 1;
 | 
| -  } else if (is_union()) {
 | 
| -    Handle<Unioned> unioned = as_union();
 | 
| +  } else if (this->IsUnion()) {
 | 
| +    UnionedHandle unioned = this->AsUnion();
 | 
|      int result = 0;
 | 
|      for (int i = 0; i < unioned->length(); ++i) {
 | 
| -      if (union_get(unioned, i)->is_class()) ++result;
 | 
| +      if (Config::union_get(unioned, i)->IsClass()) ++result;
 | 
|      }
 | 
|      return result;
 | 
|    } else {
 | 
| @@ -47,14 +48,15 @@ int Type::NumClasses() {
 | 
|  }
 | 
|  
 | 
|  
 | 
| -int Type::NumConstants() {
 | 
| -  if (is_constant()) {
 | 
| +template<class Config>
 | 
| +int TypeImpl<Config>::NumConstants() {
 | 
| +  if (this->IsConstant()) {
 | 
|      return 1;
 | 
| -  } else if (is_union()) {
 | 
| -    Handle<Unioned> unioned = as_union();
 | 
| +  } else if (this->IsUnion()) {
 | 
| +    UnionedHandle unioned = this->AsUnion();
 | 
|      int result = 0;
 | 
|      for (int i = 0; i < unioned->length(); ++i) {
 | 
| -      if (union_get(unioned, i)->is_constant()) ++result;
 | 
| +      if (Config::union_get(unioned, i)->IsConstant()) ++result;
 | 
|      }
 | 
|      return result;
 | 
|    } else {
 | 
| @@ -63,41 +65,61 @@ int Type::NumConstants() {
 | 
|  }
 | 
|  
 | 
|  
 | 
| -template<class T>
 | 
| -Handle<Type> Type::Iterator<T>::get_type() {
 | 
| +template<class Config> template<class T>
 | 
| +typename TypeImpl<Config>::TypeHandle
 | 
| +TypeImpl<Config>::Iterator<T>::get_type() {
 | 
|    ASSERT(!Done());
 | 
| -  return type_->is_union() ? union_get(type_->as_union(), index_) : type_;
 | 
| +  return type_->IsUnion() ? Config::union_get(type_->AsUnion(), index_) : type_;
 | 
|  }
 | 
|  
 | 
| -template<>
 | 
| -Handle<i::Map> Type::Iterator<i::Map>::Current() {
 | 
| -  return get_type()->as_class();
 | 
| -}
 | 
|  
 | 
| -template<>
 | 
| -Handle<i::Object> Type::Iterator<i::Object>::Current() {
 | 
| -  return get_type()->as_constant();
 | 
| -}
 | 
| +// C++ cannot specialise nested templates, so we have to go through this
 | 
| +// contortion with an auxiliary template to simulate it.
 | 
| +template<class Config, class T>
 | 
| +struct TypeImplIteratorAux {
 | 
| +  static bool matches(typename TypeImpl<Config>::TypeHandle type);
 | 
| +  static i::Handle<T> current(typename TypeImpl<Config>::TypeHandle type);
 | 
| +};
 | 
| +
 | 
| +template<class Config>
 | 
| +struct TypeImplIteratorAux<Config, i::Map> {
 | 
| +  static bool matches(typename TypeImpl<Config>::TypeHandle type) {
 | 
| +    return type->IsClass();
 | 
| +  }
 | 
| +  static i::Handle<i::Map> current(typename TypeImpl<Config>::TypeHandle type) {
 | 
| +    return type->AsClass();
 | 
| +  }
 | 
| +};
 | 
|  
 | 
| +template<class Config>
 | 
| +struct TypeImplIteratorAux<Config, i::Object> {
 | 
| +  static bool matches(typename TypeImpl<Config>::TypeHandle type) {
 | 
| +    return type->IsConstant();
 | 
| +  }
 | 
| +  static i::Handle<i::Object> current(
 | 
| +      typename TypeImpl<Config>::TypeHandle type) {
 | 
| +    return type->AsConstant();
 | 
| +  }
 | 
| +};
 | 
|  
 | 
| -template<>
 | 
| -bool Type::Iterator<i::Map>::matches(Handle<Type> type) {
 | 
| -  return type->is_class();
 | 
| +template<class Config> template<class T>
 | 
| +bool TypeImpl<Config>::Iterator<T>::matches(TypeHandle type) {
 | 
| +  return TypeImplIteratorAux<Config, T>::matches(type);
 | 
|  }
 | 
|  
 | 
| -template<>
 | 
| -bool Type::Iterator<i::Object>::matches(Handle<Type> type) {
 | 
| -  return type->is_constant();
 | 
| +template<class Config> template<class T>
 | 
| +i::Handle<T> TypeImpl<Config>::Iterator<T>::Current() {
 | 
| +  return TypeImplIteratorAux<Config, T>::current(get_type());
 | 
|  }
 | 
|  
 | 
|  
 | 
| -template<class T>
 | 
| -void Type::Iterator<T>::Advance() {
 | 
| +template<class Config> template<class T>
 | 
| +void TypeImpl<Config>::Iterator<T>::Advance() {
 | 
|    ++index_;
 | 
| -  if (type_->is_union()) {
 | 
| -    Handle<Unioned> unioned = type_->as_union();
 | 
| +  if (type_->IsUnion()) {
 | 
| +    UnionedHandle unioned = type_->AsUnion();
 | 
|      for (; index_ < unioned->length(); ++index_) {
 | 
| -      if (matches(union_get(unioned, index_))) return;
 | 
| +      if (matches(Config::union_get(unioned, index_))) return;
 | 
|      }
 | 
|    } else if (index_ == 0 && matches(type_)) {
 | 
|      return;
 | 
| @@ -105,30 +127,29 @@ void Type::Iterator<T>::Advance() {
 | 
|    index_ = -1;
 | 
|  }
 | 
|  
 | 
| -template class Type::Iterator<i::Map>;
 | 
| -template class Type::Iterator<i::Object>;
 | 
| -
 | 
|  
 | 
|  // Get the smallest bitset subsuming this type.
 | 
| -int Type::LubBitset() {
 | 
| -  if (this->is_bitset()) {
 | 
| -    return this->as_bitset();
 | 
| -  } else if (this->is_union()) {
 | 
| -    Handle<Unioned> unioned = this->as_union();
 | 
| +template<class Config>
 | 
| +int TypeImpl<Config>::LubBitset() {
 | 
| +  if (this->IsBitset()) {
 | 
| +    return this->AsBitset();
 | 
| +  } else if (this->IsUnion()) {
 | 
| +    UnionedHandle unioned = this->AsUnion();
 | 
|      int bitset = kNone;
 | 
|      for (int i = 0; i < unioned->length(); ++i) {
 | 
| -      bitset |= union_get(unioned, i)->LubBitset();
 | 
| +      bitset |= Config::union_get(unioned, i)->LubBitset();
 | 
|      }
 | 
|      return bitset;
 | 
| -  } else if (this->is_class()) {
 | 
| -    return LubBitset(*this->as_class());
 | 
| +  } else if (this->IsClass()) {
 | 
| +    return LubBitset(*this->AsClass());
 | 
|    } else {
 | 
| -    return LubBitset(*this->as_constant());
 | 
| +    return LubBitset(*this->AsConstant());
 | 
|    }
 | 
|  }
 | 
|  
 | 
|  
 | 
| -int Type::LubBitset(i::Object* value) {
 | 
| +template<class Config>
 | 
| +int TypeImpl<Config>::LubBitset(i::Object* value) {
 | 
|    if (value->IsSmi()) return kSmi;
 | 
|    i::Map* map = i::HeapObject::cast(value)->map();
 | 
|    if (map->instance_type() == HEAP_NUMBER_TYPE) {
 | 
| @@ -145,11 +166,12 @@ int Type::LubBitset(i::Object* value) {
 | 
|      if (value->IsTheHole()) return kAny;  // TODO(rossberg): kNone?
 | 
|      UNREACHABLE();
 | 
|    }
 | 
| -  return Type::LubBitset(map);
 | 
| +  return LubBitset(map);
 | 
|  }
 | 
|  
 | 
|  
 | 
| -int Type::LubBitset(i::Map* map) {
 | 
| +template<class Config>
 | 
| +int TypeImpl<Config>::LubBitset(i::Map* map) {
 | 
|    switch (map->instance_type()) {
 | 
|      case STRING_TYPE:
 | 
|      case ASCII_STRING_TYPE:
 | 
| @@ -231,12 +253,13 @@ int Type::LubBitset(i::Map* map) {
 | 
|  
 | 
|  
 | 
|  // Get the largest bitset subsumed by this type.
 | 
| -int Type::GlbBitset() {
 | 
| -  if (this->is_bitset()) {
 | 
| -    return this->as_bitset();
 | 
| -  } else if (this->is_union()) {
 | 
| +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 union_get(this->as_union(), 0)->GlbBitset();
 | 
| +    return Config::union_get(this->AsUnion(), 0)->GlbBitset();
 | 
|    } else {
 | 
|      return kNone;
 | 
|    }
 | 
| @@ -244,37 +267,40 @@ int Type::GlbBitset() {
 | 
|  
 | 
|  
 | 
|  // Most precise _current_ type of a value (usually its class).
 | 
| -Type* Type::OfCurrently(Handle<i::Object> value) {
 | 
| -  if (value->IsSmi()) return Smi();
 | 
| +template<class Config>
 | 
| +typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::OfCurrently(
 | 
| +    i::Handle<i::Object> value, Region* region) {
 | 
| +  if (value->IsSmi()) return Smi(region);
 | 
|    i::Map* map = i::HeapObject::cast(*value)->map();
 | 
|    if (map->instance_type() == HEAP_NUMBER_TYPE ||
 | 
|        map->instance_type() == ODDBALL_TYPE) {
 | 
| -    return Type::Of(value);
 | 
| +    return Of(value, region);
 | 
|    }
 | 
| -  return Class(i::handle(map));
 | 
| +  return Class(i::handle(map), region);
 | 
|  }
 | 
|  
 | 
|  
 | 
|  // Check this <= that.
 | 
| -bool Type::SlowIs(Type* that) {
 | 
| +template<class Config>
 | 
| +bool TypeImpl<Config>::SlowIs(TypeImpl* that) {
 | 
|    // Fast path for bitsets.
 | 
| -  if (this->is_none()) return true;
 | 
| -  if (that->is_bitset()) {
 | 
| -    return (this->LubBitset() | that->as_bitset()) == that->as_bitset();
 | 
| +  if (this->IsNone()) return true;
 | 
| +  if (that->IsBitset()) {
 | 
| +    return (this->LubBitset() | that->AsBitset()) == that->AsBitset();
 | 
|    }
 | 
|  
 | 
| -  if (that->is_class()) {
 | 
| -    return this->is_class() && *this->as_class() == *that->as_class();
 | 
| +  if (that->IsClass()) {
 | 
| +    return this->IsClass() && *this->AsClass() == *that->AsClass();
 | 
|    }
 | 
| -  if (that->is_constant()) {
 | 
| -    return this->is_constant() && *this->as_constant() == *that->as_constant();
 | 
| +  if (that->IsConstant()) {
 | 
| +    return this->IsConstant() && *this->AsConstant() == *that->AsConstant();
 | 
|    }
 | 
|  
 | 
|    // (T1 \/ ... \/ Tn) <= T  <=>  (T1 <= T) /\ ... /\ (Tn <= T)
 | 
| -  if (this->is_union()) {
 | 
| -    Handle<Unioned> unioned = this->as_union();
 | 
| +  if (this->IsUnion()) {
 | 
| +    UnionedHandle unioned = this->AsUnion();
 | 
|      for (int i = 0; i < unioned->length(); ++i) {
 | 
| -      Handle<Type> this_i = union_get(unioned, i);
 | 
| +      TypeHandle this_i = Config::union_get(unioned, i);
 | 
|        if (!this_i->Is(that)) return false;
 | 
|      }
 | 
|      return true;
 | 
| @@ -282,13 +308,13 @@ bool Type::SlowIs(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();
 | 
| +  ASSERT(!this->IsUnion());
 | 
| +  if (that->IsUnion()) {
 | 
| +    UnionedHandle unioned = that->AsUnion();
 | 
|      for (int i = 0; i < unioned->length(); ++i) {
 | 
| -      Handle<Type> that_i = union_get(unioned, i);
 | 
| +      TypeHandle that_i = Config::union_get(unioned, i);
 | 
|        if (this->Is(that_i)) return true;
 | 
| -      if (this->is_bitset()) break;  // Fast fail, no other field is a bitset.
 | 
| +      if (this->IsBitset()) break;  // Fast fail, only first field is a bitset.
 | 
|      }
 | 
|      return false;
 | 
|    }
 | 
| @@ -297,60 +323,63 @@ bool Type::SlowIs(Type* that) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| -bool Type::IsCurrently(Type* that) {
 | 
| +template<class Config>
 | 
| +bool TypeImpl<Config>::IsCurrently(TypeImpl* that) {
 | 
|    return this->Is(that) ||
 | 
| -      (this->is_constant() && that->is_class() &&
 | 
| -       this->as_constant()->IsHeapObject() &&
 | 
| -       i::HeapObject::cast(*this->as_constant())->map() == *that->as_class());
 | 
| +      (this->IsConstant() && that->IsClass() &&
 | 
| +       this->AsConstant()->IsHeapObject() &&
 | 
| +       i::HeapObject::cast(*this->AsConstant())->map() == *that->AsClass());
 | 
|  }
 | 
|  
 | 
|  
 | 
|  // Check this overlaps that.
 | 
| -bool Type::Maybe(Type* that) {
 | 
| +template<class Config>
 | 
| +bool TypeImpl<Config>::Maybe(TypeImpl* that) {
 | 
|    // Fast path for bitsets.
 | 
| -  if (this->is_bitset()) {
 | 
| -    return (this->as_bitset() & that->LubBitset()) != 0;
 | 
| +  if (this->IsBitset()) {
 | 
| +    return (this->AsBitset() & that->LubBitset()) != 0;
 | 
|    }
 | 
| -  if (that->is_bitset()) {
 | 
| -    return (this->LubBitset() & that->as_bitset()) != 0;
 | 
| +  if (that->IsBitset()) {
 | 
| +    return (this->LubBitset() & that->AsBitset()) != 0;
 | 
|    }
 | 
|  
 | 
|    // (T1 \/ ... \/ Tn) overlaps T <=> (T1 overlaps T) \/ ... \/ (Tn overlaps T)
 | 
| -  if (this->is_union()) {
 | 
| -    Handle<Unioned> unioned = this->as_union();
 | 
| +  if (this->IsUnion()) {
 | 
| +    UnionedHandle unioned = this->AsUnion();
 | 
|      for (int i = 0; i < unioned->length(); ++i) {
 | 
| -      Handle<Type> this_i = union_get(unioned, i);
 | 
| +      TypeHandle this_i = Config::union_get(unioned, i);
 | 
|        if (this_i->Maybe(that)) return true;
 | 
|      }
 | 
|      return false;
 | 
|    }
 | 
|  
 | 
|    // T overlaps (T1 \/ ... \/ Tn) <=> (T overlaps T1) \/ ... \/ (T overlaps Tn)
 | 
| -  if (that->is_union()) {
 | 
| -    Handle<Unioned> unioned = that->as_union();
 | 
| +  if (that->IsUnion()) {
 | 
| +    UnionedHandle unioned = that->AsUnion();
 | 
|      for (int i = 0; i < unioned->length(); ++i) {
 | 
| -      Handle<Type> that_i = union_get(unioned, i);
 | 
| +      TypeHandle that_i = Config::union_get(unioned, i);
 | 
|        if (this->Maybe(that_i)) return true;
 | 
|      }
 | 
|      return false;
 | 
|    }
 | 
|  
 | 
| -  ASSERT(!that->is_union());
 | 
| -  if (this->is_class()) {
 | 
| -    return that->is_class() && *this->as_class() == *that->as_class();
 | 
| +  ASSERT(!this->IsUnion() && !that->IsUnion());
 | 
| +  if (this->IsClass()) {
 | 
| +    return that->IsClass() && *this->AsClass() == *that->AsClass();
 | 
|    }
 | 
| -  if (this->is_constant()) {
 | 
| -    return that->is_constant() && *this->as_constant() == *that->as_constant();
 | 
| +  if (this->IsConstant()) {
 | 
| +    return that->IsConstant() && *this->AsConstant() == *that->AsConstant();
 | 
|    }
 | 
|  
 | 
|    return false;
 | 
|  }
 | 
|  
 | 
|  
 | 
| -bool Type::InUnion(Handle<Unioned> unioned, int current_size) {
 | 
| -  ASSERT(!this->is_union());
 | 
| +template<class Config>
 | 
| +bool TypeImpl<Config>::InUnion(UnionedHandle unioned, int current_size) {
 | 
| +  ASSERT(!this->IsUnion());
 | 
|    for (int i = 0; i < current_size; ++i) {
 | 
| -    Handle<Type> type = union_get(unioned, i);
 | 
| +    TypeHandle type = Config::union_get(unioned, i);
 | 
|      if (this->Is(type)) return true;
 | 
|    }
 | 
|    return false;
 | 
| @@ -359,17 +388,20 @@ bool Type::InUnion(Handle<Unioned> unioned, int current_size) {
 | 
|  
 | 
|  // 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) {
 | 
| +template<class Config>
 | 
| +int TypeImpl<Config>::ExtendUnion(UnionedHandle result, int current_size) {
 | 
|    int old_size = current_size;
 | 
| -  if (this->is_class() || this->is_constant()) {
 | 
| +  if (this->IsClass() || this->IsConstant()) {
 | 
|      if (!this->InUnion(result, old_size)) result->set(current_size++, this);
 | 
| -  } else if (this->is_union()) {
 | 
| -    Handle<Unioned> unioned = this->as_union();
 | 
| +  } else if (this->IsUnion()) {
 | 
| +    UnionedHandle unioned = this->AsUnion();
 | 
|      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->InUnion(result, old_size)) result->set(current_size++, *type);
 | 
| +      TypeHandle type = Config::union_get(unioned, i);
 | 
| +      ASSERT(i == 0 ||
 | 
| +             !(type->IsBitset() || type->Is(Config::union_get(unioned, 0))));
 | 
| +      if (!type->IsBitset() && !type->InUnion(result, old_size)) {
 | 
| +        result->set(current_size++, *type);
 | 
| +      }
 | 
|      }
 | 
|    }
 | 
|    return current_size;
 | 
| @@ -378,74 +410,75 @@ int Type::ExtendUnion(Handle<Unioned> result, int current_size) {
 | 
|  
 | 
|  // Union 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::Union(Handle<Type> type1, Handle<Type> type2) {
 | 
| +template<class Config>
 | 
| +typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Union(
 | 
| +    TypeHandle type1, TypeHandle type2, Region* region) {
 | 
|    // Fast case: bit sets.
 | 
| -  if (type1->is_bitset() && type2->is_bitset()) {
 | 
| -    return from_bitset(type1->as_bitset() | type2->as_bitset());
 | 
| +  if (type1->IsBitset() && type2->IsBitset()) {
 | 
| +    return Config::from_bitset(type1->AsBitset() | type2->AsBitset(), region);
 | 
|    }
 | 
|  
 | 
|    // Fast case: top or bottom types.
 | 
| -  if (type1->SameValue(Type::Any())) return *type1;
 | 
| -  if (type2->SameValue(Type::Any())) return *type2;
 | 
| -  if (type1->SameValue(Type::None())) return *type2;
 | 
| -  if (type2->SameValue(Type::None())) return *type1;
 | 
| +  if (type1->IsAny()) return type1;
 | 
| +  if (type2->IsAny()) return type2;
 | 
| +  if (type1->IsNone()) return type2;
 | 
| +  if (type2->IsNone()) return type1;
 | 
|  
 | 
|    // Semi-fast case: Unioned objects are neither involved nor produced.
 | 
| -  if (!(type1->is_union() || type2->is_union())) {
 | 
| -    if (type1->Is(type2)) return *type2;
 | 
| -    if (type2->Is(type1)) return *type1;
 | 
| +  if (!(type1->IsUnion() || type2->IsUnion())) {
 | 
| +    if (type1->Is(type2)) return type2;
 | 
| +    if (type2->Is(type1)) return type1;
 | 
|    }
 | 
|  
 | 
|    // Slow case: may need to produce a Unioned object.
 | 
| -  Isolate* isolate = NULL;
 | 
| -  int size = type1->is_bitset() || type2->is_bitset() ? 1 : 0;
 | 
| -  if (!type1->is_bitset()) {
 | 
| -    isolate = i::HeapObject::cast(*type1)->GetIsolate();
 | 
| -    size += (type1->is_union() ? type1->as_union()->length() : 1);
 | 
| +  int size = type1->IsBitset() || type2->IsBitset() ? 1 : 0;
 | 
| +  if (!type1->IsBitset()) {
 | 
| +    size += (type1->IsUnion() ? type1->AsUnion()->length() : 1);
 | 
|    }
 | 
| -  if (!type2->is_bitset()) {
 | 
| -    isolate = i::HeapObject::cast(*type2)->GetIsolate();
 | 
| -    size += (type2->is_union() ? type2->as_union()->length() : 1);
 | 
| +  if (!type2->IsBitset()) {
 | 
| +    size += (type2->IsUnion() ? type2->AsUnion()->length() : 1);
 | 
|    }
 | 
| -  ASSERT(isolate != NULL);
 | 
|    ASSERT(size >= 2);
 | 
| -  Handle<Unioned> unioned = isolate->factory()->NewFixedArray(size);
 | 
| +  UnionedHandle unioned = Config::union_create(size, region);
 | 
|    size = 0;
 | 
|  
 | 
|    int bitset = type1->GlbBitset() | type2->GlbBitset();
 | 
| -  if (bitset != kNone) unioned->set(size++, from_bitset(bitset));
 | 
| +  if (bitset != kNone) unioned->set(size++, Config::from_bitset(bitset));
 | 
|    size = type1->ExtendUnion(unioned, size);
 | 
|    size = type2->ExtendUnion(unioned, size);
 | 
|  
 | 
|    if (size == 1) {
 | 
| -    return *union_get(unioned, 0);
 | 
| +    return Config::union_get(unioned, 0);
 | 
|    } else if (size == unioned->length()) {
 | 
| -    return from_handle(unioned);
 | 
| +    return Config::from_union(unioned);
 | 
|    }
 | 
|  
 | 
|    // There was an overlap. Copy to smaller union.
 | 
| -  Handle<Unioned> result = isolate->factory()->NewFixedArray(size);
 | 
| +  UnionedHandle result = Config::union_create(size, region);
 | 
|    for (int i = 0; i < size; ++i) result->set(i, unioned->get(i));
 | 
| -  return from_handle(result);
 | 
| +  return Config::from_union(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) {
 | 
| +template<class Config>
 | 
| +int TypeImpl<Config>::ExtendIntersection(
 | 
| +    UnionedHandle result, TypeHandle that, int current_size) {
 | 
|    int old_size = current_size;
 | 
| -  if (this->is_class() || this->is_constant()) {
 | 
| +  if (this->IsClass() || this->IsConstant()) {
 | 
|      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();
 | 
| +  } else if (this->IsUnion()) {
 | 
| +    UnionedHandle unioned = this->AsUnion();
 | 
|      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))
 | 
| +      TypeHandle type = Config::union_get(unioned, i);
 | 
| +      ASSERT(i == 0 ||
 | 
| +             !(type->IsBitset() || type->Is(Config::union_get(unioned, 0))));
 | 
| +      if (!type->IsBitset() && type->Is(that) &&
 | 
| +          !type->InUnion(result, old_size)) {
 | 
|          result->set(current_size++, *type);
 | 
| +      }
 | 
|      }
 | 
|    }
 | 
|    return current_size;
 | 
| @@ -454,68 +487,60 @@ int Type::ExtendIntersection(
 | 
|  
 | 
|  // 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) {
 | 
| +template<class Config>
 | 
| +typename TypeImpl<Config>::TypeHandle TypeImpl<Config>::Intersect(
 | 
| +    TypeHandle type1, TypeHandle type2, Region* region) {
 | 
|    // Fast case: bit sets.
 | 
| -  if (type1->is_bitset() && type2->is_bitset()) {
 | 
| -    return from_bitset(type1->as_bitset() & type2->as_bitset());
 | 
| +  if (type1->IsBitset() && type2->IsBitset()) {
 | 
| +    return Config::from_bitset(type1->AsBitset() & type2->AsBitset(), region);
 | 
|    }
 | 
|  
 | 
|    // Fast case: top or bottom types.
 | 
| -  if (type1->SameValue(Type::None())) return *type1;
 | 
| -  if (type2->SameValue(Type::None())) return *type2;
 | 
| -  if (type1->SameValue(Type::Any())) return *type2;
 | 
| -  if (type2->SameValue(Type::Any())) return *type1;
 | 
| +  if (type1->IsNone()) return type1;
 | 
| +  if (type2->IsNone()) return type2;
 | 
| +  if (type1->IsAny()) return type2;
 | 
| +  if (type2->IsAny()) return type1;
 | 
|  
 | 
|    // 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;
 | 
| +  if (!(type1->IsUnion() || type2->IsUnion())) {
 | 
| +    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 = i::HeapObject::cast(*type1)->GetIsolate();
 | 
| -    size = (type1->is_union() ? type1->as_union()->length() : 2);
 | 
| +  if (!type1->IsBitset()) {
 | 
| +    size = (type1->IsUnion() ? type1->AsUnion()->length() : 2);
 | 
|    }
 | 
| -  if (!type2->is_bitset()) {
 | 
| -    isolate = i::HeapObject::cast(*type2)->GetIsolate();
 | 
| -    int size2 = (type2->is_union() ? type2->as_union()->length() : 2);
 | 
| +  if (!type2->IsBitset()) {
 | 
| +    int size2 = (type2->IsUnion() ? type2->AsUnion()->length() : 2);
 | 
|      size = (size == 0 ? size2 : Min(size, size2));
 | 
|    }
 | 
| -  ASSERT(isolate != NULL);
 | 
|    ASSERT(size >= 2);
 | 
| -  Handle<Unioned> unioned = isolate->factory()->NewFixedArray(size);
 | 
| +  UnionedHandle unioned = Config::union_create(size, region);
 | 
|    size = 0;
 | 
|  
 | 
|    int bitset = type1->GlbBitset() & type2->GlbBitset();
 | 
| -  if (bitset != kNone) unioned->set(size++, from_bitset(bitset));
 | 
| +  if (bitset != kNone) unioned->set(size++, Config::from_bitset(bitset));
 | 
|    size = type1->ExtendIntersection(unioned, type2, size);
 | 
|    size = type2->ExtendIntersection(unioned, type1, size);
 | 
|  
 | 
|    if (size == 0) {
 | 
| -    return None();
 | 
| +    return None(region);
 | 
|    } else if (size == 1) {
 | 
| -    return *union_get(unioned, 0);
 | 
| +    return Config::union_get(unioned, 0);
 | 
|    } else if (size == unioned->length()) {
 | 
| -    return from_handle(unioned);
 | 
| +    return Config::from_union(unioned);
 | 
|    }
 | 
|  
 | 
|    // There were dropped cases. Copy to smaller union.
 | 
| -  Handle<Unioned> result = isolate->factory()->NewFixedArray(size);
 | 
| +  UnionedHandle result = Config::union_create(size, region);
 | 
|    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)
 | 
| -      : Union(type, Undefined()->handle_via_isolate_of(*type));
 | 
| +  return Config::from_union(result);
 | 
|  }
 | 
|  
 | 
|  
 | 
| +// TODO(rossberg): this does not belong here.
 | 
|  Representation Representation::FromType(Handle<Type> type) {
 | 
|    if (type->Is(Type::None())) return Representation::None();
 | 
|    if (type->Is(Type::Smi())) return Representation::Smi();
 | 
| @@ -526,14 +551,16 @@ Representation Representation::FromType(Handle<Type> type) {
 | 
|  
 | 
|  
 | 
|  #ifdef OBJECT_PRINT
 | 
| -void Type::TypePrint() {
 | 
| +template<class Config>
 | 
| +void TypeImpl<Config>::TypePrint() {
 | 
|    TypePrint(stdout);
 | 
|    PrintF(stdout, "\n");
 | 
|    Flush(stdout);
 | 
|  }
 | 
|  
 | 
|  
 | 
| -const char* Type::bitset_name(int bitset) {
 | 
| +template<class Config>
 | 
| +const char* TypeImpl<Config>::bitset_name(int bitset) {
 | 
|    switch (bitset) {
 | 
|      #define PRINT_COMPOSED_TYPE(type, value) case k##type: return #type;
 | 
|      BITSET_TYPE_LIST(PRINT_COMPOSED_TYPE)
 | 
| @@ -544,9 +571,10 @@ const char* Type::bitset_name(int bitset) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| -void Type::TypePrint(FILE* out) {
 | 
| -  if (is_bitset()) {
 | 
| -    int bitset = as_bitset();
 | 
| +template<class Config>
 | 
| +void TypeImpl<Config>::TypePrint(FILE* out) {
 | 
| +  if (this->IsBitset()) {
 | 
| +    int bitset = this->AsBitset();
 | 
|      const char* name = bitset_name(bitset);
 | 
|      if (name != NULL) {
 | 
|        PrintF(out, "%s", name);
 | 
| @@ -562,19 +590,19 @@ void Type::TypePrint(FILE* out) {
 | 
|        }
 | 
|        PrintF(out, ")");
 | 
|      }
 | 
| -  } else if (is_constant()) {
 | 
| -    PrintF(out, "Constant(%p : ", static_cast<void*>(*as_constant()));
 | 
| -    from_bitset(LubBitset())->TypePrint(out);
 | 
| +  } else if (this->IsConstant()) {
 | 
| +    PrintF(out, "Constant(%p : ", static_cast<void*>(*this->AsConstant()));
 | 
| +    Config::from_bitset(this->LubBitset())->TypePrint(out);
 | 
|      PrintF(")");
 | 
| -  } else if (is_class()) {
 | 
| -    PrintF(out, "Class(%p < ", static_cast<void*>(*as_class()));
 | 
| -    from_bitset(LubBitset())->TypePrint(out);
 | 
| +  } else if (this->IsClass()) {
 | 
| +    PrintF(out, "Class(%p < ", static_cast<void*>(*this->AsClass()));
 | 
| +    Config::from_bitset(this->LubBitset())->TypePrint(out);
 | 
|      PrintF(")");
 | 
| -  } else if (is_union()) {
 | 
| +  } else if (this->IsUnion()) {
 | 
|      PrintF(out, "(");
 | 
| -    Handle<Unioned> unioned = as_union();
 | 
| +    UnionedHandle unioned = this->AsUnion();
 | 
|      for (int i = 0; i < unioned->length(); ++i) {
 | 
| -      Handle<Type> type_i = union_get(unioned, i);
 | 
| +      TypeHandle type_i = Config::union_get(unioned, i);
 | 
|        if (i > 0) PrintF(out, " | ");
 | 
|        type_i->TypePrint(out);
 | 
|      }
 | 
| @@ -584,4 +612,9 @@ void Type::TypePrint(FILE* out) {
 | 
|  #endif
 | 
|  
 | 
|  
 | 
| +template class TypeImpl<HeapTypeConfig>;
 | 
| +template class TypeImpl<HeapTypeConfig>::Iterator<i::Map>;
 | 
| +template class TypeImpl<HeapTypeConfig>::Iterator<i::Object>;
 | 
| +
 | 
| +
 | 
|  } }  // namespace v8::internal
 | 
| 
 |