Revert "Revert "Upgrade to 5.0.71.48"" DO NOT MERGE

This reverts commit f2e3994fa5148cc3d9946666f0b0596290192b0e,
and updates the x64 makefile properly so it doesn't break that
build.

FPIIM-449

Change-Id: Ib83e35bfbae6af627451c926a9650ec57c045605
(cherry picked from commit 109988c7ccb6f3fd1a58574fa3dfb88beaef6632)
diff --git a/src/types.h b/src/types.h
index 9ce650d..9984ad8 100644
--- a/src/types.h
+++ b/src/types.h
@@ -143,14 +143,6 @@
 // bitsets. Bit 0 is reserved for tagging. Class is a heap pointer to the
 // respective map. Only structured types require allocation.
 // Note that the bitset representation is closed under both Union and Intersect.
-//
-// 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.
 
 
 // -----------------------------------------------------------------------------
@@ -159,20 +151,21 @@
 // clang-format off
 
 #define MASK_BITSET_TYPE_LIST(V) \
-  V(Representation, 0xff800000u) \
-  V(Semantic,       0x007ffffeu)
+  V(Representation, 0xffc00000u) \
+  V(Semantic,       0x003ffffeu)
 
 #define REPRESENTATION(k) ((k) & BitsetType::kRepresentation)
 #define SEMANTIC(k)       ((k) & BitsetType::kSemantic)
 
 #define REPRESENTATION_BITSET_TYPE_LIST(V)    \
   V(None,               0)                    \
-  V(UntaggedBit,        1u << 23 | kSemantic) \
-  V(UntaggedIntegral8,  1u << 24 | kSemantic) \
-  V(UntaggedIntegral16, 1u << 25 | kSemantic) \
-  V(UntaggedIntegral32, 1u << 26 | kSemantic) \
-  V(UntaggedFloat32,    1u << 27 | kSemantic) \
-  V(UntaggedFloat64,    1u << 28 | kSemantic) \
+  V(UntaggedBit,        1u << 22 | kSemantic) \
+  V(UntaggedIntegral8,  1u << 23 | kSemantic) \
+  V(UntaggedIntegral16, 1u << 24 | kSemantic) \
+  V(UntaggedIntegral32, 1u << 25 | kSemantic) \
+  V(UntaggedFloat32,    1u << 26 | kSemantic) \
+  V(UntaggedFloat64,    1u << 27 | kSemantic) \
+  V(UntaggedSimd128,    1u << 28 | kSemantic) \
   V(UntaggedPointer,    1u << 29 | kSemantic) \
   V(TaggedSigned,       1u << 30 | kSemantic) \
   V(TaggedPointer,      1u << 31 | kSemantic) \
@@ -267,400 +260,27 @@
   INTERNAL_BITSET_TYPE_LIST(V)       \
   SEMANTIC_BITSET_TYPE_LIST(V)
 
-
-// -----------------------------------------------------------------------------
-// The abstract Type class, parameterized over the low-level representation.
-
-// struct Config {
-//   typedef TypeImpl<Config> Type;
-//   typedef Base;
-//   typedef Struct;
-//   typedef Range;
-//   typedef Region;
-//   template<class> struct Handle { typedef type; }  // No template typedefs...
-//
-//   template<class T> static Handle<T>::type null_handle();
-//   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_struct(Type*, int tag);
-//   static bool is_range(Type*);
-//
-//   static bitset as_bitset(Type*);
-//   static i::Handle<i::Map> as_class(Type*);
-//   static Handle<Struct>::type as_struct(Type*);
-//   static Handle<Range>::type as_range(Type*);
-//
-//   static Type* from_bitset(bitset);
-//   static Handle<Type>::type from_bitset(bitset, Region*);
-//   static Handle<Type>::type from_class(i::Handle<Map>, Region*);
-//   static Handle<Type>::type from_struct(Handle<Struct>::type, int tag);
-//   static Handle<Type>::type from_range(Handle<Range>::type);
-//
-//   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);
-//   static int struct_length(Handle<Struct>::type);
-//   static Handle<Type>::type struct_get(Handle<Struct>::type, int);
-//   static void struct_set(Handle<Struct>::type, int, Handle<Type>::type);
-//   template<class V>
-//   static i::Handle<V> struct_get_value(Handle<Struct>::type, int);
-//   template<class V>
-//   static void struct_set_value(Handle<Struct>::type, int, i::Handle<V>);
-//
-//   static Handle<Range>::type range_create(Region*);
-//   static int range_get_bitset(Handle<Range>::type);
-//   static void range_set_bitset(Handle<Range>::type, int);
-//   static double range_get_double(Handle<Range>::type, int);
-//   static void range_set_double(Handle<Range>::type, int, double, Region*);
-// }
-template<class Config>
-class TypeImpl : public Config::Base {
- public:
-  // Auxiliary types.
-
-  typedef uint32_t bitset;  // Internal
-  class BitsetType;         // Internal
-  class StructuralType;     // Internal
-  class UnionType;          // Internal
-
-  class ClassType;
-  class ConstantType;
-  class RangeType;
-  class ContextType;
-  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<RangeType>::type RangeHandle;
-  typedef typename Config::template Handle<ContextType>::type ContextHandle;
-  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;
-
-  // Constructors.
-
-  #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);                    \
-    }
-  PROPER_BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR)
-  #undef DEFINE_TYPE_CONSTRUCTOR
-
-  static TypeImpl* SignedSmall() {
-    return BitsetType::New(BitsetType::SignedSmall());
-  }
-  static TypeHandle SignedSmall(Region* region) {
-    return BitsetType::New(BitsetType::SignedSmall(), region);
-  }
-  static TypeImpl* UnsignedSmall() {
-    return BitsetType::New(BitsetType::UnsignedSmall());
-  }
-  static TypeHandle UnsignedSmall(Region* region) {
-    return BitsetType::New(BitsetType::UnsignedSmall(), region);
-  }
-
-  static TypeHandle Class(i::Handle<i::Map> map, Region* region) {
-    return ClassType::New(map, region);
-  }
-  static TypeHandle Constant(i::Handle<i::Object> value, Region* region) {
-    return ConstantType::New(value, region);
-  }
-  static TypeHandle Range(double min, double max, Region* region) {
-    return RangeType::New(
-        min, max, BitsetType::New(REPRESENTATION(BitsetType::kTagged |
-                                                 BitsetType::kUntaggedNumber),
-                                  region),
-        region);
-  }
-  static TypeHandle Context(TypeHandle outer, Region* region) {
-    return ContextType::New(outer, 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 Function(
-      TypeHandle result, TypeHandle param0, TypeHandle param1,
-      TypeHandle param2, Region* region) {
-    FunctionHandle function = Function(result, Any(region), 3, region);
-    function->InitParameter(0, param0);
-    function->InitParameter(1, param1);
-    function->InitParameter(2, param2);
-    return function;
-  }
-  static TypeHandle Function(TypeHandle result, int arity, TypeHandle* params,
-                             Region* region) {
-    FunctionHandle function = Function(result, Any(region), arity, region);
-    for (int i = 0; i < arity; ++i) {
-      function->InitParameter(i, params[i]);
-    }
-    return function;
-  }
-
-#define CONSTRUCT_SIMD_TYPE(NAME, Name, name, lane_count, lane_type) \
-  static TypeHandle Name(Isolate* isolate, Region* region);
-  SIMD128_TYPES(CONSTRUCT_SIMD_TYPE)
-#undef CONSTRUCT_SIMD_TYPE
-
-  static TypeHandle Union(TypeHandle type1, TypeHandle type2, Region* reg);
-  static TypeHandle Intersect(TypeHandle type1, TypeHandle type2, Region* reg);
-
-  static TypeHandle Of(double value, Region* region) {
-    return Config::from_bitset(BitsetType::ExpandInternals(
-        BitsetType::Lub(value)), region);
-  }
-  static TypeHandle Of(i::Object* value, Region* region) {
-    return Config::from_bitset(BitsetType::ExpandInternals(
-        BitsetType::Lub(value)), region);
-  }
-  static TypeHandle Of(i::Handle<i::Object> value, Region* region) {
-    return Of(*value, region);
-  }
-
-  // Extraction of components.
-  static TypeHandle Representation(TypeHandle t, Region* region);
-  static TypeHandle Semantic(TypeHandle t, Region* region);
-
-  // Predicates.
-  bool IsInhabited() { return BitsetType::IsInhabited(this->BitsetLub()); }
-
-  bool Is(TypeImpl* that) { return this == that || this->SlowIs(that); }
-  template<class TypeHandle>
-  bool Is(TypeHandle that) { return this->Is(*that); }
-
-  bool Maybe(TypeImpl* that);
-  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(val)->Is(this), but avoiding allocation.
-  bool Contains(i::Object* val);
-  bool Contains(i::Handle<i::Object> val) { return this->Contains(*val); }
-
-  // State-dependent versions of the above that consider subtyping between
-  // a constant and its map class.
-  inline static TypeHandle NowOf(i::Object* value, Region* region);
-  static TypeHandle NowOf(i::Handle<i::Object> value, Region* region) {
-    return NowOf(*value, region);
-  }
-  bool NowIs(TypeImpl* that);
-  template<class TypeHandle>
-  bool NowIs(TypeHandle that)  { return this->NowIs(*that); }
-  inline bool NowContains(i::Object* val);
-  bool NowContains(i::Handle<i::Object> val) { return this->NowContains(*val); }
-
-  bool NowStable();
-
-  // Inspection.
-
-  bool IsRange() { return Config::is_range(this); }
-  bool IsClass() {
-    return Config::is_class(this)
-        || Config::is_struct(this, StructuralType::kClassTag);
-  }
-  bool IsConstant() {
-    return Config::is_struct(this, StructuralType::kConstantTag);
-  }
-  bool IsContext() {
-    return Config::is_struct(this, StructuralType::kContextTag);
-  }
-  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); }
-  RangeType* AsRange() { return RangeType::cast(this); }
-  ContextType* AsContext() { return ContextType::cast(this); }
-  ArrayType* AsArray() { return ArrayType::cast(this); }
-  FunctionType* AsFunction() { return FunctionType::cast(this); }
-
-  // Minimum and maximum of a numeric type.
-  // These functions do not distinguish between -0 and +0.  If the type equals
-  // kNaN, they return NaN; otherwise kNaN is ignored.  Only call these
-  // functions on subtypes of Number.
-  double Min();
-  double Max();
-
-  // Extracts a range from the type: if the type is a range or a union
-  // containing a range, that range is returned; otherwise, NULL is returned.
-  RangeType* GetRange();
-
-  static bool IsInteger(double x) {
-    return nearbyint(x) == x && !i::IsMinusZero(x);  // Allows for infinities.
-  }
-  static bool IsInteger(i::Object* x) {
-    return x->IsNumber() && IsInteger(x->Number());
-  }
-
-  int NumClasses();
-  int NumConstants();
-
-  template<class T> class Iterator;
-  Iterator<i::Map> Classes() {
-    if (this->IsBitset()) return Iterator<i::Map>();
-    return Iterator<i::Map>(Config::handle(this));
-  }
-  Iterator<i::Object> Constants() {
-    if (this->IsBitset()) return Iterator<i::Object>();
-    return Iterator<i::Object>(Config::handle(this));
-  }
-
-  // Casting and conversion.
-
-  static inline TypeImpl* cast(typename Config::Base* object);
-
-  template<class OtherTypeImpl>
-  static TypeHandle Convert(
-      typename OtherTypeImpl::TypeHandle type, Region* region);
-
-  // Printing.
-
-  enum PrintDimension { BOTH_DIMS, SEMANTIC_DIM, REPRESENTATION_DIM };
-
-  void PrintTo(std::ostream& os, PrintDimension dim = BOTH_DIMS);  // NOLINT
-
-#ifdef DEBUG
-  void Print();
-#endif
-
-  bool IsUnionForTesting() { return IsUnion(); }
-
- protected:
-  // Friends.
-
-  template<class> friend class Iterator;
-  template<class> friend class TypeImpl;
-
-  // Handle conversion.
-
-  template<class T>
-  static typename Config::template Handle<T>::type handle(T* type) {
-    return Config::handle(type);
-  }
-  TypeImpl* unhandle() { return this; }
-
-  // Internal inspection.
-
-  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); }
-
-  bitset AsBitset() {
-    DCHECK(this->IsBitset());
-    return static_cast<BitsetType*>(this)->Bitset();
-  }
-  UnionType* AsUnion() { return UnionType::cast(this); }
-
-  bitset Representation();
-
-  // Auxiliary functions.
-  bool SemanticMaybe(TypeImpl* that);
-
-  bitset BitsetGlb() { return BitsetType::Glb(this); }
-  bitset BitsetLub() { return BitsetType::Lub(this); }
-
-  bool SlowIs(TypeImpl* that);
-  bool SemanticIs(TypeImpl* that);
-
-  struct Limits {
-    double min;
-    double max;
-    Limits(double min, double max) : min(min), max(max) {}
-    explicit Limits(RangeType* range) : min(range->Min()), max(range->Max()) {}
-    bool IsEmpty();
-    static Limits Empty() { return Limits(1, 0); }
-    static Limits Intersect(Limits lhs, Limits rhs);
-    static Limits Union(Limits lhs, Limits rhs);
-  };
-
-  static bool Overlap(RangeType* lhs, RangeType* rhs);
-  static bool Contains(RangeType* lhs, RangeType* rhs);
-  static bool Contains(RangeType* range, ConstantType* constant);
-  static bool Contains(RangeType* range, i::Object* val);
-
-  static int UpdateRange(
-      RangeHandle type, UnionHandle result, int size, Region* region);
-
-  static Limits IntersectRangeAndBitset(TypeHandle range, TypeHandle bits,
-                                        Region* region);
-  static Limits ToLimits(bitset bits, Region* region);
-
-  bool SimplyEquals(TypeImpl* that);
-  template<class TypeHandle>
-  bool SimplyEquals(TypeHandle that) { return this->SimplyEquals(*that); }
-
-  static int AddToUnion(
-      TypeHandle type, UnionHandle result, int size, Region* region);
-  static int IntersectAux(TypeHandle type, TypeHandle other, UnionHandle result,
-                          int size, Limits* limits, Region* region);
-  static TypeHandle NormalizeUnion(UnionHandle unioned, int size,
-                                   Region* region);
-  static TypeHandle NormalizeRangeAndBitset(RangeHandle range, bitset* bits,
-                                            Region* region);
-};
-
+class Type;
 
 // -----------------------------------------------------------------------------
 // Bitset types (internal).
 
-template<class Config>
-class TypeImpl<Config>::BitsetType : public TypeImpl<Config> {
- protected:
-  friend class TypeImpl<Config>;
+class BitsetType {
+ public:
+  typedef uint32_t bitset;  // Internal
 
   enum : uint32_t {
-    #define DECLARE_TYPE(type, value) k##type = (value),
+#define DECLARE_TYPE(type, value) k##type = (value),
     BITSET_TYPE_LIST(DECLARE_TYPE)
-    #undef DECLARE_TYPE
-    kUnusedEOL = 0
+#undef DECLARE_TYPE
+        kUnusedEOL = 0
   };
 
   static bitset SignedSmall();
   static bitset UnsignedSmall();
 
-  bitset Bitset() { return Config::as_bitset(this); }
-
-  static TypeImpl* New(bitset bits) {
-    return Config::from_bitset(bits);
-  }
-  static TypeHandle New(bitset bits, Region* region) {
-    return Config::from_bitset(bits, region);
+  bitset Bitset() {
+    return static_cast<bitset>(reinterpret_cast<uintptr_t>(this) ^ 1u);
   }
 
   static bool IsInhabited(bitset bits) {
@@ -678,9 +298,9 @@
   static double Min(bitset);
   static double Max(bitset);
 
-  static bitset Glb(TypeImpl* type);  // greatest lower bound that's a bitset
+  static bitset Glb(Type* type);  // greatest lower bound that's a bitset
   static bitset Glb(double min, double max);
-  static bitset Lub(TypeImpl* type);  // least upper bound that's a bitset
+  static bitset Lub(Type* type);  // least upper bound that's a bitset
   static bitset Lub(i::Map* map);
   static bitset Lub(i::Object* value);
   static bitset Lub(double value);
@@ -695,7 +315,19 @@
 
   static bitset NumberBits(bitset bits);
 
+  static bool IsBitset(Type* type) {
+    return reinterpret_cast<uintptr_t>(type) & 1;
+  }
+
+  static Type* NewForTesting(bitset bits) { return New(bits); }
+
  private:
+  friend class Type;
+
+  static Type* New(bitset bits) {
+    return reinterpret_cast<Type*>(static_cast<uintptr_t>(bits | 1u));
+  }
+
   struct Boundary {
     bitset internal;
     bitset external;
@@ -706,57 +338,302 @@
   static inline size_t BoundariesSize();
 };
 
-
 // -----------------------------------------------------------------------------
 // Superclass for non-bitset types (internal).
-// Contains a tag and a variable number of type or value fields.
-
-template<class Config>
-class TypeImpl<Config>::StructuralType : public TypeImpl<Config> {
+class TypeBase {
  protected:
-  template<class> friend class TypeImpl;
-  friend struct ZoneTypeConfig;  // For tags.
-  friend struct HeapTypeConfig;
+  friend class Type;
 
-  enum Tag {
-    kClassTag,
-    kConstantTag,
-    kContextTag,
-    kArrayTag,
-    kFunctionTag,
-    kUnionTag
+  enum Kind {
+    kClass,
+    kConstant,
+    kContext,
+    kArray,
+    kFunction,
+    kTuple,
+    kUnion,
+    kRange
   };
 
-  int Length() {
-    return Config::struct_length(Config::as_struct(this));
-  }
-  TypeHandle Get(int i) {
-    DCHECK(0 <= i && i < this->Length());
-    return Config::struct_get(Config::as_struct(this), i);
-  }
-  void Set(int i, TypeHandle type) {
-    DCHECK(0 <= i && i < this->Length());
-    Config::struct_set(Config::as_struct(this), i, type);
-  }
-  void Shrink(int length) {
-    DCHECK(2 <= length && length <= this->Length());
-    Config::struct_shrink(Config::as_struct(this), length);
-  }
-  template<class V> i::Handle<V> GetValue(int i) {
-    DCHECK(0 <= i && i < this->Length());
-    return Config::template struct_get_value<V>(Config::as_struct(this), i);
-  }
-  template<class V> void SetValue(int i, i::Handle<V> x) {
-    DCHECK(0 <= i && i < this->Length());
-    Config::struct_set_value(Config::as_struct(this), i, x);
+  Kind kind() const { return kind_; }
+  explicit TypeBase(Kind kind) : kind_(kind) {}
+
+  static bool IsKind(Type* type, Kind kind) {
+    if (BitsetType::IsBitset(type)) return false;
+    TypeBase* base = reinterpret_cast<TypeBase*>(type);
+    return base->kind() == kind;
   }
 
-  static TypeHandle New(Tag tag, int length, Region* region) {
-    DCHECK(1 <= length);
-    return Config::from_struct(Config::struct_create(tag, length, region));
+  // The hacky conversion to/from Type*.
+  static Type* AsType(TypeBase* type) { return reinterpret_cast<Type*>(type); }
+  static TypeBase* FromType(Type* type) {
+    return reinterpret_cast<TypeBase*>(type);
+  }
+
+ private:
+  Kind kind_;
+};
+
+// -----------------------------------------------------------------------------
+// Class types.
+
+class ClassType : public TypeBase {
+ public:
+  i::Handle<i::Map> Map() { return map_; }
+
+ private:
+  friend class Type;
+  friend class BitsetType;
+
+  static Type* New(i::Handle<i::Map> map, Zone* zone) {
+    return AsType(new (zone->New(sizeof(ClassType)))
+                      ClassType(BitsetType::Lub(*map), map));
+  }
+
+  static ClassType* cast(Type* type) {
+    DCHECK(IsKind(type, kClass));
+    return static_cast<ClassType*>(FromType(type));
+  }
+
+  ClassType(BitsetType::bitset bitset, i::Handle<i::Map> map)
+      : TypeBase(kClass), bitset_(bitset), map_(map) {}
+
+  BitsetType::bitset Lub() { return bitset_; }
+
+  BitsetType::bitset bitset_;
+  Handle<i::Map> map_;
+};
+
+// -----------------------------------------------------------------------------
+// Constant types.
+
+class ConstantType : public TypeBase {
+ public:
+  i::Handle<i::Object> Value() { return object_; }
+
+ private:
+  friend class Type;
+  friend class BitsetType;
+
+  static Type* New(i::Handle<i::Object> value, Zone* zone) {
+    BitsetType::bitset bitset = BitsetType::Lub(*value);
+    return AsType(new (zone->New(sizeof(ConstantType)))
+                      ConstantType(bitset, value));
+  }
+
+  static ConstantType* cast(Type* type) {
+    DCHECK(IsKind(type, kConstant));
+    return static_cast<ConstantType*>(FromType(type));
+  }
+
+  ConstantType(BitsetType::bitset bitset, i::Handle<i::Object> object)
+      : TypeBase(kConstant), bitset_(bitset), object_(object) {}
+
+  BitsetType::bitset Lub() { return bitset_; }
+
+  BitsetType::bitset bitset_;
+  Handle<i::Object> object_;
+};
+// TODO(neis): Also cache value if numerical.
+// TODO(neis): Allow restricting the representation.
+
+// -----------------------------------------------------------------------------
+// Range types.
+
+class RangeType : public TypeBase {
+ public:
+  struct Limits {
+    double min;
+    double max;
+    Limits(double min, double max) : min(min), max(max) {}
+    explicit Limits(RangeType* range) : min(range->Min()), max(range->Max()) {}
+    bool IsEmpty();
+    static Limits Empty() { return Limits(1, 0); }
+    static Limits Intersect(Limits lhs, Limits rhs);
+    static Limits Union(Limits lhs, Limits rhs);
+  };
+
+  double Min() { return limits_.min; }
+  double Max() { return limits_.max; }
+
+ private:
+  friend class Type;
+  friend class BitsetType;
+  friend class UnionType;
+
+  static Type* New(double min, double max, BitsetType::bitset representation,
+                   Zone* zone) {
+    return New(Limits(min, max), representation, zone);
+  }
+
+  static bool IsInteger(double x) {
+    return nearbyint(x) == x && !i::IsMinusZero(x);  // Allows for infinities.
+  }
+
+  static Type* New(Limits lim, BitsetType::bitset representation, Zone* zone) {
+    DCHECK(IsInteger(lim.min) && IsInteger(lim.max));
+    DCHECK(lim.min <= lim.max);
+    DCHECK(REPRESENTATION(representation) == representation);
+    BitsetType::bitset bits =
+        SEMANTIC(BitsetType::Lub(lim.min, lim.max)) | representation;
+
+    return AsType(new (zone->New(sizeof(RangeType))) RangeType(bits, lim));
+  }
+
+  static RangeType* cast(Type* type) {
+    DCHECK(IsKind(type, kRange));
+    return static_cast<RangeType*>(FromType(type));
+  }
+
+  RangeType(BitsetType::bitset bitset, Limits limits)
+      : TypeBase(kRange), bitset_(bitset), limits_(limits) {}
+
+  BitsetType::bitset Lub() { return bitset_; }
+
+  BitsetType::bitset bitset_;
+  Limits limits_;
+};
+
+// -----------------------------------------------------------------------------
+// Context types.
+
+class ContextType : public TypeBase {
+ public:
+  Type* Outer() { return outer_; }
+
+ private:
+  friend class Type;
+
+  static Type* New(Type* outer, Zone* zone) {
+    return AsType(new (zone->New(sizeof(ContextType))) ContextType(outer));
+  }
+
+  static ContextType* cast(Type* type) {
+    DCHECK(IsKind(type, kContext));
+    return static_cast<ContextType*>(FromType(type));
+  }
+
+  explicit ContextType(Type* outer) : TypeBase(kContext), outer_(outer) {}
+
+  Type* outer_;
+};
+
+// -----------------------------------------------------------------------------
+// Array types.
+
+class ArrayType : public TypeBase {
+ public:
+  Type* Element() { return element_; }
+
+ private:
+  friend class Type;
+
+  explicit ArrayType(Type* element) : TypeBase(kArray), element_(element) {}
+
+  static Type* New(Type* element, Zone* zone) {
+    return AsType(new (zone->New(sizeof(ArrayType))) ArrayType(element));
+  }
+
+  static ArrayType* cast(Type* type) {
+    DCHECK(IsKind(type, kArray));
+    return static_cast<ArrayType*>(FromType(type));
+  }
+
+  Type* element_;
+};
+
+// -----------------------------------------------------------------------------
+// Superclass for types with variable number of type fields.
+class StructuralType : public TypeBase {
+ public:
+  int LengthForTesting() { return Length(); }
+
+ protected:
+  friend class Type;
+
+  int Length() { return length_; }
+
+  Type* Get(int i) {
+    DCHECK(0 <= i && i < this->Length());
+    return elements_[i];
+  }
+
+  void Set(int i, Type* type) {
+    DCHECK(0 <= i && i < this->Length());
+    elements_[i] = type;
+  }
+
+  void Shrink(int length) {
+    DCHECK(2 <= length && length <= this->Length());
+    length_ = length;
+  }
+
+  StructuralType(Kind kind, int length, i::Zone* zone)
+      : TypeBase(kind), length_(length) {
+    elements_ = reinterpret_cast<Type**>(zone->New(sizeof(Type*) * length));
+  }
+
+ private:
+  int length_;
+  Type** elements_;
+};
+
+// -----------------------------------------------------------------------------
+// Function types.
+
+class FunctionType : public StructuralType {
+ public:
+  int Arity() { return this->Length() - 2; }
+  Type* Result() { return this->Get(0); }
+  Type* Receiver() { return this->Get(1); }
+  Type* Parameter(int i) { return this->Get(2 + i); }
+
+  void InitParameter(int i, Type* type) { this->Set(2 + i, type); }
+
+ private:
+  friend class Type;
+
+  FunctionType(Type* result, Type* receiver, int arity, Zone* zone)
+      : StructuralType(kFunction, 2 + arity, zone) {
+    Set(0, result);
+    Set(1, receiver);
+  }
+
+  static Type* New(Type* result, Type* receiver, int arity, Zone* zone) {
+    return AsType(new (zone->New(sizeof(FunctionType)))
+                      FunctionType(result, receiver, arity, zone));
+  }
+
+  static FunctionType* cast(Type* type) {
+    DCHECK(IsKind(type, kFunction));
+    return static_cast<FunctionType*>(FromType(type));
   }
 };
 
+// -----------------------------------------------------------------------------
+// Tuple types.
+
+class TupleType : public StructuralType {
+ public:
+  int Arity() { return this->Length(); }
+  Type* Element(int i) { return this->Get(i); }
+
+  void InitElement(int i, Type* type) { this->Set(i, type); }
+
+ private:
+  friend class Type;
+
+  TupleType(int length, Zone* zone) : StructuralType(kTuple, length, zone) {}
+
+  static Type* New(int length, Zone* zone) {
+    return AsType(new (zone->New(sizeof(TupleType))) TupleType(length, zone));
+  }
+
+  static TupleType* cast(Type* type) {
+    DCHECK(IsKind(type, kTuple));
+    return static_cast<TupleType*>(FromType(type));
+  }
+};
 
 // -----------------------------------------------------------------------------
 // Union types (internal).
@@ -765,420 +642,329 @@
 // - at most one field is a bitset, and it must go into index 0
 // - no field is a union
 // - no field is a subtype of any other field
-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));
+class UnionType : public StructuralType {
+ private:
+  friend Type;
+  friend BitsetType;
+
+  UnionType(int length, Zone* zone) : StructuralType(kUnion, length, zone) {}
+
+  static Type* New(int length, Zone* zone) {
+    return AsType(new (zone->New(sizeof(UnionType))) UnionType(length, zone));
   }
 
-  static UnionType* cast(TypeImpl* type) {
-    DCHECK(type->IsUnion());
-    return static_cast<UnionType*>(type);
+  static UnionType* cast(Type* type) {
+    DCHECK(IsKind(type, kUnion));
+    return static_cast<UnionType*>(FromType(type));
   }
 
   bool Wellformed();
 };
 
-
-// -----------------------------------------------------------------------------
-// Class types.
-
-template<class Config>
-class TypeImpl<Config>::ClassType : public StructuralType {
+class Type {
  public:
-  i::Handle<i::Map> Map() {
-    return Config::is_class(this) ? Config::as_class(this) :
-        this->template GetValue<i::Map>(1);
+  typedef BitsetType::bitset bitset;  // Internal
+
+// Constructors.
+#define DEFINE_TYPE_CONSTRUCTOR(type, value) \
+  static Type* type() { return BitsetType::New(BitsetType::k##type); }
+  PROPER_BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR)
+#undef DEFINE_TYPE_CONSTRUCTOR
+
+  static Type* SignedSmall() {
+    return BitsetType::New(BitsetType::SignedSmall());
+  }
+  static Type* UnsignedSmall() {
+    return BitsetType::New(BitsetType::UnsignedSmall());
   }
 
-  static ClassHandle New(i::Handle<i::Map> map, Region* region) {
-    ClassHandle type =
-        Config::template cast<ClassType>(Config::from_class(map, region));
-    if (!type->IsClass()) {
-      type = Config::template cast<ClassType>(
-          StructuralType::New(StructuralType::kClassTag, 2, region));
-      type->Set(0, BitsetType::New(BitsetType::Lub(*map), region));
-      type->SetValue(1, map);
+  static Type* Class(i::Handle<i::Map> map, Zone* zone) {
+    return ClassType::New(map, zone);
+  }
+  static Type* Constant(i::Handle<i::Object> value, Zone* zone) {
+    return ConstantType::New(value, zone);
+  }
+  static Type* Range(double min, double max, Zone* zone) {
+    return RangeType::New(min, max, REPRESENTATION(BitsetType::kTagged |
+                                                   BitsetType::kUntaggedNumber),
+                          zone);
+  }
+  static Type* Context(Type* outer, Zone* zone) {
+    return ContextType::New(outer, zone);
+  }
+  static Type* Array(Type* element, Zone* zone) {
+    return ArrayType::New(element, zone);
+  }
+  static Type* Function(Type* result, Type* receiver, int arity, Zone* zone) {
+    return FunctionType::New(result, receiver, arity, zone);
+  }
+  static Type* Function(Type* result, Zone* zone) {
+    return Function(result, Any(), 0, zone);
+  }
+  static Type* Function(Type* result, Type* param0, Zone* zone) {
+    Type* function = Function(result, Any(), 1, zone);
+    function->AsFunction()->InitParameter(0, param0);
+    return function;
+  }
+  static Type* Function(Type* result, Type* param0, Type* param1, Zone* zone) {
+    Type* function = Function(result, Any(), 2, zone);
+    function->AsFunction()->InitParameter(0, param0);
+    function->AsFunction()->InitParameter(1, param1);
+    return function;
+  }
+  static Type* Function(Type* result, Type* param0, Type* param1, Type* param2,
+                        Zone* zone) {
+    Type* function = Function(result, Any(), 3, zone);
+    function->AsFunction()->InitParameter(0, param0);
+    function->AsFunction()->InitParameter(1, param1);
+    function->AsFunction()->InitParameter(2, param2);
+    return function;
+  }
+  static Type* Function(Type* result, int arity, Type** params, Zone* zone) {
+    Type* function = Function(result, Any(), arity, zone);
+    for (int i = 0; i < arity; ++i) {
+      function->AsFunction()->InitParameter(i, params[i]);
     }
-    return type;
+    return function;
+  }
+  static Type* Tuple(Type* first, Type* second, Type* third, Zone* zone) {
+    Type* tuple = TupleType::New(3, zone);
+    tuple->AsTuple()->InitElement(0, first);
+    tuple->AsTuple()->InitElement(1, second);
+    tuple->AsTuple()->InitElement(2, third);
+    return tuple;
   }
 
-  static ClassType* cast(TypeImpl* type) {
-    DCHECK(type->IsClass());
-    return static_cast<ClassType*>(type);
+#define CONSTRUCT_SIMD_TYPE(NAME, Name, name, lane_count, lane_type) \
+  static Type* Name(Isolate* isolate, Zone* zone);
+  SIMD128_TYPES(CONSTRUCT_SIMD_TYPE)
+#undef CONSTRUCT_SIMD_TYPE
+
+  static Type* Union(Type* type1, Type* type2, Zone* reg);
+  static Type* Intersect(Type* type1, Type* type2, Zone* reg);
+
+  static Type* Of(double value, Zone* zone) {
+    return BitsetType::New(BitsetType::ExpandInternals(BitsetType::Lub(value)));
+  }
+  static Type* Of(i::Object* value, Zone* zone) {
+    return BitsetType::New(BitsetType::ExpandInternals(BitsetType::Lub(value)));
+  }
+  static Type* Of(i::Handle<i::Object> value, Zone* zone) {
+    return Of(*value, zone);
   }
 
- private:
-  template<class> friend class TypeImpl;
-  bitset Lub() {
-    return Config::is_class(this) ?
-        BitsetType::Lub(*Config::as_class(this)) :
-        this->Get(0)->AsBitset();
+  // Extraction of components.
+  static Type* Representation(Type* t, Zone* zone);
+  static Type* Semantic(Type* t, Zone* zone);
+
+  // Predicates.
+  bool IsInhabited() { return BitsetType::IsInhabited(this->BitsetLub()); }
+
+  bool Is(Type* that) { return this == that || this->SlowIs(that); }
+  bool Maybe(Type* that);
+  bool Equals(Type* that) { return this->Is(that) && that->Is(this); }
+
+  // Equivalent to Constant(val)->Is(this), but avoiding allocation.
+  bool Contains(i::Object* val);
+  bool Contains(i::Handle<i::Object> val) { return this->Contains(*val); }
+
+  // State-dependent versions of the above that consider subtyping between
+  // a constant and its map class.
+  static Type* NowOf(i::Object* value, Zone* zone);
+  static Type* NowOf(i::Handle<i::Object> value, Zone* zone) {
+    return NowOf(*value, zone);
   }
-};
+  bool NowIs(Type* that);
+  bool NowContains(i::Object* val);
+  bool NowContains(i::Handle<i::Object> val) { return this->NowContains(*val); }
 
+  bool NowStable();
 
-// -----------------------------------------------------------------------------
-// Constant types.
+  // Inspection.
+  bool IsRange() { return IsKind(TypeBase::kRange); }
+  bool IsClass() { return IsKind(TypeBase::kClass); }
+  bool IsConstant() { return IsKind(TypeBase::kConstant); }
+  bool IsContext() { return IsKind(TypeBase::kContext); }
+  bool IsArray() { return IsKind(TypeBase::kArray); }
+  bool IsFunction() { return IsKind(TypeBase::kFunction); }
+  bool IsTuple() { return IsKind(TypeBase::kTuple); }
 
-template<class Config>
-class TypeImpl<Config>::ConstantType : public StructuralType {
- public:
-  i::Handle<i::Object> Value() { return this->template GetValue<i::Object>(1); }
+  ClassType* AsClass() { return ClassType::cast(this); }
+  ConstantType* AsConstant() { return ConstantType::cast(this); }
+  RangeType* AsRange() { return RangeType::cast(this); }
+  ContextType* AsContext() { return ContextType::cast(this); }
+  ArrayType* AsArray() { return ArrayType::cast(this); }
+  FunctionType* AsFunction() { return FunctionType::cast(this); }
+  TupleType* AsTuple() { return TupleType::cast(this); }
 
-  static ConstantHandle New(i::Handle<i::Object> value, Region* region) {
-    ConstantHandle type = Config::template cast<ConstantType>(
-        StructuralType::New(StructuralType::kConstantTag, 2, region));
-    type->Set(0, BitsetType::New(BitsetType::Lub(*value), region));
-    type->SetValue(1, value);
-    return type;
+  // Minimum and maximum of a numeric type.
+  // These functions do not distinguish between -0 and +0.  If the type equals
+  // kNaN, they return NaN; otherwise kNaN is ignored.  Only call these
+  // functions on subtypes of Number.
+  double Min();
+  double Max();
+
+  // Extracts a range from the type: if the type is a range or a union
+  // containing a range, that range is returned; otherwise, NULL is returned.
+  Type* GetRange();
+
+  static bool IsInteger(i::Object* x);
+  static bool IsInteger(double x) {
+    return nearbyint(x) == x && !i::IsMinusZero(x);  // Allows for infinities.
   }
 
-  static ConstantType* cast(TypeImpl* type) {
-    DCHECK(type->IsConstant());
-    return static_cast<ConstantType*>(type);
-  }
+  int NumClasses();
+  int NumConstants();
 
- private:
-  template<class> friend class TypeImpl;
-  bitset Lub() { return this->Get(0)->AsBitset(); }
-};
-// TODO(neis): Also cache value if numerical.
-// TODO(neis): Allow restricting the representation.
+  template <class T>
+  class Iterator {
+   public:
+    bool Done() const { return index_ < 0; }
+    i::Handle<T> Current();
+    void Advance();
 
+   private:
+    friend class Type;
 
-// -----------------------------------------------------------------------------
-// Range types.
+    Iterator() : index_(-1) {}
+    explicit Iterator(Type* type) : type_(type), index_(-1) { Advance(); }
 
-template <class Config>
-class TypeImpl<Config>::RangeType : public TypeImpl<Config> {
- public:
-  double Min() { return Config::range_get_double(Config::as_range(this), 0); }
-  double Max() { return Config::range_get_double(Config::as_range(this), 1); }
+    inline bool matches(Type* type);
+    inline Type* get_type();
 
-  static RangeHandle New(double min, double max, TypeHandle representation,
-                         Region* region) {
-    DCHECK(IsInteger(min) && IsInteger(max));
-    DCHECK(min <= max);
-    bitset representation_bits = representation->AsBitset();
-    DCHECK(REPRESENTATION(representation_bits) == representation_bits);
-
-    typename Config::template Handle<typename Config::Range>::type range =
-        Config::range_create(region);
-
-    bitset bits = SEMANTIC(BitsetType::Lub(min, max)) | representation_bits;
-    Config::range_set_bitset(range, bits);
-    Config::range_set_double(range, 0, min, region);
-    Config::range_set_double(range, 1, max, region);
-    return Config::template cast<RangeType>(Config::from_range(range));
-  }
-
-  static RangeHandle New(Limits lim, bitset representation, Region* region) {
-    return New(lim.min, lim.max, BitsetType::New(representation, region),
-               region);
-  }
-
-  static RangeType* cast(TypeImpl* type) {
-    DCHECK(type->IsRange());
-    return static_cast<RangeType*>(type);
-  }
-
- private:
-  template<class> friend class TypeImpl;
-  bitset Lub() {
-    return Config::range_get_bitset(Config::as_range(this));
-  }
-};
-
-
-// -----------------------------------------------------------------------------
-// Context types.
-
-template<class Config>
-class TypeImpl<Config>::ContextType : public StructuralType {
- public:
-  TypeHandle Outer() { return this->Get(0); }
-
-  static ContextHandle New(TypeHandle outer, Region* region) {
-    ContextHandle type = Config::template cast<ContextType>(
-        StructuralType::New(StructuralType::kContextTag, 1, region));
-    type->Set(0, outer);
-    return type;
-  }
-
-  static ContextType* cast(TypeImpl* type) {
-    DCHECK(type->IsContext());
-    return static_cast<ContextType*>(type);
-  }
-};
-
-
-// -----------------------------------------------------------------------------
-// Array types.
-
-template<class Config>
-class TypeImpl<Config>::ArrayType : public StructuralType {
- public:
-  TypeHandle Element() { return this->Get(0); }
-
-  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) {
-    DCHECK(type->IsArray());
-    return static_cast<ArrayType*>(type);
-  }
-};
-
-
-// -----------------------------------------------------------------------------
-// Function types.
-
-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) {
-    DCHECK(type->IsFunction());
-    return static_cast<FunctionType*>(type);
-  }
-};
-
-
-// -----------------------------------------------------------------------------
-// Type iterators.
-
-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_;
-};
-
-
-// -----------------------------------------------------------------------------
-// Zone-allocated types; they are either (odd) integers to represent bitsets, or
-// (even) pointers to structures for everything else.
-
-struct ZoneTypeConfig {
-  typedef TypeImpl<ZoneTypeConfig> Type;
-  class Base {};
-  typedef void* Struct;
-  // Hack: the Struct and Range types can be aliased in memory, the first
-  // pointer word of each both must be the tag (kRangeStructTag for Range,
-  // anything else for Struct) so that we can differentiate them.
-  struct Range {
-    void* tag;
-    int bitset;
-    double limits[2];
+    Type* type_;
+    int index_;
   };
-  typedef i::Zone Region;
-  template<class T> struct Handle { typedef T* type; };
 
-  static const int kRangeStructTag = 0x1000;
-
-  template<class T> static inline T* null_handle() { return nullptr; }
-  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_struct(Type* type, int tag);
-  static inline bool is_range(Type* type);
-
-  static inline Type::bitset as_bitset(Type* type);
-  static inline i::Handle<i::Map> as_class(Type* type);
-  static inline Struct* as_struct(Type* type);
-  static inline Range* as_range(Type* type);
-
-  static inline Type* from_bitset(Type::bitset);
-  static inline Type* from_bitset(Type::bitset, Zone* zone);
-  static inline Type* from_class(i::Handle<i::Map> map, Zone* zone);
-  static inline Type* from_struct(Struct* structured);
-  static inline Type* from_range(Range* range);
-
-  static inline Struct* struct_create(int tag, int length, Zone* zone);
-  static inline void struct_shrink(Struct* structure, int length);
-  static inline int struct_tag(Struct* structure);
-  static inline int struct_length(Struct* structure);
-  static inline Type* struct_get(Struct* structure, int i);
-  static inline void struct_set(Struct* structure, int i, Type* type);
-  template<class V>
-  static inline i::Handle<V> struct_get_value(Struct* structure, int i);
-  template<class V> static inline void struct_set_value(
-      Struct* structure, int i, i::Handle<V> x);
-
-  static inline Range* range_create(Zone* zone);
-  static inline int range_get_bitset(Range* range);
-  static inline void range_set_bitset(Range* range, int);
-  static inline double range_get_double(Range*, int index);
-  static inline void range_set_double(Range*, int index, double value, Zone*);
-};
-
-typedef TypeImpl<ZoneTypeConfig> Type;
-
-
-// -----------------------------------------------------------------------------
-// Heap-allocated types; either smis for bitsets, maps for classes, boxes for
-// constants, or fixed arrays for unions.
-
-struct HeapTypeConfig {
-  typedef TypeImpl<HeapTypeConfig> Type;
-  typedef i::Object Base;
-  typedef i::FixedArray Struct;
-  typedef i::FixedArray Range;
-  typedef i::Isolate Region;
-  template<class T> struct Handle { typedef i::Handle<T> type; };
-
-  static const int kRangeStructTag = 0xffff;
-
-  template<class T> static inline i::Handle<T> null_handle() {
-    return i::Handle<T>();
+  Iterator<i::Map> Classes() {
+    if (this->IsBitset()) return Iterator<i::Map>();
+    return Iterator<i::Map>(this);
   }
-  template<class T> static inline i::Handle<T> handle(T* type);
-  template<class T> static inline i::Handle<T> cast(i::Handle<Type> type);
+  Iterator<i::Object> Constants() {
+    if (this->IsBitset()) return Iterator<i::Object>();
+    return Iterator<i::Object>(this);
+  }
 
-  static inline bool is_bitset(Type* type);
-  static inline bool is_class(Type* type);
-  static inline bool is_struct(Type* type, int tag);
-  static inline bool is_range(Type* type);
+  // Printing.
 
-  static inline Type::bitset as_bitset(Type* type);
-  static inline i::Handle<i::Map> as_class(Type* type);
-  static inline i::Handle<Struct> as_struct(Type* type);
-  static inline i::Handle<Range> as_range(Type* type);
+  enum PrintDimension { BOTH_DIMS, SEMANTIC_DIM, REPRESENTATION_DIM };
 
-  static inline Type* from_bitset(Type::bitset);
-  static inline i::Handle<Type> from_bitset(Type::bitset, Isolate* isolate);
-  static inline i::Handle<Type> from_class(
-      i::Handle<i::Map> map, Isolate* isolate);
-  static inline i::Handle<Type> from_struct(i::Handle<Struct> structure);
-  static inline i::Handle<Type> from_range(i::Handle<Range> range);
+  void PrintTo(std::ostream& os, PrintDimension dim = BOTH_DIMS);  // NOLINT
 
-  static inline i::Handle<Struct> struct_create(
-      int tag, int length, Isolate* isolate);
-  static inline void struct_shrink(i::Handle<Struct> structure, int length);
-  static inline int struct_tag(i::Handle<Struct> structure);
-  static inline int struct_length(i::Handle<Struct> structure);
-  static inline i::Handle<Type> struct_get(i::Handle<Struct> structure, int i);
-  static inline void struct_set(
-      i::Handle<Struct> structure, int i, i::Handle<Type> type);
-  template<class V>
-  static inline i::Handle<V> struct_get_value(
-      i::Handle<Struct> structure, int i);
-  template<class V>
-  static inline void struct_set_value(
-      i::Handle<Struct> structure, int i, i::Handle<V> x);
+#ifdef DEBUG
+  void Print();
+#endif
 
-  static inline i::Handle<Range> range_create(Isolate* isolate);
-  static inline int range_get_bitset(i::Handle<Range> range);
-  static inline void range_set_bitset(i::Handle<Range> range, int value);
-  static inline double range_get_double(i::Handle<Range> range, int index);
-  static inline void range_set_double(i::Handle<Range> range, int index,
-                                      double value, Isolate* isolate);
+  // Helpers for testing.
+  bool IsBitsetForTesting() { return IsBitset(); }
+  bool IsUnionForTesting() { return IsUnion(); }
+  bitset AsBitsetForTesting() { return AsBitset(); }
+  UnionType* AsUnionForTesting() { return AsUnion(); }
+
+ private:
+  // Friends.
+  template <class>
+  friend class Iterator;
+  friend BitsetType;
+  friend UnionType;
+
+  // Internal inspection.
+  bool IsKind(TypeBase::Kind kind) { return TypeBase::IsKind(this, kind); }
+
+  bool IsNone() { return this == None(); }
+  bool IsAny() { return this == Any(); }
+  bool IsBitset() { return BitsetType::IsBitset(this); }
+  bool IsUnion() { return IsKind(TypeBase::kUnion); }
+
+  bitset AsBitset() {
+    DCHECK(this->IsBitset());
+    return reinterpret_cast<BitsetType*>(this)->Bitset();
+  }
+  UnionType* AsUnion() { return UnionType::cast(this); }
+
+  bitset Representation();
+
+  // Auxiliary functions.
+  bool SemanticMaybe(Type* that);
+
+  bitset BitsetGlb() { return BitsetType::Glb(this); }
+  bitset BitsetLub() { return BitsetType::Lub(this); }
+
+  bool SlowIs(Type* that);
+  bool SemanticIs(Type* that);
+
+  static bool Overlap(RangeType* lhs, RangeType* rhs);
+  static bool Contains(RangeType* lhs, RangeType* rhs);
+  static bool Contains(RangeType* range, ConstantType* constant);
+  static bool Contains(RangeType* range, i::Object* val);
+
+  static int UpdateRange(Type* type, UnionType* result, int size, Zone* zone);
+
+  static RangeType::Limits IntersectRangeAndBitset(Type* range, Type* bits,
+                                                   Zone* zone);
+  static RangeType::Limits ToLimits(bitset bits, Zone* zone);
+
+  bool SimplyEquals(Type* that);
+
+  static int AddToUnion(Type* type, UnionType* result, int size, Zone* zone);
+  static int IntersectAux(Type* type, Type* other, UnionType* result, int size,
+                          RangeType::Limits* limits, Zone* zone);
+  static Type* NormalizeUnion(Type* unioned, int size, Zone* zone);
+  static Type* NormalizeRangeAndBitset(Type* range, bitset* bits, Zone* zone);
 };
 
-typedef TypeImpl<HeapTypeConfig> HeapType;
-
-
 // -----------------------------------------------------------------------------
 // Type bounds. A simple struct to represent a pair of lower/upper types.
 
-template<class Config>
-struct BoundsImpl {
-  typedef TypeImpl<Config> Type;
-  typedef typename Type::TypeHandle TypeHandle;
-  typedef typename Type::Region Region;
+struct Bounds {
+  Type* lower;
+  Type* upper;
 
-  TypeHandle lower;
-  TypeHandle upper;
-
-  BoundsImpl() :  // Make sure accessing uninitialized bounds crashes big-time.
-    lower(Config::template null_handle<Type>()),
-    upper(Config::template null_handle<Type>()) {}
-  explicit BoundsImpl(TypeHandle t) : lower(t), upper(t) {}
-  BoundsImpl(TypeHandle l, TypeHandle u) : lower(l), upper(u) {
-    DCHECK(lower->Is(upper));
-  }
+  Bounds()
+      :  // Make sure accessing uninitialized bounds crashes big-time.
+        lower(nullptr),
+        upper(nullptr) {}
+  explicit Bounds(Type* t) : lower(t), upper(t) {}
+  Bounds(Type* l, Type* u) : lower(l), upper(u) { DCHECK(lower->Is(upper)); }
 
   // Unrestricted bounds.
-  static BoundsImpl Unbounded() {
-    return BoundsImpl(Type::None(), Type::Any());
-  }
+  static Bounds Unbounded() { return Bounds(Type::None(), Type::Any()); }
 
   // Meet: both b1 and b2 are known to hold.
-  static BoundsImpl Both(BoundsImpl b1, BoundsImpl b2, Region* region) {
-    TypeHandle lower = Type::Union(b1.lower, b2.lower, region);
-    TypeHandle upper = Type::Intersect(b1.upper, b2.upper, region);
+  static Bounds Both(Bounds b1, Bounds b2, Zone* zone) {
+    Type* lower = Type::Union(b1.lower, b2.lower, zone);
+    Type* upper = Type::Intersect(b1.upper, b2.upper, zone);
     // Lower bounds are considered approximate, correct as necessary.
     if (!lower->Is(upper)) lower = upper;
-    return BoundsImpl(lower, upper);
+    return Bounds(lower, upper);
   }
 
   // Join: either b1 or b2 is known to hold.
-  static BoundsImpl Either(BoundsImpl b1, BoundsImpl b2, Region* region) {
-    TypeHandle lower = Type::Intersect(b1.lower, b2.lower, region);
-    TypeHandle upper = Type::Union(b1.upper, b2.upper, region);
-    return BoundsImpl(lower, upper);
+  static Bounds Either(Bounds b1, Bounds b2, Zone* zone) {
+    Type* lower = Type::Intersect(b1.lower, b2.lower, zone);
+    Type* upper = Type::Union(b1.upper, b2.upper, zone);
+    return Bounds(lower, upper);
   }
 
-  static BoundsImpl NarrowLower(BoundsImpl b, TypeHandle t, Region* region) {
-    TypeHandle lower = Type::Union(b.lower, t, region);
+  static Bounds NarrowLower(Bounds b, Type* t, Zone* zone) {
+    Type* lower = Type::Union(b.lower, t, zone);
     // Lower bounds are considered approximate, correct as necessary.
     if (!lower->Is(b.upper)) lower = b.upper;
-    return BoundsImpl(lower, b.upper);
+    return Bounds(lower, b.upper);
   }
-  static BoundsImpl NarrowUpper(BoundsImpl b, TypeHandle t, Region* region) {
-    TypeHandle lower = b.lower;
-    TypeHandle upper = Type::Intersect(b.upper, t, region);
+  static Bounds NarrowUpper(Bounds b, Type* t, Zone* zone) {
+    Type* lower = b.lower;
+    Type* upper = Type::Intersect(b.upper, t, zone);
     // Lower bounds are considered approximate, correct as necessary.
     if (!lower->Is(upper)) lower = upper;
-    return BoundsImpl(lower, upper);
+    return Bounds(lower, upper);
   }
 
-  bool Narrows(BoundsImpl that) {
+  bool Narrows(Bounds that) {
     return that.lower->Is(this->lower) && this->upper->Is(that.upper);
   }
 };
 
-typedef BoundsImpl<ZoneTypeConfig> Bounds;
-
 }  // namespace internal
 }  // namespace v8