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