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