Home | History | Annotate | Download | only in compiler
      1 // Copyright 2014 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef V8_COMPILER_TYPES_H_
      6 #define V8_COMPILER_TYPES_H_
      7 
      8 #include "src/base/compiler-specific.h"
      9 #include "src/compiler/js-heap-broker.h"
     10 #include "src/conversions.h"
     11 #include "src/globals.h"
     12 #include "src/handles.h"
     13 #include "src/objects.h"
     14 #include "src/ostreams.h"
     15 
     16 namespace v8 {
     17 namespace internal {
     18 namespace compiler {
     19 
     20 // SUMMARY
     21 //
     22 // A simple type system for compiler-internal use. It is based entirely on
     23 // union types, and all subtyping hence amounts to set inclusion. Besides the
     24 // obvious primitive types and some predefined unions, the type language also
     25 // can express class types (a.k.a. specific maps) and singleton types (i.e.,
     26 // concrete constants).
     27 //
     28 // The following equations and inequations hold:
     29 //
     30 //   None <= T
     31 //   T <= Any
     32 //
     33 //   Number = Signed32 \/ Unsigned32 \/ Double
     34 //   Smi <= Signed32
     35 //   Name = String \/ Symbol
     36 //   UniqueName = InternalizedString \/ Symbol
     37 //   InternalizedString < String
     38 //
     39 //   Receiver = Object \/ Proxy
     40 //   OtherUndetectable < Object
     41 //   DetectableReceiver = Receiver - OtherUndetectable
     42 //
     43 //   Constant(x) < T  iff instance_type(map(x)) < T
     44 //
     45 //
     46 // RANGE TYPES
     47 //
     48 // A range type represents a continuous integer interval by its minimum and
     49 // maximum value.  Either value may be an infinity, in which case that infinity
     50 // itself is also included in the range.   A range never contains NaN or -0.
     51 //
     52 // If a value v happens to be an integer n, then Constant(v) is considered a
     53 // subtype of Range(n, n) (and therefore also a subtype of any larger range).
     54 // In order to avoid large unions, however, it is usually a good idea to use
     55 // Range rather than Constant.
     56 //
     57 //
     58 // PREDICATES
     59 //
     60 // There are two main functions for testing types:
     61 //
     62 //   T1.Is(T2)     -- tests whether T1 is included in T2 (i.e., T1 <= T2)
     63 //   T1.Maybe(T2)  -- tests whether T1 and T2 overlap (i.e., T1 /\ T2 =/= 0)
     64 //
     65 // Typically, the former is to be used to select representations (e.g., via
     66 // T.Is(SignedSmall())), and the latter to check whether a specific case needs
     67 // handling (e.g., via T.Maybe(Number())).
     68 //
     69 // There is no functionality to discover whether a type is a leaf in the
     70 // lattice. That is intentional. It should always be possible to refine the
     71 // lattice (e.g., splitting up number types further) without invalidating any
     72 // existing assumptions or tests.
     73 // Consequently, do not normally use Equals for type tests, always use Is!
     74 //
     75 // The NowIs operator implements state-sensitive subtying, as described above.
     76 // Any compilation decision based on such temporary properties requires runtime
     77 // guarding!
     78 //
     79 //
     80 // PROPERTIES
     81 //
     82 // Various formal properties hold for constructors, operators, and predicates
     83 // over types. For example, constructors are injective and subtyping is a
     84 // complete partial order.
     85 //
     86 // See test/cctest/test-types.cc for a comprehensive executable specification,
     87 // especially with respect to the properties of the more exotic 'temporal'
     88 // constructors and predicates (those prefixed 'Now').
     89 //
     90 //
     91 // IMPLEMENTATION
     92 //
     93 // Internally, all 'primitive' types, and their unions, are represented as
     94 // bitsets. Bit 0 is reserved for tagging. Only structured types require
     95 // allocation.
     96 
     97 // -----------------------------------------------------------------------------
     98 // Values for bitset types
     99 
    100 // clang-format off
    101 
    102 #define INTERNAL_BITSET_TYPE_LIST(V)                                      \
    103   V(OtherUnsigned31, 1u << 1)  \
    104   V(OtherUnsigned32, 1u << 2)  \
    105   V(OtherSigned32,   1u << 3)  \
    106   V(OtherNumber,     1u << 4)  \
    107   V(OtherString,     1u << 5)  \
    108 
    109 #define PROPER_BITSET_TYPE_LIST(V) \
    110   V(None,                     0u)        \
    111   V(Negative31,               1u << 6)   \
    112   V(Null,                     1u << 7)   \
    113   V(Undefined,                1u << 8)   \
    114   V(Boolean,                  1u << 9)   \
    115   V(Unsigned30,               1u << 10)   \
    116   V(MinusZero,                1u << 11)  \
    117   V(NaN,                      1u << 12)  \
    118   V(Symbol,                   1u << 13)  \
    119   V(InternalizedString,       1u << 14)  \
    120   V(OtherCallable,            1u << 16)  \
    121   V(OtherObject,              1u << 17)  \
    122   V(OtherUndetectable,        1u << 18)  \
    123   V(CallableProxy,            1u << 19)  \
    124   V(OtherProxy,               1u << 20)  \
    125   V(Function,                 1u << 21)  \
    126   V(BoundFunction,            1u << 22)  \
    127   V(Hole,                     1u << 23)  \
    128   V(OtherInternal,            1u << 24)  \
    129   V(ExternalPointer,          1u << 25)  \
    130   V(Array,                    1u << 26)  \
    131   V(BigInt,                   1u << 27)  \
    132   \
    133   V(Signed31,                     kUnsigned30 | kNegative31) \
    134   V(Signed32,                     kSigned31 | kOtherUnsigned31 | \
    135                                   kOtherSigned32) \
    136   V(Signed32OrMinusZero,          kSigned32 | kMinusZero) \
    137   V(Signed32OrMinusZeroOrNaN,     kSigned32 | kMinusZero | kNaN) \
    138   V(Negative32,                   kNegative31 | kOtherSigned32) \
    139   V(Unsigned31,                   kUnsigned30 | kOtherUnsigned31) \
    140   V(Unsigned32,                   kUnsigned30 | kOtherUnsigned31 | \
    141                                   kOtherUnsigned32) \
    142   V(Unsigned32OrMinusZero,        kUnsigned32 | kMinusZero) \
    143   V(Unsigned32OrMinusZeroOrNaN,   kUnsigned32 | kMinusZero | kNaN) \
    144   V(Integral32,                   kSigned32 | kUnsigned32) \
    145   V(Integral32OrMinusZero,        kIntegral32 | kMinusZero) \
    146   V(Integral32OrMinusZeroOrNaN,   kIntegral32OrMinusZero | kNaN) \
    147   V(PlainNumber,                  kIntegral32 | kOtherNumber) \
    148   V(OrderedNumber,                kPlainNumber | kMinusZero) \
    149   V(MinusZeroOrNaN,               kMinusZero | kNaN) \
    150   V(Number,                       kOrderedNumber | kNaN) \
    151   V(Numeric,                      kNumber | kBigInt) \
    152   V(String,                       kInternalizedString | kOtherString) \
    153   V(UniqueName,                   kSymbol | kInternalizedString) \
    154   V(Name,                         kSymbol | kString) \
    155   V(InternalizedStringOrNull,     kInternalizedString | kNull) \
    156   V(BooleanOrNumber,              kBoolean | kNumber) \
    157   V(BooleanOrNullOrNumber,        kBooleanOrNumber | kNull) \
    158   V(BooleanOrNullOrUndefined,     kBoolean | kNull | kUndefined) \
    159   V(Oddball,                      kBooleanOrNullOrUndefined | kHole) \
    160   V(NullOrNumber,                 kNull | kNumber) \
    161   V(NullOrUndefined,              kNull | kUndefined) \
    162   V(Undetectable,                 kNullOrUndefined | kOtherUndetectable) \
    163   V(NumberOrHole,                 kNumber | kHole) \
    164   V(NumberOrOddball,              kNumber | kNullOrUndefined | kBoolean | \
    165                                   kHole) \
    166   V(NumericOrString,              kNumeric | kString) \
    167   V(NumberOrUndefined,            kNumber | kUndefined) \
    168   V(NumberOrUndefinedOrNullOrBoolean,  \
    169                                   kNumber | kNullOrUndefined | kBoolean) \
    170   V(PlainPrimitive,               kNumber | kString | kBoolean | \
    171                                   kNullOrUndefined) \
    172   V(Primitive,                    kSymbol | kBigInt | kPlainPrimitive) \
    173   V(OtherUndetectableOrUndefined, kOtherUndetectable | kUndefined) \
    174   V(Proxy,                        kCallableProxy | kOtherProxy) \
    175   V(ArrayOrOtherObject,           kArray | kOtherObject) \
    176   V(ArrayOrProxy,                 kArray | kProxy) \
    177   V(DetectableCallable,           kFunction | kBoundFunction | \
    178                                   kOtherCallable | kCallableProxy) \
    179   V(Callable,                     kDetectableCallable | kOtherUndetectable) \
    180   V(NonCallable,                  kArray | kOtherObject | kOtherProxy) \
    181   V(NonCallableOrNull,            kNonCallable | kNull) \
    182   V(DetectableObject,             kArray | kFunction | kBoundFunction | \
    183                                   kOtherCallable | kOtherObject) \
    184   V(DetectableReceiver,           kDetectableObject | kProxy) \
    185   V(DetectableReceiverOrNull,     kDetectableReceiver | kNull) \
    186   V(Object,                       kDetectableObject | kOtherUndetectable) \
    187   V(Receiver,                     kObject | kProxy) \
    188   V(ReceiverOrUndefined,          kReceiver | kUndefined) \
    189   V(ReceiverOrNullOrUndefined,    kReceiver | kNull | kUndefined) \
    190   V(SymbolOrReceiver,             kSymbol | kReceiver) \
    191   V(StringOrReceiver,             kString | kReceiver) \
    192   V(Unique,                       kBoolean | kUniqueName | kNull | \
    193                                   kUndefined | kReceiver) \
    194   V(Internal,                     kHole | kExternalPointer | kOtherInternal) \
    195   V(NonInternal,                  kPrimitive | kReceiver) \
    196   V(NonNumber,                    kUnique | kString | kInternal) \
    197   V(Any,                          0xfffffffeu)
    198 
    199 // clang-format on
    200 
    201 /*
    202  * The following diagrams show how integers (in the mathematical sense) are
    203  * divided among the different atomic numerical types.
    204  *
    205  *   ON    OS32     N31     U30     OU31    OU32     ON
    206  * ______[_______[_______[_______[_______[_______[_______
    207  *     -2^31   -2^30     0      2^30    2^31    2^32
    208  *
    209  * E.g., OtherUnsigned32 (OU32) covers all integers from 2^31 to 2^32-1.
    210  *
    211  * Some of the atomic numerical bitsets are internal only (see
    212  * INTERNAL_BITSET_TYPE_LIST).  To a types user, they should only occur in
    213  * union with certain other bitsets.  For instance, OtherNumber should only
    214  * occur as part of PlainNumber.
    215  */
    216 
    217 #define BITSET_TYPE_LIST(V)    \
    218   INTERNAL_BITSET_TYPE_LIST(V) \
    219   PROPER_BITSET_TYPE_LIST(V)
    220 
    221 class HeapConstantType;
    222 class OtherNumberConstantType;
    223 class TupleType;
    224 class Type;
    225 class UnionType;
    226 
    227 // -----------------------------------------------------------------------------
    228 // Bitset types (internal).
    229 
    230 class V8_EXPORT_PRIVATE BitsetType {
    231  public:
    232   typedef uint32_t bitset;  // Internal
    233 
    234   enum : uint32_t {
    235 #define DECLARE_TYPE(type, value) k##type = (value),
    236     BITSET_TYPE_LIST(DECLARE_TYPE)
    237 #undef DECLARE_TYPE
    238         kUnusedEOL = 0
    239   };
    240 
    241   static bitset SignedSmall();
    242   static bitset UnsignedSmall();
    243 
    244   static bool IsNone(bitset bits) { return bits == kNone; }
    245 
    246   static bool Is(bitset bits1, bitset bits2) {
    247     return (bits1 | bits2) == bits2;
    248   }
    249 
    250   static double Min(bitset);
    251   static double Max(bitset);
    252 
    253   static bitset Glb(double min, double max);
    254   static bitset Lub(HeapObjectType const& type);
    255   static bitset Lub(double value);
    256   static bitset Lub(double min, double max);
    257   static bitset ExpandInternals(bitset bits);
    258 
    259   static const char* Name(bitset);
    260   static void Print(std::ostream& os, bitset);  // NOLINT
    261 #ifdef DEBUG
    262   static void Print(bitset);
    263 #endif
    264 
    265   static bitset NumberBits(bitset bits);
    266 
    267  private:
    268   struct Boundary {
    269     bitset internal;
    270     bitset external;
    271     double min;
    272   };
    273   static const Boundary BoundariesArray[];
    274   static inline const Boundary* Boundaries();
    275   static inline size_t BoundariesSize();
    276 };
    277 
    278 // -----------------------------------------------------------------------------
    279 // Superclass for non-bitset types (internal).
    280 class TypeBase {
    281  protected:
    282   friend class Type;
    283 
    284   enum Kind { kHeapConstant, kOtherNumberConstant, kTuple, kUnion, kRange };
    285 
    286   Kind kind() const { return kind_; }
    287   explicit TypeBase(Kind kind) : kind_(kind) {}
    288 
    289   static bool IsKind(Type type, Kind kind);
    290 
    291  private:
    292   Kind kind_;
    293 };
    294 
    295 // -----------------------------------------------------------------------------
    296 // Range types.
    297 
    298 class RangeType : public TypeBase {
    299  public:
    300   struct Limits {
    301     double min;
    302     double max;
    303     Limits(double min, double max) : min(min), max(max) {}
    304     explicit Limits(const RangeType* range)
    305         : min(range->Min()), max(range->Max()) {}
    306     bool IsEmpty();
    307     static Limits Empty() { return Limits(1, 0); }
    308     static Limits Intersect(Limits lhs, Limits rhs);
    309     static Limits Union(Limits lhs, Limits rhs);
    310   };
    311 
    312   double Min() const { return limits_.min; }
    313   double Max() const { return limits_.max; }
    314 
    315   static bool IsInteger(double x) {
    316     return nearbyint(x) == x && !IsMinusZero(x);  // Allows for infinities.
    317   }
    318 
    319  private:
    320   friend class Type;
    321   friend class BitsetType;
    322   friend class UnionType;
    323 
    324   static RangeType* New(double min, double max, Zone* zone) {
    325     return New(Limits(min, max), zone);
    326   }
    327 
    328   static RangeType* New(Limits lim, Zone* zone) {
    329     DCHECK(IsInteger(lim.min) && IsInteger(lim.max));
    330     DCHECK(lim.min <= lim.max);
    331     BitsetType::bitset bits = BitsetType::Lub(lim.min, lim.max);
    332 
    333     return new (zone->New(sizeof(RangeType))) RangeType(bits, lim);
    334   }
    335 
    336   RangeType(BitsetType::bitset bitset, Limits limits)
    337       : TypeBase(kRange), bitset_(bitset), limits_(limits) {}
    338 
    339   BitsetType::bitset Lub() const { return bitset_; }
    340 
    341   BitsetType::bitset bitset_;
    342   Limits limits_;
    343 };
    344 
    345 // -----------------------------------------------------------------------------
    346 // The actual type.
    347 
    348 class V8_EXPORT_PRIVATE Type {
    349  public:
    350   typedef BitsetType::bitset bitset;  // Internal
    351 
    352 // Constructors.
    353 #define DEFINE_TYPE_CONSTRUCTOR(type, value) \
    354   static Type type() { return NewBitset(BitsetType::k##type); }
    355   PROPER_BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR)
    356 #undef DEFINE_TYPE_CONSTRUCTOR
    357 
    358   Type() : payload_(0) {}
    359 
    360   static Type SignedSmall() { return NewBitset(BitsetType::SignedSmall()); }
    361   static Type UnsignedSmall() { return NewBitset(BitsetType::UnsignedSmall()); }
    362 
    363   static Type OtherNumberConstant(double value, Zone* zone);
    364   static Type HeapConstant(JSHeapBroker* js_heap_broker,
    365                            Handle<i::Object> value, Zone* zone);
    366   static Type HeapConstant(const HeapObjectRef& value, Zone* zone);
    367   static Type Range(double min, double max, Zone* zone);
    368   static Type Range(RangeType::Limits lims, Zone* zone);
    369   static Type Tuple(Type first, Type second, Type third, Zone* zone);
    370   static Type Union(int length, Zone* zone);
    371 
    372   // NewConstant is a factory that returns Constant, Range or Number.
    373   static Type NewConstant(JSHeapBroker* js_heap_broker, Handle<i::Object> value,
    374                           Zone* zone);
    375   static Type NewConstant(double value, Zone* zone);
    376 
    377   static Type Union(Type type1, Type type2, Zone* zone);
    378   static Type Intersect(Type type1, Type type2, Zone* zone);
    379 
    380   static Type For(JSHeapBroker* js_heap_broker, Handle<i::Map> map) {
    381     HeapObjectType type = js_heap_broker->HeapObjectTypeFromMap(map);
    382     return NewBitset(BitsetType::ExpandInternals(BitsetType::Lub(type)));
    383   }
    384 
    385   // Predicates.
    386   bool IsNone() const { return payload_ == None().payload_; }
    387   bool IsInvalid() const { return payload_ == 0u; }
    388 
    389   bool Is(Type that) const {
    390     return payload_ == that.payload_ || this->SlowIs(that);
    391   }
    392   bool Maybe(Type that) const;
    393   bool Equals(Type that) const { return this->Is(that) && that.Is(*this); }
    394 
    395   // Inspection.
    396   bool IsBitset() const { return payload_ & 1; }
    397   bool IsRange() const { return IsKind(TypeBase::kRange); }
    398   bool IsHeapConstant() const { return IsKind(TypeBase::kHeapConstant); }
    399   bool IsOtherNumberConstant() const {
    400     return IsKind(TypeBase::kOtherNumberConstant);
    401   }
    402   bool IsTuple() const { return IsKind(TypeBase::kTuple); }
    403 
    404   const HeapConstantType* AsHeapConstant() const;
    405   const OtherNumberConstantType* AsOtherNumberConstant() const;
    406   const RangeType* AsRange() const;
    407   const TupleType* AsTuple() const;
    408 
    409   // Minimum and maximum of a numeric type.
    410   // These functions do not distinguish between -0 and +0.  NaN is ignored.
    411   // Only call them on subtypes of Number whose intersection with OrderedNumber
    412   // is not empty.
    413   double Min() const;
    414   double Max() const;
    415 
    416   // Extracts a range from the type: if the type is a range or a union
    417   // containing a range, that range is returned; otherwise, nullptr is returned.
    418   Type GetRange() const;
    419 
    420   int NumConstants() const;
    421 
    422   static Type Invalid() { return Type(); }
    423 
    424   bool operator==(Type other) const { return payload_ == other.payload_; }
    425   bool operator!=(Type other) const { return payload_ != other.payload_; }
    426 
    427   // Printing.
    428 
    429   void PrintTo(std::ostream& os) const;
    430 
    431 #ifdef DEBUG
    432   void Print() const;
    433 #endif
    434 
    435   // Helpers for testing.
    436   bool IsUnionForTesting() { return IsUnion(); }
    437   bitset AsBitsetForTesting() { return AsBitset(); }
    438   const UnionType* AsUnionForTesting() { return AsUnion(); }
    439   Type BitsetGlbForTesting() { return NewBitset(BitsetGlb()); }
    440   Type BitsetLubForTesting() { return NewBitset(BitsetLub()); }
    441 
    442  private:
    443   // Friends.
    444   template <class>
    445   friend class Iterator;
    446   friend BitsetType;
    447   friend UnionType;
    448   friend size_t hash_value(Type type);
    449 
    450   Type(bitset bits) : payload_(bits | 1u) {}
    451   Type(TypeBase* type_base)
    452       : payload_(reinterpret_cast<uintptr_t>(type_base)) {}
    453 
    454   // Internal inspection.
    455   bool IsKind(TypeBase::Kind kind) const {
    456     if (IsBitset()) return false;
    457     const TypeBase* base = ToTypeBase();
    458     return base->kind() == kind;
    459   }
    460 
    461   const TypeBase* ToTypeBase() const {
    462     return reinterpret_cast<TypeBase*>(payload_);
    463   }
    464   static Type FromTypeBase(TypeBase* type) { return Type(type); }
    465 
    466   bool IsAny() const { return payload_ == Any().payload_; }
    467   bool IsUnion() const { return IsKind(TypeBase::kUnion); }
    468 
    469   bitset AsBitset() const {
    470     DCHECK(IsBitset());
    471     return static_cast<bitset>(payload_) ^ 1u;
    472   }
    473 
    474   const UnionType* AsUnion() const;
    475 
    476   bitset BitsetGlb() const;  // greatest lower bound that's a bitset
    477   bitset BitsetLub() const;  // least upper bound that's a bitset
    478 
    479   bool SlowIs(Type that) const;
    480 
    481   static Type NewBitset(bitset bits) { return Type(bits); }
    482 
    483   static bool Overlap(const RangeType* lhs, const RangeType* rhs);
    484   static bool Contains(const RangeType* lhs, const RangeType* rhs);
    485 
    486   static int UpdateRange(Type type, UnionType* result, int size, Zone* zone);
    487 
    488   static RangeType::Limits IntersectRangeAndBitset(Type range, Type bits,
    489                                                    Zone* zone);
    490   static RangeType::Limits ToLimits(bitset bits, Zone* zone);
    491 
    492   bool SimplyEquals(Type that) const;
    493 
    494   static int AddToUnion(Type type, UnionType* result, int size, Zone* zone);
    495   static int IntersectAux(Type type, Type other, UnionType* result, int size,
    496                           RangeType::Limits* limits, Zone* zone);
    497   static Type NormalizeUnion(UnionType* unioned, int size, Zone* zone);
    498   static Type NormalizeRangeAndBitset(Type range, bitset* bits, Zone* zone);
    499 
    500   // If LSB is set, the payload is a bitset; if LSB is clear, the payload is
    501   // a pointer to a subtype of the TypeBase class.
    502   uintptr_t payload_;
    503 };
    504 
    505 inline size_t hash_value(Type type) { return type.payload_; }
    506 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, Type type);
    507 
    508 // -----------------------------------------------------------------------------
    509 // Constant types.
    510 
    511 class OtherNumberConstantType : public TypeBase {
    512  public:
    513   double Value() const { return value_; }
    514 
    515   static bool IsOtherNumberConstant(double value);
    516 
    517  private:
    518   friend class Type;
    519   friend class BitsetType;
    520 
    521   static OtherNumberConstantType* New(double value, Zone* zone) {
    522     return new (zone->New(sizeof(OtherNumberConstantType)))
    523         OtherNumberConstantType(value);  // NOLINT
    524   }
    525 
    526   explicit OtherNumberConstantType(double value)
    527       : TypeBase(kOtherNumberConstant), value_(value) {
    528     CHECK(IsOtherNumberConstant(value));
    529   }
    530 
    531   BitsetType::bitset Lub() const { return BitsetType::kOtherNumber; }
    532 
    533   double value_;
    534 };
    535 
    536 class V8_EXPORT_PRIVATE HeapConstantType : public NON_EXPORTED_BASE(TypeBase) {
    537  public:
    538   Handle<HeapObject> Value() const;
    539   const HeapObjectRef& Ref() const { return heap_ref_; }
    540 
    541  private:
    542   friend class Type;
    543   friend class BitsetType;
    544 
    545   static HeapConstantType* New(const HeapObjectRef& heap_ref, Zone* zone) {
    546     DCHECK(!heap_ref.IsHeapNumber());
    547     DCHECK_IMPLIES(heap_ref.IsString(), heap_ref.IsInternalizedString());
    548     BitsetType::bitset bitset = BitsetType::Lub(heap_ref.type());
    549     return new (zone->New(sizeof(HeapConstantType)))
    550         HeapConstantType(bitset, heap_ref);
    551   }
    552 
    553   HeapConstantType(BitsetType::bitset bitset, const HeapObjectRef& heap_ref);
    554 
    555   BitsetType::bitset Lub() const { return bitset_; }
    556 
    557   BitsetType::bitset bitset_;
    558   HeapObjectRef heap_ref_;
    559 };
    560 
    561 // -----------------------------------------------------------------------------
    562 // Superclass for types with variable number of type fields.
    563 class StructuralType : public TypeBase {
    564  public:
    565   int LengthForTesting() const { return Length(); }
    566 
    567  protected:
    568   friend class Type;
    569 
    570   int Length() const { return length_; }
    571 
    572   Type Get(int i) const {
    573     DCHECK(0 <= i && i < this->Length());
    574     return elements_[i];
    575   }
    576 
    577   void Set(int i, Type type) {
    578     DCHECK(0 <= i && i < this->Length());
    579     elements_[i] = type;
    580   }
    581 
    582   void Shrink(int length) {
    583     DCHECK(2 <= length && length <= this->Length());
    584     length_ = length;
    585   }
    586 
    587   StructuralType(Kind kind, int length, Zone* zone)
    588       : TypeBase(kind), length_(length) {
    589     elements_ = reinterpret_cast<Type*>(zone->New(sizeof(Type) * length));
    590   }
    591 
    592  private:
    593   int length_;
    594   Type* elements_;
    595 };
    596 
    597 // -----------------------------------------------------------------------------
    598 // Tuple types.
    599 
    600 class TupleType : public StructuralType {
    601  public:
    602   int Arity() const { return this->Length(); }
    603   Type Element(int i) const { return this->Get(i); }
    604 
    605   void InitElement(int i, Type type) { this->Set(i, type); }
    606 
    607  private:
    608   friend class Type;
    609 
    610   TupleType(int length, Zone* zone) : StructuralType(kTuple, length, zone) {}
    611 
    612   static TupleType* New(int length, Zone* zone) {
    613     return new (zone->New(sizeof(TupleType))) TupleType(length, zone);
    614   }
    615 };
    616 
    617 // -----------------------------------------------------------------------------
    618 // Union types (internal).
    619 // A union is a structured type with the following invariants:
    620 // - its length is at least 2
    621 // - at most one field is a bitset, and it must go into index 0
    622 // - no field is a union
    623 // - no field is a subtype of any other field
    624 class UnionType : public StructuralType {
    625  private:
    626   friend Type;
    627   friend BitsetType;
    628 
    629   UnionType(int length, Zone* zone) : StructuralType(kUnion, length, zone) {}
    630 
    631   static UnionType* New(int length, Zone* zone) {
    632     return new (zone->New(sizeof(UnionType))) UnionType(length, zone);
    633   }
    634 
    635   bool Wellformed() const;
    636 };
    637 
    638 }  // namespace compiler
    639 }  // namespace internal
    640 }  // namespace v8
    641 
    642 #endif  // V8_COMPILER_TYPES_H_
    643