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