v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
turbofan-types.h
Go to the documentation of this file.
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_TURBOFAN_TYPES_H_
6#define V8_COMPILER_TURBOFAN_TYPES_H_
7
11#include "src/handles/handles.h"
13#include "src/objects/objects.h"
14#include "src/utils/ostreams.h"
15
16#ifdef V8_ENABLE_WEBASSEMBLY
17#include "src/wasm/value-type.h"
18#endif
19
20namespace v8 {
21namespace internal {
22namespace wasm {
23struct TypeInModule;
24}
25namespace compiler {
26
27// SUMMARY
28//
29// A simple type system for compiler-internal use. It is based entirely on
30// union types, and all subtyping hence amounts to set inclusion. Besides the
31// obvious primitive types and some predefined unions, the type language also
32// can express class types (a.k.a. specific maps) and singleton types (i.e.,
33// concrete constants).
34//
35// The following equations and inequations hold:
36//
37// None <= T
38// T <= Any
39//
40// Number = Signed32 \/ Unsigned32 \/ Double
41// Smi <= Signed32
42// Name = String \/ Symbol
43// UniqueName = InternalizedString \/ Symbol
44// InternalizedString < String
45//
46// Receiver = Object \/ Proxy
47// OtherUndetectable < Object
48// DetectableReceiver = Receiver - OtherUndetectable
49//
50// Constant(x) < T iff instance_type(map(x)) < T
51//
52// None <= Machine <= Any
53//
54// RANGE TYPES
55//
56// A range type represents a continuous integer interval by its minimum and
57// maximum value. Either value may be an infinity, in which case that infinity
58// itself is also included in the range. A range never contains NaN or -0.
59//
60// If a value v happens to be an integer n, then Constant(v) is considered a
61// subtype of Range(n, n) (and therefore also a subtype of any larger range).
62// In order to avoid large unions, however, it is usually a good idea to use
63// Range rather than Constant.
64//
65//
66// PREDICATES
67//
68// There are two main functions for testing types:
69//
70// T1.Is(T2) -- tests whether T1 is included in T2 (i.e., T1 <= T2)
71// T1.Maybe(T2) -- tests whether T1 and T2 overlap (i.e., T1 /\ T2 =/= 0)
72//
73// Typically, the former is to be used to select representations (e.g., via
74// T.Is(SignedSmall())), and the latter to check whether a specific case needs
75// handling (e.g., via T.Maybe(Number())).
76//
77// There is no functionality to discover whether a type is a leaf in the
78// lattice. That is intentional. It should always be possible to refine the
79// lattice (e.g., splitting up number types further) without invalidating any
80// existing assumptions or tests.
81// Consequently, do not normally use Equals for type tests, always use Is!
82//
83//
84// PROPERTIES
85//
86// Various formal properties hold for constructors, operators, and predicates
87// over types. For example, constructors are injective and subtyping is a
88// complete partial order.
89//
90// See test/cctest/test-types.cc for a comprehensive executable specification,
91// especially with respect to the properties of the more exotic 'temporal'
92// constructors and predicates (those prefixed 'Now').
93//
94//
95// IMPLEMENTATION
96//
97// Internally, all 'primitive' types, and their unions, are represented as
98// bitsets. Bit 0 is reserved for tagging. Only structured types require
99// allocation.
100
101// -----------------------------------------------------------------------------
102// Values for bitset types
103
104// clang-format off
105
106#define INTERNAL_BITSET_TYPE_LIST(V) \
107 V(OtherUnsigned31, uint64_t{1} << 1) \
108 V(OtherUnsigned32, uint64_t{1} << 2) \
109 V(OtherSigned32, uint64_t{1} << 3) \
110 V(OtherNumber, uint64_t{1} << 4) \
111 V(OtherString, uint64_t{1} << 5) \
112
113#define PROPER_ATOMIC_BITSET_TYPE_LOW_LIST(V) \
114 V(Negative31, uint64_t{1} << 6) \
115 V(Null, uint64_t{1} << 7) \
116 V(Undefined, uint64_t{1} << 8) \
117 V(Boolean, uint64_t{1} << 9) \
118 V(Unsigned30, uint64_t{1} << 10) \
119 V(MinusZero, uint64_t{1} << 11) \
120 V(NaN, uint64_t{1} << 12) \
121 V(Symbol, uint64_t{1} << 13) \
122 V(InternalizedString, uint64_t{1} << 14) \
123 V(OtherCallable, uint64_t{1} << 15) \
124 V(OtherObject, uint64_t{1} << 16) \
125 V(OtherUndetectable, uint64_t{1} << 17) \
126 V(CallableProxy, uint64_t{1} << 18) \
127 V(OtherProxy, uint64_t{1} << 19) \
128 V(CallableFunction, uint64_t{1} << 20) \
129 V(ClassConstructor, uint64_t{1} << 21) \
130 V(BoundFunction, uint64_t{1} << 22) \
131 V(OtherInternal, uint64_t{1} << 23) \
132 V(ExternalPointer, uint64_t{1} << 24) \
133 V(Array, uint64_t{1} << 25) \
134 V(UnsignedBigInt63, uint64_t{1} << 26) \
135 V(OtherUnsignedBigInt64, uint64_t{1} << 27) \
136 V(NegativeBigInt63, uint64_t{1} << 28) \
137 V(OtherBigInt, uint64_t{1} << 29) \
138 V(WasmObject, uint64_t{1} << 30) \
139 V(SandboxedPointer, uint64_t{1} << 31)
140
141// We split the macro list into two parts because the Torque equivalent in
142// turbofan-types.tq uses two 32bit bitfield structs.
143#define PROPER_ATOMIC_BITSET_TYPE_HIGH_LIST(V) \
144 V(Machine, uint64_t{1} << 32) \
145 V(Hole, uint64_t{1} << 33) \
146 V(StringWrapper, uint64_t{1} << 34) \
147 V(TypedArray, uint64_t{1} << 35)
148
149#define PROPER_BITSET_TYPE_LIST(V) \
150 V(None, uint64_t{0}) \
151 PROPER_ATOMIC_BITSET_TYPE_LOW_LIST(V) \
152 PROPER_ATOMIC_BITSET_TYPE_HIGH_LIST(V) \
153 V(Signed31, kUnsigned30 | kNegative31) \
154 V(Signed32, kSigned31 | kOtherUnsigned31 | \
155 kOtherSigned32) \
156 V(Signed32OrMinusZero, kSigned32 | kMinusZero) \
157 V(Signed32OrMinusZeroOrNaN, kSigned32 | kMinusZero | kNaN) \
158 V(Negative32, kNegative31 | kOtherSigned32) \
159 V(Unsigned31, kUnsigned30 | kOtherUnsigned31) \
160 V(Unsigned32, kUnsigned30 | kOtherUnsigned31 | \
161 kOtherUnsigned32) \
162 V(Unsigned32OrMinusZero, kUnsigned32 | kMinusZero) \
163 V(Unsigned32OrMinusZeroOrNaN, kUnsigned32 | kMinusZero | kNaN) \
164 V(Integral32, kSigned32 | kUnsigned32) \
165 V(Integral32OrMinusZero, kIntegral32 | kMinusZero) \
166 V(Integral32OrMinusZeroOrNaN, kIntegral32OrMinusZero | kNaN) \
167 V(PlainNumber, kIntegral32 | kOtherNumber) \
168 V(OrderedNumber, kPlainNumber | kMinusZero) \
169 V(MinusZeroOrNaN, kMinusZero | kNaN) \
170 V(Number, kOrderedNumber | kNaN) \
171 V(SignedBigInt64, kUnsignedBigInt63 | kNegativeBigInt63) \
172 V(UnsignedBigInt64, kUnsignedBigInt63 | kOtherUnsignedBigInt64) \
173 V(BigInt, kSignedBigInt64 | kOtherUnsignedBigInt64 | \
174 kOtherBigInt) \
175 V(Numeric, kNumber | kBigInt) \
176 V(String, kInternalizedString | kOtherString) \
177 V(StringOrStringWrapper, kString | kStringWrapper) \
178 V(UniqueName, kSymbol | kInternalizedString) \
179 V(Name, kSymbol | kString) \
180 V(InternalizedStringOrNull, kInternalizedString | kNull) \
181 V(BooleanOrNumber, kBoolean | kNumber) \
182 V(BooleanOrNullOrNumber, kBooleanOrNumber | kNull) \
183 V(BooleanOrNullOrUndefined, kBoolean | kNull | kUndefined) \
184 V(NullOrNumber, kNull | kNumber) \
185 V(NullOrUndefined, kNull | kUndefined) \
186 V(Undetectable, kNullOrUndefined | kOtherUndetectable) \
187 V(NumberOrHole, kNumber | kHole) \
188 V(NumberOrOddball, kNumber | kBooleanOrNullOrUndefined ) \
189 V(NumberOrOddballOrHole, kNumberOrOddball| kHole ) \
190 V(NumericOrString, kNumeric | kString) \
191 V(NumberOrUndefined, kNumber | kUndefined) \
192 V(PlainPrimitive, kNumber | kString | kBoolean | \
193 kNullOrUndefined) \
194 V(NonBigIntPrimitive, kSymbol | kPlainPrimitive) \
195 V(Primitive, kBigInt | kNonBigIntPrimitive) \
196 V(OtherUndetectableOrUndefined, kOtherUndetectable | kUndefined) \
197 V(Proxy, kCallableProxy | kOtherProxy) \
198 V(ArrayOrOtherObject, kArray | kOtherObject) \
199 V(ArrayOrProxy, kArray | kProxy) \
200 V(StringWrapperOrOtherObject, kStringWrapper | kOtherObject) \
201 V(Function, kCallableFunction | kClassConstructor) \
202 V(DetectableCallable, kFunction | kBoundFunction | \
203 kOtherCallable | kCallableProxy) \
204 V(Callable, kDetectableCallable | kOtherUndetectable) \
205 V(NonCallable, kArray | kStringWrapper | kTypedArray | \
206 kOtherObject | kOtherProxy | kWasmObject) \
207 V(NonCallableOrNull, kNonCallable | kNull) \
208 V(DetectableObject, kArray | kFunction | kBoundFunction | \
209 kStringWrapper | kTypedArray | kOtherCallable | \
210 kOtherObject) \
211 V(DetectableReceiver, kDetectableObject | kProxy | kWasmObject) \
212 V(DetectableReceiverOrNull, kDetectableReceiver | kNull) \
213 V(Object, kDetectableObject | kOtherUndetectable) \
214 V(Receiver, kObject | kProxy | kWasmObject) \
215 V(ReceiverOrUndefined, kReceiver | kUndefined) \
216 V(ReceiverOrNull, kReceiver | kNull) \
217 V(ReceiverOrNullOrUndefined, kReceiver | kNull | kUndefined) \
218 V(SymbolOrReceiver, kSymbol | kReceiver) \
219 V(StringOrReceiver, kString | kReceiver) \
220 V(Unique, kBoolean | kUniqueName | kNull | \
221 kUndefined | kHole | kReceiver) \
222 V(Internal, kHole | kExternalPointer | \
223 kSandboxedPointer | kOtherInternal) \
224 V(NonInternal, kPrimitive | kReceiver) \
225 V(NonBigInt, kNonBigIntPrimitive | kReceiver) \
226 V(NonNumber, kBigInt | kUnique | kString | kInternal) \
227 V(Any, uint64_t{0xfffffffffffffffe})
228
229// clang-format on
230
231/*
232 * The following diagrams show how integers (in the mathematical sense) are
233 * divided among the different atomic numerical types.
234 *
235 * ON OS32 N31 U30 OU31 OU32 ON
236 * ______[_______[_______[_______[_______[_______[_______
237 * -2^31 -2^30 0 2^30 2^31 2^32
238 *
239 * E.g., OtherUnsigned32 (OU32) covers all integers from 2^31 to 2^32-1.
240 *
241 * Some of the atomic numerical bitsets are internal only (see
242 * INTERNAL_BITSET_TYPE_LIST). To a types user, they should only occur in
243 * union with certain other bitsets. For instance, OtherNumber should only
244 * occur as part of PlainNumber.
245 */
246
247#define BITSET_TYPE_LIST(V) \
248 INTERNAL_BITSET_TYPE_LIST(V) \
249 PROPER_BITSET_TYPE_LIST(V)
250
251class JSHeapBroker;
252class HeapConstantType;
253class OtherNumberConstantType;
254class TupleType;
255class Type;
256class UnionType;
257
258// -----------------------------------------------------------------------------
259// Bitset types (internal).
260
262 public:
263 using bitset = uint64_t; // Internal
264
265 enum : bitset {
266#define DECLARE_TYPE(type, value) k##type = (value),
268#undef DECLARE_TYPE
269 kUnusedEOL = 0
270 };
271
272 static bitset SignedSmall();
273 static bitset UnsignedSmall();
274
275 static bool IsNone(bitset bits) { return bits == kNone; }
276
277 static bool Is(bitset bits1, bitset bits2) {
278 return (bits1 | bits2) == bits2;
279 }
280
281 static double Min(bitset);
282 static double Max(bitset);
283
284 static bitset Glb(double min, double max);
286 return Lub<HeapObjectType>(type, broker);
287 }
289 return Lub<MapRef>(map, broker);
290 }
291 static bitset Lub(double value);
292 static bitset Lub(double min, double max);
293 static bitset ExpandInternals(bitset bits);
294
295 static const char* Name(bitset);
296 static void Print(std::ostream& os, bitset);
297#ifdef DEBUG
298 static void Print(bitset);
299#endif
300
301 static bitset NumberBits(bitset bits);
302
303 private:
309 static const Boundary BoundariesArray[];
310 static inline const Boundary* Boundaries();
311 static inline size_t BoundariesSize();
312
313 template <typename MapRefLike>
314 static bitset Lub(MapRefLike map, JSHeapBroker* broker);
315};
316
317// -----------------------------------------------------------------------------
318// Superclass for non-bitset types (internal).
319class TypeBase {
320 protected:
321 friend class Type;
322
331
332 Kind kind() const { return kind_; }
333 explicit TypeBase(Kind kind) : kind_(kind) {}
334
335 static bool IsKind(Type type, Kind kind);
336
337 private:
339};
340
341// -----------------------------------------------------------------------------
342// Range types.
343
344class RangeType : public TypeBase {
345 public:
346 struct Limits {
347 double min;
348 double max;
349 Limits(double min, double max) : min(min), max(max) {}
350 explicit Limits(const RangeType* range)
351 : min(range->Min()), max(range->Max()) {}
352 bool IsEmpty();
353 static Limits Empty() { return Limits(1, 0); }
354 static Limits Intersect(Limits lhs, Limits rhs);
355 static Limits Union(Limits lhs, Limits rhs);
356 };
357
358 double Min() const { return limits_.min; }
359 double Max() const { return limits_.max; }
360
361 static bool IsInteger(double x) {
362 return nearbyint(x) == x && !IsMinusZero(x); // Allows for infinities.
363 }
364
365 private:
366 friend class Type;
367 friend class BitsetType;
368 friend class UnionType;
369 friend Zone;
370
371 static RangeType* New(double min, double max, Zone* zone) {
372 return New(Limits(min, max), zone);
373 }
374
375 static RangeType* New(Limits lim, Zone* zone) {
376 DCHECK(IsInteger(lim.min) && IsInteger(lim.max));
377 DCHECK(lim.min <= lim.max);
378 BitsetType::bitset bits = BitsetType::Lub(lim.min, lim.max);
379
380 return zone->New<RangeType>(bits, lim);
381 }
382
384 : TypeBase(kRange), bitset_(bitset), limits_(limits) {}
385
386 BitsetType::bitset Lub() const { return bitset_; }
387
390};
391
392#ifdef V8_ENABLE_WEBASSEMBLY
393class WasmType : public TypeBase {
394 public:
395 static WasmType* New(wasm::ValueType value_type,
396 const wasm::WasmModule* module, Zone* zone) {
397 return zone->New<WasmType>(value_type, module);
398 }
399 wasm::ValueType value_type() const { return value_type_; }
400 const wasm::WasmModule* module() const { return module_; }
401
402 private:
403 friend class Type;
404 friend Zone;
405
406 explicit WasmType(wasm::ValueType value_type, const wasm::WasmModule* module)
407 : TypeBase(kWasm), value_type_(value_type), module_(module) {}
408
409 BitsetType::bitset Lub() const {
410 // TODO(manoskouk): Specify more concrete types.
411 return BitsetType::kAny;
412 }
413
414 wasm::ValueType value_type_;
415 const wasm::WasmModule* module_;
416};
417#endif // V8_ENABLE_WEBASSEMBLY
418
419// -----------------------------------------------------------------------------
420// The actual type.
421
423 public:
424 using bitset = BitsetType::bitset; // Internal
425
426// Constructors.
427#define DEFINE_TYPE_CONSTRUCTOR(type, value) \
428 static Type type() { return NewBitset(BitsetType::k##type); }
430#undef DEFINE_TYPE_CONSTRUCTOR
431
432 Type() : payload_(uint64_t{0}) {}
433
434 static Type SignedSmall() { return NewBitset(BitsetType::SignedSmall()); }
435 static Type UnsignedSmall() { return NewBitset(BitsetType::UnsignedSmall()); }
436
438 Zone* zone);
439 static Type Constant(JSHeapBroker* broker, ObjectRef value, Zone* zone);
440 static Type Constant(double value, Zone* zone);
441 static Type Range(double min, double max, Zone* zone);
442 static Type Tuple(Type first, Type second, Type third, Zone* zone);
443 static Type Tuple(Type first, Type second, Zone* zone);
444
445 static Type Union(Type type1, Type type2, Zone* zone);
446 static Type Intersect(Type type1, Type type2, Zone* zone);
447#ifdef V8_ENABLE_WEBASSEMBLY
448 static Type Wasm(wasm::ValueType value_type, const wasm::WasmModule* module,
449 Zone* zone);
450 static Type Wasm(wasm::TypeInModule type_in_module, Zone* zone);
451#endif
452
454 return NewBitset(
455 BitsetType::ExpandInternals(BitsetType::Lub(type, broker)));
456 }
457
458 // Predicates.
459 bool IsNone() const { return payload_ == None().payload_; }
460 bool IsInvalid() const { return payload_ == uint64_t{0}; }
461
462 bool Is(Type that) const {
463 return payload_ == that.payload_ || this->SlowIs(that);
464 }
465 bool Maybe(Type that) const;
466 bool Equals(Type that) const { return this->Is(that) && that.Is(*this); }
467
468 // Inspection.
469 bool IsBitset() const { return payload_ & uint64_t{1}; }
470 bool IsRange() const { return IsKind(TypeBase::kRange); }
471 bool IsHeapConstant() const { return IsKind(TypeBase::kHeapConstant); }
473 return IsKind(TypeBase::kOtherNumberConstant);
474 }
475 bool IsTuple() const { return IsKind(TypeBase::kTuple); }
476#ifdef V8_ENABLE_WEBASSEMBLY
477 bool IsWasm() const { return IsKind(TypeBase::kWasm); }
478#endif
479
480 bool IsSingleton() const {
481 if (IsNone()) return false;
482 return Is(Type::Null()) || Is(Type::Undefined()) || Is(Type::MinusZero()) ||
483 Is(Type::NaN()) || IsHeapConstant() ||
484 (Is(Type::PlainNumber()) && Min() == Max());
485 }
486
487 bool CanBeAsserted() const { return Is(Type::NonInternal()); }
488 Handle<TurbofanType> AllocateOnHeap(Factory* factory);
489
490 const HeapConstantType* AsHeapConstant() const;
491 const OtherNumberConstantType* AsOtherNumberConstant() const;
492 const RangeType* AsRange() const;
493 const TupleType* AsTuple() const;
494#ifdef V8_ENABLE_WEBASSEMBLY
495 wasm::TypeInModule AsWasm() const;
496#endif
497
498 // Minimum and maximum of a numeric type.
499 // These functions do not distinguish between -0 and +0. NaN is ignored.
500 // Only call them on subtypes of Number whose intersection with OrderedNumber
501 // is not empty.
502 double Min() const;
503 double Max() const;
504
505 // Extracts a range from the type: if the type is a range or a union
506 // containing a range, that range is returned; otherwise, nullptr is returned.
507 Type GetRange() const;
508
509 int NumConstants() const;
510
511 static Type Invalid() { return Type(); }
512
513 bool operator==(Type other) const { return payload_ == other.payload_; }
514 bool operator!=(Type other) const { return payload_ != other.payload_; }
515
516 // Printing.
517
518 void PrintTo(std::ostream& os) const;
519
520#ifdef DEBUG
521 void Print() const;
522#endif
523
524 // Helpers for testing.
525 bool IsUnionForTesting() { return IsUnion(); }
526 bitset AsBitsetForTesting() { return AsBitset(); }
527 const UnionType* AsUnionForTesting() { return AsUnion(); }
528 Type BitsetGlbForTesting() { return NewBitset(BitsetGlb()); }
529 Type BitsetLubForTesting() { return NewBitset(BitsetLub()); }
530
531 private:
532 // Friends.
533 template <class>
534 friend class Iterator;
536 friend UnionType;
537 friend size_t hash_value(Type type);
538
539 explicit Type(bitset bits) : payload_(bits | uint64_t{1}) {}
540
541 Type(TypeBase* type_base) // NOLINT(runtime/explicit)
542 : payload_(reinterpret_cast<uint64_t>(type_base)) {}
543
544 // Internal inspection.
546 if (IsBitset()) return false;
547 const TypeBase* base = ToTypeBase();
548 return base->kind() == kind;
549 }
550
551 const TypeBase* ToTypeBase() const {
552 return reinterpret_cast<TypeBase*>(payload_);
553 }
554 static Type FromTypeBase(TypeBase* type) { return Type(type); }
555
556 bool IsAny() const { return payload_ == Any().payload_; }
557 bool IsUnion() const { return IsKind(TypeBase::kUnion); }
558
559 bitset AsBitset() const {
560 DCHECK(IsBitset());
561 return static_cast<bitset>(payload_) ^ uint64_t { 1 };
562 }
563
564 const UnionType* AsUnion() const;
565
566 bitset BitsetGlb() const; // greatest lower bound that's a bitset
567 bitset BitsetLub() const; // least upper bound that's a bitset
568
569 bool SlowIs(Type that) const;
570
571 static Type NewBitset(bitset bits) { return Type(bits); }
572
573 static Type Range(RangeType::Limits lims, Zone* zone);
574 static Type OtherNumberConstant(double value, Zone* zone);
575 static Type HeapConstant(HeapObjectRef value, JSHeapBroker* broker,
576 Zone* zone);
577
578 static bool Overlap(const RangeType* lhs, const RangeType* rhs);
579 static bool Contains(const RangeType* lhs, const RangeType* rhs);
580
581 static int UpdateRange(Type type, UnionType* result, int size, Zone* zone);
582
583 static RangeType::Limits IntersectRangeAndBitset(Type range, Type bits,
584 Zone* zone);
585 static RangeType::Limits ToLimits(bitset bits, Zone* zone);
586
587 bool SimplyEquals(Type that) const;
588
589 static int AddToUnion(Type type, UnionType* result, int size, Zone* zone);
590 static int IntersectAux(Type type, Type other, UnionType* result, int size,
591 RangeType::Limits* limits, Zone* zone);
592 static Type NormalizeUnion(UnionType* unioned, int size, Zone* zone);
593 static Type NormalizeRangeAndBitset(Type range, bitset* bits, Zone* zone);
594
595 // If LSB is set, the payload is a bitset; if LSB is clear, the payload is
596 // a pointer to a subtype of the TypeBase class.
597 uint64_t payload_;
598};
599
600inline size_t hash_value(Type type) { return type.payload_; }
601V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, Type type);
602
603// -----------------------------------------------------------------------------
604// Constant types.
605
607 public:
608 double Value() const { return value_; }
609
610 static bool IsOtherNumberConstant(double value);
611
612 private:
613 friend class Type;
614 friend class BitsetType;
615 friend Zone;
616
617 static OtherNumberConstantType* New(double value, Zone* zone) {
618 return zone->New<OtherNumberConstantType>(value);
619 }
620
621 explicit OtherNumberConstantType(double value)
624 }
625
626 BitsetType::bitset Lub() const { return BitsetType::kOtherNumber; }
627
628 double value_;
629};
630
632 public:
634 HeapObjectRef Ref() const { return heap_ref_; }
635
636 private:
637 friend class Type;
638 friend class BitsetType;
639 friend Zone;
640
642 BitsetType::bitset bitset, Zone* zone) {
643 return zone->New<HeapConstantType>(bitset, heap_ref);
644 }
645
647
648 BitsetType::bitset Lub() const { return bitset_; }
649
652};
653
654// -----------------------------------------------------------------------------
655// Superclass for types with variable number of type fields.
656class StructuralType : public TypeBase {
657 public:
658 int LengthForTesting() const { return Length(); }
659
660 protected:
661 friend class Type;
662
663 int Length() const { return length_; }
664
665 Type Get(int i) const {
666 DCHECK(0 <= i && i < this->Length());
667 return elements_[i];
668 }
669
670 void Set(int i, Type type) {
671 DCHECK(0 <= i && i < this->Length());
672 elements_[i] = type;
673 }
674
675 void Shrink(int length) {
676 DCHECK(2 <= length && length <= this->Length());
677 length_ = length;
678 }
679
680 StructuralType(Kind kind, int length, Zone* zone)
681 : TypeBase(kind), length_(length) {
683 }
684
685 private:
688};
689
690// -----------------------------------------------------------------------------
691// Tuple types.
692
693class TupleType : public StructuralType {
694 public:
695 int Arity() const { return this->Length(); }
696 Type Element(int i) const { return this->Get(i); }
697
698 void InitElement(int i, Type type) { this->Set(i, type); }
699
700 private:
701 friend Type;
702 friend Zone;
703
704 TupleType(int length, Zone* zone) : StructuralType(kTuple, length, zone) {}
705
706 static TupleType* New(int length, Zone* zone) {
707 return zone->New<TupleType>(length, zone);
708 }
709};
710
711// -----------------------------------------------------------------------------
712// Union types (internal).
713// A union is a structured type with the following invariants:
714// - its length is at least 2
715// - at most one field is a bitset, and it must go into index 0
716// - no field is a union
717// - no field is a subtype of any other field
718class UnionType : public StructuralType {
719 private:
720 friend Type;
722 friend Zone;
723
724 UnionType(int length, Zone* zone) : StructuralType(kUnion, length, zone) {}
725
726 static UnionType* New(int length, Zone* zone) {
727 return zone->New<UnionType>(length, zone);
728 }
729
730 bool Wellformed() const;
731};
732
733} // namespace compiler
734} // namespace internal
735} // namespace v8
736
737#endif // V8_COMPILER_TURBOFAN_TYPES_H_
friend Zone
Definition asm-types.cc:195
Builtins::Kind kind
Definition builtins.cc:40
T * AllocateArray(size_t length)
Definition zone.h:127
T * New(Args &&... args)
Definition zone.h:114
static bitset Lub(MapRefLike map, JSHeapBroker *broker)
static bool Is(bitset bits1, bitset bits2)
static bitset Lub(MapRef map, JSHeapBroker *broker)
static bool IsNone(bitset bits)
static bitset Lub(HeapObjectType const &type, JSHeapBroker *broker)
static HeapConstantType * New(HeapObjectRef heap_ref, BitsetType::bitset bitset, Zone *zone)
static OtherNumberConstantType * New(double value, Zone *zone)
static RangeType * New(Limits lim, Zone *zone)
BitsetType::bitset Lub() const
RangeType(BitsetType::bitset bitset, Limits limits)
static RangeType * New(double min, double max, Zone *zone)
StructuralType(Kind kind, int length, Zone *zone)
void InitElement(int i, Type type)
static TupleType * New(int length, Zone *zone)
TupleType(int length, Zone *zone)
static bool IsKind(Type type, Kind kind)
bool operator!=(Type other) const
Type(TypeBase *type_base)
static Type For(MapRef type, JSHeapBroker *broker)
const TypeBase * ToTypeBase() const
bool Equals(Type that) const
bool Is(Type that) const
bool operator==(Type other) const
const UnionType * AsUnionForTesting()
static Type FromTypeBase(TypeBase *type)
static Type NewBitset(bitset bits)
bool IsKind(TypeBase::Kind kind) const
static UnionType * New(int length, Zone *zone)
UnionType(int length, Zone *zone)
#define PROPER_BITSET_TYPE_LIST(V)
#define DECLARE_TYPE(type, value)
#define DEFINE_TYPE_CONSTRUCTOR(type, value)
#define BITSET_TYPE_LIST(V)
JSHeapBroker * broker
double second
ZoneVector< RpoNumber > & result
int x
size_t hash_value(const BranchParameters &p)
std::ostream & operator<<(std::ostream &os, AccessMode access_mode)
bool IsNone(Tagged< FieldType > obj)
Definition field-type.h:50
bool Is(IndirectHandle< U > value)
Definition handles-inl.h:51
return value
Definition map-inl.h:893
static bool IsMinusZero(double value)
Definition c-api.cc:87
Type value_type_
#define NON_EXPORTED_BASE(code)
#define CHECK(condition)
Definition logging.h:124
#define DCHECK(condition)
Definition logging.h:482
#define V8_EXPORT_PRIVATE
Definition macros.h:460
static Limits Union(Limits lhs, Limits rhs)
static Limits Intersect(Limits lhs, Limits rhs)
wasm::ValueType type
const wasm::WasmModule * module_