| Index: src/types.h
 | 
| diff --git a/src/types.h b/src/types.h
 | 
| index 48b39335b63dcd5c4da0f468f30afd4efaa409d4..c529634ee0323f05aefc81f122733e40ed564e2a 100644
 | 
| --- a/src/types.h
 | 
| +++ b/src/types.h
 | 
| @@ -87,12 +87,17 @@ namespace internal {
 | 
|  // Consequently, do not use pointer equality for type tests, always use Is!
 | 
|  //
 | 
|  // Internally, all 'primitive' types, and their unions, are represented as
 | 
| -// bitsets via smis. Class is a heap pointer to the respective map. Only
 | 
| -// Constant's, or unions containing Class'es or Constant's, require allocation.
 | 
| +// bitsets. Class is a heap pointer to the respective map. Only Constant's, or
 | 
| +// unions containing Class'es or Constant's, currently require allocation.
 | 
|  // Note that the bitset representation is closed under both Union and Intersect.
 | 
|  //
 | 
| -// The type representation is heap-allocated, so cannot (currently) be used in
 | 
| -// a concurrent compilation context.
 | 
| +// There are two type representations, using different allocation:
 | 
| +//
 | 
| +// - class Type (zone-allocated, for compiler and concurrent compilation)
 | 
| +// - class HeapType (heap-allocated, for persistent types)
 | 
| +//
 | 
| +// Both provide the same API, and the Convert method can be used to interconvert
 | 
| +// them. For zone types, no query method touches the heap, only constructors do.
 | 
|  
 | 
|  
 | 
|  #define BITSET_TYPE_LIST(V)              \
 | 
| @@ -147,14 +152,15 @@ namespace internal {
 | 
|  //   static Handle<Unioned>::type as_union(Type*);
 | 
|  //   static Type* from_bitset(int bitset);
 | 
|  //   static Handle<Type>::type from_bitset(int bitset, Region*);
 | 
| -//   static Handle<Type>::type from_class(i::Handle<i::Map>, Region*)
 | 
| -//   static Handle<Type>::type from_constant(i::Handle<i::Object>, 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_union(Handle<Unioned>::type);
 | 
|  //   static Handle<Unioned>::type union_create(int size, Region*);
 | 
|  //   static void union_shrink(Handle<Unioned>::type, int size);
 | 
|  //   static Handle<Type>::type union_get(Handle<Unioned>::type, int);
 | 
|  //   static void union_set(Handle<Unioned>::type, int, Handle<Type>::type);
 | 
|  //   static int union_length(Handle<Unioned>::type);
 | 
| +//   static int lub_bitset(Type*);
 | 
|  // }
 | 
|  template<class Config>
 | 
|  class TypeImpl : public Config::Base {
 | 
| @@ -171,10 +177,10 @@ class TypeImpl : public Config::Base {
 | 
|    #undef DEFINE_TYPE_CONSTRUCTOR
 | 
|  
 | 
|    static TypeHandle Class(i::Handle<i::Map> map, Region* region) {
 | 
| -    return Config::from_class(map, region);
 | 
| +    return Config::from_class(map, LubBitset(*map), region);
 | 
|    }
 | 
|    static TypeHandle Constant(i::Handle<i::Object> value, Region* region) {
 | 
| -    return Config::from_constant(value, region);
 | 
| +    return Config::from_constant(value, LubBitset(*value), region);
 | 
|    }
 | 
|  
 | 
|    static TypeHandle Union(TypeHandle type1, TypeHandle type2, Region* reg);
 | 
| @@ -335,7 +341,7 @@ struct ZoneTypeConfig {
 | 
|    }
 | 
|    template<class T>
 | 
|    static void tagged_set(Tagged* tagged, int i, T value) {
 | 
| -    tagged->at(i + 1) = reinterpret_cast<T>(value);
 | 
| +    tagged->at(i + 1) = reinterpret_cast<void*>(value);
 | 
|    }
 | 
|    static int tagged_length(Tagged* tagged) {
 | 
|      return tagged->length() - 1;
 | 
| @@ -375,11 +381,11 @@ struct ZoneTypeConfig {
 | 
|    }
 | 
|    static i::Handle<i::Map> as_class(Type* type) {
 | 
|      ASSERT(is_class(type));
 | 
| -    return i::Handle<i::Map>(tagged_get<i::Map**>(as_tagged(type), 0));
 | 
| +    return i::Handle<i::Map>(tagged_get<i::Map**>(as_tagged(type), 1));
 | 
|    }
 | 
|    static i::Handle<i::Object> as_constant(Type* type) {
 | 
|      ASSERT(is_constant(type));
 | 
| -    return i::Handle<i::Object>(tagged_get<i::Object**>(as_tagged(type), 0));
 | 
| +    return i::Handle<i::Object>(tagged_get<i::Object**>(as_tagged(type), 1));
 | 
|    }
 | 
|    static Unioned* as_union(Type* type) {
 | 
|      ASSERT(is_union(type));
 | 
| @@ -399,14 +405,16 @@ struct ZoneTypeConfig {
 | 
|    static Type* from_tagged(Tagged* tagged) {
 | 
|      return reinterpret_cast<Type*>(tagged);
 | 
|    }
 | 
| -  static Type* from_class(i::Handle<i::Map> map, Zone* zone) {
 | 
| -    Tagged* tagged = tagged_create(kClassTag, 1, zone);
 | 
| -    tagged_set(tagged, 0, map.location());
 | 
| +  static Type* from_class(i::Handle<i::Map> map, int lub, Zone* zone) {
 | 
| +    Tagged* tagged = tagged_create(kClassTag, 2, zone);
 | 
| +    tagged_set(tagged, 0, lub);
 | 
| +    tagged_set(tagged, 1, map.location());
 | 
|      return from_tagged(tagged);
 | 
|    }
 | 
| -  static Type* from_constant(i::Handle<i::Object> value, Zone* zone) {
 | 
| -    Tagged* tagged = tagged_create(kConstantTag, 1, zone);
 | 
| -    tagged_set(tagged, 0, value.location());
 | 
| +  static Type* from_constant(i::Handle<i::Object> value, int lub, Zone* zone) {
 | 
| +    Tagged* tagged = tagged_create(kConstantTag, 2, zone);
 | 
| +    tagged_set(tagged, 0, lub);
 | 
| +    tagged_set(tagged, 1, value.location());
 | 
|      return from_tagged(tagged);
 | 
|    }
 | 
|    static Type* from_union(Unioned* unioned) {
 | 
| @@ -434,6 +442,10 @@ struct ZoneTypeConfig {
 | 
|    static int union_length(Unioned* unioned) {
 | 
|      return tagged_length(tagged_from_union(unioned));
 | 
|    }
 | 
| +  static int lub_bitset(Type* type) {
 | 
| +    ASSERT(is_class(type) || is_constant(type));
 | 
| +    return tagged_get<int>(as_tagged(type), 0);
 | 
| +  }
 | 
|  };
 | 
|  
 | 
|  
 | 
| @@ -475,11 +487,12 @@ struct HeapTypeConfig {
 | 
|    static i::Handle<Type> from_bitset(int bitset, Isolate* isolate) {
 | 
|      return i::handle(from_bitset(bitset), isolate);
 | 
|    }
 | 
| -  static i::Handle<Type> from_class(i::Handle<i::Map> map, Isolate* isolate) {
 | 
| +  static i::Handle<Type> from_class(
 | 
| +      i::Handle<i::Map> map, int lub, Isolate* isolate) {
 | 
|      return i::Handle<Type>::cast(i::Handle<Object>::cast(map));
 | 
|    }
 | 
|    static i::Handle<Type> from_constant(
 | 
| -      i::Handle<i::Object> value, Isolate* isolate) {
 | 
| +      i::Handle<i::Object> value, int lub, Isolate* isolate) {
 | 
|      i::Handle<Box> box = isolate->factory()->NewBox(value);
 | 
|      return i::Handle<Type>::cast(i::Handle<Object>::cast(box));
 | 
|    }
 | 
| @@ -506,6 +519,9 @@ struct HeapTypeConfig {
 | 
|    static int union_length(i::Handle<Unioned> unioned) {
 | 
|      return unioned->length();
 | 
|    }
 | 
| +  static int lub_bitset(Type* type) {
 | 
| +    return 0;  // kNone, which causes recomputation.
 | 
| +  }
 | 
|  };
 | 
|  
 | 
|  typedef TypeImpl<ZoneTypeConfig> Type;
 | 
| 
 |