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/common/globals.h"
10 #include "src/compiler/heap-refs.h"
11 #include "src/handles/handles.h"
12 #include "src/numbers/conversions.h"
13 #include "src/objects/objects.h"
14 #include "src/utils/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(NonBigIntPrimitive,           kSymbol | kPlainPrimitive) \
173   V(Primitive,                    kBigInt | kNonBigIntPrimitive) \
174   V(OtherUndetectableOrUndefined, kOtherUndetectable | kUndefined) \
175   V(Proxy,                        kCallableProxy | kOtherProxy) \
176   V(ArrayOrOtherObject,           kArray | kOtherObject) \
177   V(ArrayOrProxy,                 kArray | kProxy) \
178   V(DetectableCallable,           kFunction | kBoundFunction | \
179                                   kOtherCallable | kCallableProxy) \
180   V(Callable,                     kDetectableCallable | kOtherUndetectable) \
181   V(NonCallable,                  kArray | kOtherObject | kOtherProxy) \
182   V(NonCallableOrNull,            kNonCallable | kNull) \
183   V(DetectableObject,             kArray | kFunction | kBoundFunction | \
184                                   kOtherCallable | kOtherObject) \
185   V(DetectableReceiver,           kDetectableObject | kProxy) \
186   V(DetectableReceiverOrNull,     kDetectableReceiver | kNull) \
187   V(Object,                       kDetectableObject | kOtherUndetectable) \
188   V(Receiver,                     kObject | kProxy) \
189   V(ReceiverOrUndefined,          kReceiver | kUndefined) \
190   V(ReceiverOrNullOrUndefined,    kReceiver | kNull | kUndefined) \
191   V(SymbolOrReceiver,             kSymbol | kReceiver) \
192   V(StringOrReceiver,             kString | kReceiver) \
193   V(Unique,                       kBoolean | kUniqueName | kNull | \
194                                   kUndefined | kHole | kReceiver) \
195   V(Internal,                     kHole | kExternalPointer | kOtherInternal) \
196   V(NonInternal,                  kPrimitive | kReceiver) \
197   V(NonBigInt,                    kNonBigIntPrimitive | kReceiver) \
198   V(NonNumber,                    kBigInt | kUnique | kString | kInternal) \
199   V(Any,                          0xfffffffeu)
200 
201 // clang-format on
202 
203 /*
204  * The following diagrams show how integers (in the mathematical sense) are
205  * divided among the different atomic numerical types.
206  *
207  *   ON    OS32     N31     U30     OU31    OU32     ON
208  * ______[_______[_______[_______[_______[_______[_______
209  *     -2^31   -2^30     0      2^30    2^31    2^32
210  *
211  * E.g., OtherUnsigned32 (OU32) covers all integers from 2^31 to 2^32-1.
212  *
213  * Some of the atomic numerical bitsets are internal only (see
214  * INTERNAL_BITSET_TYPE_LIST).  To a types user, they should only occur in
215  * union with certain other bitsets.  For instance, OtherNumber should only
216  * occur as part of PlainNumber.
217  */
218 
219 #define BITSET_TYPE_LIST(V)    \
220   INTERNAL_BITSET_TYPE_LIST(V) \
221   PROPER_BITSET_TYPE_LIST(V)
222 
223 class JSHeapBroker;
224 class HeapConstantType;
225 class OtherNumberConstantType;
226 class TupleType;
227 class Type;
228 class UnionType;
229 
230 // -----------------------------------------------------------------------------
231 // Bitset types (internal).
232 
233 class V8_EXPORT_PRIVATE BitsetType {
234  public:
235   using bitset = uint32_t;  // Internal
236 
237   enum : uint32_t {
238 #define DECLARE_TYPE(type, value) k##type = (value),
239     BITSET_TYPE_LIST(DECLARE_TYPE)
240 #undef DECLARE_TYPE
241         kUnusedEOL = 0
242   };
243 
244   static bitset SignedSmall();
245   static bitset UnsignedSmall();
246 
IsNone(bitset bits)247   static bool IsNone(bitset bits) { return bits == kNone; }
248 
Is(bitset bits1,bitset bits2)249   static bool Is(bitset bits1, bitset bits2) {
250     return (bits1 | bits2) == bits2;
251   }
252 
253   static double Min(bitset);
254   static double Max(bitset);
255 
256   static bitset Glb(double min, double max);
Lub(HeapObjectType const & type)257   static bitset Lub(HeapObjectType const& type) {
258     return Lub<HeapObjectType>(type);
259   }
Lub(MapRef const & map)260   static bitset Lub(MapRef const& map) { return Lub<MapRef>(map); }
261   static bitset Lub(double value);
262   static bitset Lub(double min, double max);
263   static bitset ExpandInternals(bitset bits);
264 
265   static const char* Name(bitset);
266   static void Print(std::ostream& os, bitset);  // NOLINT
267 #ifdef DEBUG
268   static void Print(bitset);
269 #endif
270 
271   static bitset NumberBits(bitset bits);
272 
273  private:
274   struct Boundary {
275     bitset internal;
276     bitset external;
277     double min;
278   };
279   static const Boundary BoundariesArray[];
280   static inline const Boundary* Boundaries();
281   static inline size_t BoundariesSize();
282 
283   template <typename MapRefLike>
284   static bitset Lub(MapRefLike const& map);
285 };
286 
287 // -----------------------------------------------------------------------------
288 // Superclass for non-bitset types (internal).
289 class TypeBase {
290  protected:
291   friend class Type;
292 
293   enum Kind { kHeapConstant, kOtherNumberConstant, kTuple, kUnion, kRange };
294 
kind()295   Kind kind() const { return kind_; }
TypeBase(Kind kind)296   explicit TypeBase(Kind kind) : kind_(kind) {}
297 
298   static bool IsKind(Type type, Kind kind);
299 
300  private:
301   Kind kind_;
302 };
303 
304 // -----------------------------------------------------------------------------
305 // Range types.
306 
307 class RangeType : public TypeBase {
308  public:
309   struct Limits {
310     double min;
311     double max;
LimitsLimits312     Limits(double min, double max) : min(min), max(max) {}
LimitsLimits313     explicit Limits(const RangeType* range)
314         : min(range->Min()), max(range->Max()) {}
315     bool IsEmpty();
EmptyLimits316     static Limits Empty() { return Limits(1, 0); }
317     static Limits Intersect(Limits lhs, Limits rhs);
318     static Limits Union(Limits lhs, Limits rhs);
319   };
320 
Min()321   double Min() const { return limits_.min; }
Max()322   double Max() const { return limits_.max; }
323 
IsInteger(double x)324   static bool IsInteger(double x) {
325     return nearbyint(x) == x && !IsMinusZero(x);  // Allows for infinities.
326   }
327 
328  private:
329   friend class Type;
330   friend class BitsetType;
331   friend class UnionType;
332 
New(double min,double max,Zone * zone)333   static RangeType* New(double min, double max, Zone* zone) {
334     return New(Limits(min, max), zone);
335   }
336 
New(Limits lim,Zone * zone)337   static RangeType* New(Limits lim, Zone* zone) {
338     DCHECK(IsInteger(lim.min) && IsInteger(lim.max));
339     DCHECK(lim.min <= lim.max);
340     BitsetType::bitset bits = BitsetType::Lub(lim.min, lim.max);
341 
342     return new (zone->New(sizeof(RangeType))) RangeType(bits, lim);
343   }
344 
RangeType(BitsetType::bitset bitset,Limits limits)345   RangeType(BitsetType::bitset bitset, Limits limits)
346       : TypeBase(kRange), bitset_(bitset), limits_(limits) {}
347 
Lub()348   BitsetType::bitset Lub() const { return bitset_; }
349 
350   BitsetType::bitset bitset_;
351   Limits limits_;
352 };
353 
354 // -----------------------------------------------------------------------------
355 // The actual type.
356 
357 class V8_EXPORT_PRIVATE Type {
358  public:
359   using bitset = BitsetType::bitset;  // Internal
360 
361 // Constructors.
362 #define DEFINE_TYPE_CONSTRUCTOR(type, value) \
363   static Type type() { return NewBitset(BitsetType::k##type); }
364   PROPER_BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR)
365 #undef DEFINE_TYPE_CONSTRUCTOR
366 
Type()367   Type() : payload_(0) {}
368 
SignedSmall()369   static Type SignedSmall() { return NewBitset(BitsetType::SignedSmall()); }
UnsignedSmall()370   static Type UnsignedSmall() { return NewBitset(BitsetType::UnsignedSmall()); }
371 
372   static Type Constant(JSHeapBroker* broker, Handle<i::Object> value,
373                        Zone* zone);
374   static Type Constant(double value, Zone* zone);
375   static Type Range(double min, double max, Zone* zone);
376   static Type Tuple(Type first, Type second, Type third, Zone* zone);
377 
378   static Type Union(Type type1, Type type2, Zone* zone);
379   static Type Intersect(Type type1, Type type2, Zone* zone);
380 
For(MapRef const & type)381   static Type For(MapRef const& type) {
382     return NewBitset(BitsetType::ExpandInternals(BitsetType::Lub(type)));
383   }
384 
385   // Predicates.
IsNone()386   bool IsNone() const { return payload_ == None().payload_; }
IsInvalid()387   bool IsInvalid() const { return payload_ == 0u; }
388 
Is(Type that)389   bool Is(Type that) const {
390     return payload_ == that.payload_ || this->SlowIs(that);
391   }
392   bool Maybe(Type that) const;
Equals(Type that)393   bool Equals(Type that) const { return this->Is(that) && that.Is(*this); }
394 
395   // Inspection.
IsBitset()396   bool IsBitset() const { return payload_ & 1; }
IsRange()397   bool IsRange() const { return IsKind(TypeBase::kRange); }
IsHeapConstant()398   bool IsHeapConstant() const { return IsKind(TypeBase::kHeapConstant); }
IsOtherNumberConstant()399   bool IsOtherNumberConstant() const {
400     return IsKind(TypeBase::kOtherNumberConstant);
401   }
IsTuple()402   bool IsTuple() const { return IsKind(TypeBase::kTuple); }
403 
IsSingleton()404   bool IsSingleton() const {
405     if (IsNone()) return false;
406     return Is(Type::Null()) || Is(Type::Undefined()) || Is(Type::MinusZero()) ||
407            Is(Type::NaN()) || Is(Type::Hole()) || IsHeapConstant() ||
408            (Is(Type::PlainNumber()) && Min() == Max());
409   }
410 
411   const HeapConstantType* AsHeapConstant() const;
412   const OtherNumberConstantType* AsOtherNumberConstant() const;
413   const RangeType* AsRange() const;
414   const TupleType* AsTuple() const;
415 
416   // Minimum and maximum of a numeric type.
417   // These functions do not distinguish between -0 and +0.  NaN is ignored.
418   // Only call them on subtypes of Number whose intersection with OrderedNumber
419   // is not empty.
420   double Min() const;
421   double Max() const;
422 
423   // Extracts a range from the type: if the type is a range or a union
424   // containing a range, that range is returned; otherwise, nullptr is returned.
425   Type GetRange() const;
426 
427   int NumConstants() const;
428 
Invalid()429   static Type Invalid() { return Type(); }
430 
431   bool operator==(Type other) const { return payload_ == other.payload_; }
432   bool operator!=(Type other) const { return payload_ != other.payload_; }
433 
434   // Printing.
435 
436   void PrintTo(std::ostream& os) const;
437 
438 #ifdef DEBUG
439   void Print() const;
440 #endif
441 
442   // Helpers for testing.
IsUnionForTesting()443   bool IsUnionForTesting() { return IsUnion(); }
AsBitsetForTesting()444   bitset AsBitsetForTesting() { return AsBitset(); }
AsUnionForTesting()445   const UnionType* AsUnionForTesting() { return AsUnion(); }
BitsetGlbForTesting()446   Type BitsetGlbForTesting() { return NewBitset(BitsetGlb()); }
BitsetLubForTesting()447   Type BitsetLubForTesting() { return NewBitset(BitsetLub()); }
448 
449  private:
450   // Friends.
451   template <class>
452   friend class Iterator;
453   friend BitsetType;
454   friend UnionType;
455   friend size_t hash_value(Type type);
456 
Type(bitset bits)457   explicit Type(bitset bits) : payload_(bits | 1u) {}
458 
Type(TypeBase * type_base)459   Type(TypeBase* type_base)  // NOLINT(runtime/explicit)
460       : payload_(reinterpret_cast<uintptr_t>(type_base)) {}
461 
462   // Internal inspection.
IsKind(TypeBase::Kind kind)463   bool IsKind(TypeBase::Kind kind) const {
464     if (IsBitset()) return false;
465     const TypeBase* base = ToTypeBase();
466     return base->kind() == kind;
467   }
468 
ToTypeBase()469   const TypeBase* ToTypeBase() const {
470     return reinterpret_cast<TypeBase*>(payload_);
471   }
FromTypeBase(TypeBase * type)472   static Type FromTypeBase(TypeBase* type) { return Type(type); }
473 
IsAny()474   bool IsAny() const { return payload_ == Any().payload_; }
IsUnion()475   bool IsUnion() const { return IsKind(TypeBase::kUnion); }
476 
AsBitset()477   bitset AsBitset() const {
478     DCHECK(IsBitset());
479     return static_cast<bitset>(payload_) ^ 1u;
480   }
481 
482   const UnionType* AsUnion() const;
483 
484   bitset BitsetGlb() const;  // greatest lower bound that's a bitset
485   bitset BitsetLub() const;  // least upper bound that's a bitset
486 
487   bool SlowIs(Type that) const;
488 
NewBitset(bitset bits)489   static Type NewBitset(bitset bits) { return Type(bits); }
490 
491   static Type Range(RangeType::Limits lims, Zone* zone);
492   static Type OtherNumberConstant(double value, Zone* zone);
493   static Type HeapConstant(const HeapObjectRef& value, Zone* zone);
494 
495   static bool Overlap(const RangeType* lhs, const RangeType* rhs);
496   static bool Contains(const RangeType* lhs, const RangeType* rhs);
497 
498   static int UpdateRange(Type type, UnionType* result, int size, Zone* zone);
499 
500   static RangeType::Limits IntersectRangeAndBitset(Type range, Type bits,
501                                                    Zone* zone);
502   static RangeType::Limits ToLimits(bitset bits, Zone* zone);
503 
504   bool SimplyEquals(Type that) const;
505 
506   static int AddToUnion(Type type, UnionType* result, int size, Zone* zone);
507   static int IntersectAux(Type type, Type other, UnionType* result, int size,
508                           RangeType::Limits* limits, Zone* zone);
509   static Type NormalizeUnion(UnionType* unioned, int size, Zone* zone);
510   static Type NormalizeRangeAndBitset(Type range, bitset* bits, Zone* zone);
511 
512   // If LSB is set, the payload is a bitset; if LSB is clear, the payload is
513   // a pointer to a subtype of the TypeBase class.
514   uintptr_t payload_;
515 };
516 
hash_value(Type type)517 inline size_t hash_value(Type type) { return type.payload_; }
518 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, Type type);
519 
520 // -----------------------------------------------------------------------------
521 // Constant types.
522 
523 class OtherNumberConstantType : public TypeBase {
524  public:
Value()525   double Value() const { return value_; }
526 
527   static bool IsOtherNumberConstant(double value);
528 
529  private:
530   friend class Type;
531   friend class BitsetType;
532 
New(double value,Zone * zone)533   static OtherNumberConstantType* New(double value, Zone* zone) {
534     return new (zone->New(sizeof(OtherNumberConstantType)))
535         OtherNumberConstantType(value);  // NOLINT
536   }
537 
OtherNumberConstantType(double value)538   explicit OtherNumberConstantType(double value)
539       : TypeBase(kOtherNumberConstant), value_(value) {
540     CHECK(IsOtherNumberConstant(value));
541   }
542 
Lub()543   BitsetType::bitset Lub() const { return BitsetType::kOtherNumber; }
544 
545   double value_;
546 };
547 
NON_EXPORTED_BASE(TypeBase)548 class V8_EXPORT_PRIVATE HeapConstantType : public NON_EXPORTED_BASE(TypeBase) {
549  public:
550   Handle<HeapObject> Value() const;
551   const HeapObjectRef& Ref() const { return heap_ref_; }
552 
553  private:
554   friend class Type;
555   friend class BitsetType;
556 
557   static HeapConstantType* New(const HeapObjectRef& heap_ref,
558                                BitsetType::bitset bitset, Zone* zone) {
559     return new (zone->New(sizeof(HeapConstantType)))
560         HeapConstantType(bitset, heap_ref);
561   }
562 
563   HeapConstantType(BitsetType::bitset bitset, const HeapObjectRef& heap_ref);
564 
565   BitsetType::bitset Lub() const { return bitset_; }
566 
567   BitsetType::bitset bitset_;
568   HeapObjectRef heap_ref_;
569 };
570 
571 // -----------------------------------------------------------------------------
572 // Superclass for types with variable number of type fields.
573 class StructuralType : public TypeBase {
574  public:
LengthForTesting()575   int LengthForTesting() const { return Length(); }
576 
577  protected:
578   friend class Type;
579 
Length()580   int Length() const { return length_; }
581 
Get(int i)582   Type Get(int i) const {
583     DCHECK(0 <= i && i < this->Length());
584     return elements_[i];
585   }
586 
Set(int i,Type type)587   void Set(int i, Type type) {
588     DCHECK(0 <= i && i < this->Length());
589     elements_[i] = type;
590   }
591 
Shrink(int length)592   void Shrink(int length) {
593     DCHECK(2 <= length && length <= this->Length());
594     length_ = length;
595   }
596 
StructuralType(Kind kind,int length,Zone * zone)597   StructuralType(Kind kind, int length, Zone* zone)
598       : TypeBase(kind), length_(length) {
599     elements_ = reinterpret_cast<Type*>(zone->New(sizeof(Type) * length));
600   }
601 
602  private:
603   int length_;
604   Type* elements_;
605 };
606 
607 // -----------------------------------------------------------------------------
608 // Tuple types.
609 
610 class TupleType : public StructuralType {
611  public:
Arity()612   int Arity() const { return this->Length(); }
Element(int i)613   Type Element(int i) const { return this->Get(i); }
614 
InitElement(int i,Type type)615   void InitElement(int i, Type type) { this->Set(i, type); }
616 
617  private:
618   friend class Type;
619 
TupleType(int length,Zone * zone)620   TupleType(int length, Zone* zone) : StructuralType(kTuple, length, zone) {}
621 
New(int length,Zone * zone)622   static TupleType* New(int length, Zone* zone) {
623     return new (zone->New(sizeof(TupleType))) TupleType(length, zone);
624   }
625 };
626 
627 // -----------------------------------------------------------------------------
628 // Union types (internal).
629 // A union is a structured type with the following invariants:
630 // - its length is at least 2
631 // - at most one field is a bitset, and it must go into index 0
632 // - no field is a union
633 // - no field is a subtype of any other field
634 class UnionType : public StructuralType {
635  private:
636   friend Type;
637   friend BitsetType;
638 
UnionType(int length,Zone * zone)639   UnionType(int length, Zone* zone) : StructuralType(kUnion, length, zone) {}
640 
New(int length,Zone * zone)641   static UnionType* New(int length, Zone* zone) {
642     return new (zone->New(sizeof(UnionType))) UnionType(length, zone);
643   }
644 
645   bool Wellformed() const;
646 };
647 
648 }  // namespace compiler
649 }  // namespace internal
650 }  // namespace v8
651 
652 #endif  // V8_COMPILER_TYPES_H_
653