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