Line data Source code
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(OtherOneByteString, 1u << 5) \
108 : V(OtherTwoByteString, 1u << 6) \
109 :
110 : #define PROPER_BITSET_TYPE_LIST(V) \
111 : V(None, 0u) \
112 : V(Negative31, 1u << 7) \
113 : V(Null, 1u << 8) \
114 : V(Undefined, 1u << 9) \
115 : V(Boolean, 1u << 10) \
116 : V(Unsigned30, 1u << 11) \
117 : V(MinusZero, 1u << 12) \
118 : V(NaN, 1u << 13) \
119 : V(Symbol, 1u << 14) \
120 : V(EmptyString, 1u << 15) \
121 : V(NonEmptyInternalizedOneByteString, 1u << 16) \
122 : V(NonEmptyInternalizedTwoByteString, 1u << 17) \
123 : V(OtherCallable, 1u << 18) \
124 : V(OtherObject, 1u << 19) \
125 : V(OtherUndetectable, 1u << 20) \
126 : V(CallableProxy, 1u << 21) \
127 : V(OtherProxy, 1u << 22) \
128 : V(Function, 1u << 23) \
129 : V(BoundFunction, 1u << 24) \
130 : V(Hole, 1u << 25) \
131 : V(OtherInternal, 1u << 26) \
132 : V(ExternalPointer, 1u << 27) \
133 : V(Array, 1u << 28) \
134 : V(BigInt, 1u << 29) \
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(InternalizedOneByteString, kEmptyString | \
156 : kNonEmptyInternalizedOneByteString) \
157 : V(OneByteString, kInternalizedOneByteString | \
158 : kOtherOneByteString) \
159 : V(InternalizedString, kInternalizedOneByteString | \
160 : kNonEmptyInternalizedTwoByteString) \
161 : V(NonEmptyOneByteString, kNonEmptyInternalizedOneByteString | \
162 : kOtherOneByteString) \
163 : V(NonEmptyTwoByteString, kNonEmptyInternalizedTwoByteString | \
164 : kOtherTwoByteString) \
165 : V(NonEmptyString, kNonEmptyOneByteString | \
166 : kNonEmptyTwoByteString) \
167 : V(String, kEmptyString | kNonEmptyString) \
168 : V(UniqueName, kSymbol | kInternalizedString) \
169 : V(Name, kSymbol | kString) \
170 : V(InternalizedStringOrNull, kInternalizedString | kNull) \
171 : V(BooleanOrNumber, kBoolean | kNumber) \
172 : V(BooleanOrNullOrNumber, kBooleanOrNumber | kNull) \
173 : V(BooleanOrNullOrUndefined, kBoolean | kNull | kUndefined) \
174 : V(Oddball, kBooleanOrNullOrUndefined | kHole) \
175 : V(NullOrNumber, kNull | kNumber) \
176 : V(NullOrUndefined, kNull | kUndefined) \
177 : V(Undetectable, kNullOrUndefined | kOtherUndetectable) \
178 : V(NumberOrHole, kNumber | kHole) \
179 : V(NumberOrOddball, kNumber | kNullOrUndefined | kBoolean | \
180 : kHole) \
181 : V(NumericOrString, kNumeric | kString) \
182 : V(NumberOrUndefined, kNumber | kUndefined) \
183 : V(NumberOrUndefinedOrNullOrBoolean, \
184 : kNumber | kNullOrUndefined | kBoolean) \
185 : V(PlainPrimitive, kNumber | kString | kBoolean | \
186 : kNullOrUndefined) \
187 : V(NonBigIntPrimitive, kSymbol | kPlainPrimitive) \
188 : V(Primitive, kBigInt | kNonBigIntPrimitive) \
189 : V(OtherUndetectableOrUndefined, kOtherUndetectable | kUndefined) \
190 : V(Proxy, kCallableProxy | kOtherProxy) \
191 : V(ArrayOrOtherObject, kArray | kOtherObject) \
192 : V(ArrayOrProxy, kArray | kProxy) \
193 : V(DetectableCallable, kFunction | kBoundFunction | \
194 : kOtherCallable | kCallableProxy) \
195 : V(Callable, kDetectableCallable | kOtherUndetectable) \
196 : V(NonCallable, kArray | kOtherObject | kOtherProxy) \
197 : V(NonCallableOrNull, kNonCallable | kNull) \
198 : V(DetectableObject, kArray | kFunction | kBoundFunction | \
199 : kOtherCallable | kOtherObject) \
200 : V(DetectableReceiver, kDetectableObject | kProxy) \
201 : V(DetectableReceiverOrNull, kDetectableReceiver | kNull) \
202 : V(Object, kDetectableObject | kOtherUndetectable) \
203 : V(Receiver, kObject | kProxy) \
204 : V(ReceiverOrUndefined, kReceiver | kUndefined) \
205 : V(ReceiverOrNullOrUndefined, kReceiver | kNull | kUndefined) \
206 : V(SymbolOrReceiver, kSymbol | kReceiver) \
207 : V(StringOrReceiver, kString | kReceiver) \
208 : V(Unique, kBoolean | kUniqueName | kNull | \
209 : kUndefined | kReceiver) \
210 : V(Internal, kHole | kExternalPointer | kOtherInternal) \
211 : V(NonInternal, kPrimitive | kReceiver) \
212 : V(NonBigInt, kNonBigIntPrimitive | kReceiver) \
213 : V(NonNumber, kBigInt | kUnique | kString | kInternal) \
214 : V(Any, 0xfffffffeu)
215 :
216 : // clang-format on
217 :
218 : /*
219 : * The following diagrams show how integers (in the mathematical sense) are
220 : * divided among the different atomic numerical types.
221 : *
222 : * ON OS32 N31 U30 OU31 OU32 ON
223 : * ______[_______[_______[_______[_______[_______[_______
224 : * -2^31 -2^30 0 2^30 2^31 2^32
225 : *
226 : * E.g., OtherUnsigned32 (OU32) covers all integers from 2^31 to 2^32-1.
227 : *
228 : * Some of the atomic numerical bitsets are internal only (see
229 : * INTERNAL_BITSET_TYPE_LIST). To a types user, they should only occur in
230 : * union with certain other bitsets. For instance, OtherNumber should only
231 : * occur as part of PlainNumber.
232 : */
233 :
234 : #define BITSET_TYPE_LIST(V) \
235 : INTERNAL_BITSET_TYPE_LIST(V) \
236 : PROPER_BITSET_TYPE_LIST(V)
237 :
238 : class HeapConstantType;
239 : class OtherNumberConstantType;
240 : class TupleType;
241 : class Type;
242 : class UnionType;
243 :
244 : // -----------------------------------------------------------------------------
245 : // Bitset types (internal).
246 :
247 : class V8_EXPORT_PRIVATE BitsetType {
248 : public:
249 : using bitset = uint32_t; // Internal
250 :
251 : enum : uint32_t {
252 : #define DECLARE_TYPE(type, value) k##type = (value),
253 : BITSET_TYPE_LIST(DECLARE_TYPE)
254 : #undef DECLARE_TYPE
255 : kUnusedEOL = 0
256 : };
257 :
258 : static bitset SignedSmall();
259 : static bitset UnsignedSmall();
260 :
261 : static bool IsNone(bitset bits) { return bits == kNone; }
262 :
263 : static bool Is(bitset bits1, bitset bits2) {
264 351128304 : return (bits1 | bits2) == bits2;
265 : }
266 :
267 : static double Min(bitset);
268 : static double Max(bitset);
269 :
270 : static bitset Glb(double min, double max);
271 : static bitset Lub(HeapObjectType const& type) {
272 18423328 : return Lub<HeapObjectType>(type);
273 : }
274 12596 : static bitset Lub(MapRef const& map) { return Lub<MapRef>(map); }
275 : static bitset Lub(double value);
276 : static bitset Lub(double min, double max);
277 : static bitset ExpandInternals(bitset bits);
278 :
279 : static const char* Name(bitset);
280 : static void Print(std::ostream& os, bitset); // NOLINT
281 : #ifdef DEBUG
282 : static void Print(bitset);
283 : #endif
284 :
285 : static bitset NumberBits(bitset bits);
286 :
287 : private:
288 : struct Boundary {
289 : bitset internal;
290 : bitset external;
291 : double min;
292 : };
293 : static const Boundary BoundariesArray[];
294 : static inline const Boundary* Boundaries();
295 : static inline size_t BoundariesSize();
296 :
297 : template <typename MapRefLike>
298 : static bitset Lub(MapRefLike const& map);
299 : };
300 :
301 : // -----------------------------------------------------------------------------
302 : // Superclass for non-bitset types (internal).
303 : class TypeBase {
304 : protected:
305 : friend class Type;
306 :
307 : enum Kind { kHeapConstant, kOtherNumberConstant, kTuple, kUnion, kRange };
308 :
309 1141125093 : Kind kind() const { return kind_; }
310 61804428 : explicit TypeBase(Kind kind) : kind_(kind) {}
311 :
312 : static bool IsKind(Type type, Kind kind);
313 :
314 : private:
315 : Kind kind_;
316 : };
317 :
318 : // -----------------------------------------------------------------------------
319 : // Range types.
320 :
321 : class RangeType : public TypeBase {
322 : public:
323 : struct Limits {
324 : double min;
325 : double max;
326 17437907 : Limits(double min, double max) : min(min), max(max) {}
327 : explicit Limits(const RangeType* range)
328 : : min(range->Min()), max(range->Max()) {}
329 : bool IsEmpty();
330 : static Limits Empty() { return Limits(1, 0); }
331 : static Limits Intersect(Limits lhs, Limits rhs);
332 : static Limits Union(Limits lhs, Limits rhs);
333 : };
334 :
335 : double Min() const { return limits_.min; }
336 : double Max() const { return limits_.max; }
337 :
338 : static bool IsInteger(double x) {
339 9558656 : return nearbyint(x) == x && !IsMinusZero(x); // Allows for infinities.
340 : }
341 :
342 : private:
343 : friend class Type;
344 : friend class BitsetType;
345 : friend class UnionType;
346 :
347 : static RangeType* New(double min, double max, Zone* zone) {
348 17437907 : return New(Limits(min, max), zone);
349 : }
350 :
351 21395117 : static RangeType* New(Limits lim, Zone* zone) {
352 : DCHECK(IsInteger(lim.min) && IsInteger(lim.max));
353 : DCHECK(lim.min <= lim.max);
354 : BitsetType::bitset bits = BitsetType::Lub(lim.min, lim.max);
355 :
356 42790168 : return new (zone->New(sizeof(RangeType))) RangeType(bits, lim);
357 : }
358 :
359 : RangeType(BitsetType::bitset bitset, Limits limits)
360 21395084 : : TypeBase(kRange), bitset_(bitset), limits_(limits) {}
361 :
362 : BitsetType::bitset Lub() const { return bitset_; }
363 :
364 : BitsetType::bitset bitset_;
365 : Limits limits_;
366 : };
367 :
368 : // -----------------------------------------------------------------------------
369 : // The actual type.
370 :
371 : class V8_EXPORT_PRIVATE Type {
372 : public:
373 : using bitset = BitsetType::bitset; // Internal
374 :
375 : // Constructors.
376 : #define DEFINE_TYPE_CONSTRUCTOR(type, value) \
377 : static Type type() { return NewBitset(BitsetType::k##type); }
378 : PROPER_BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR)
379 : #undef DEFINE_TYPE_CONSTRUCTOR
380 :
381 201405832 : Type() : payload_(0) {}
382 :
383 6829755 : static Type SignedSmall() { return NewBitset(BitsetType::SignedSmall()); }
384 231968 : static Type UnsignedSmall() { return NewBitset(BitsetType::UnsignedSmall()); }
385 :
386 : static Type OtherNumberConstant(double value, Zone* zone);
387 : static Type HeapConstant(JSHeapBroker* broker, Handle<i::Object> value,
388 : Zone* zone);
389 : static Type HeapConstant(const HeapObjectRef& value, Zone* zone);
390 : static Type Range(double min, double max, Zone* zone);
391 : static Type Range(RangeType::Limits lims, Zone* zone);
392 : static Type Tuple(Type first, Type second, Type third, Zone* zone);
393 : static Type Union(int length, Zone* zone);
394 :
395 : // NewConstant is a factory that returns Constant, Range or Number.
396 : static Type NewConstant(JSHeapBroker* broker, Handle<i::Object> value,
397 : Zone* zone);
398 : static Type NewConstant(double value, Zone* zone);
399 :
400 : static Type Union(Type type1, Type type2, Zone* zone);
401 : static Type Intersect(Type type1, Type type2, Zone* zone);
402 :
403 : static Type For(HeapObjectType const& type) {
404 : return NewBitset(BitsetType::ExpandInternals(BitsetType::Lub(type)));
405 : }
406 12596 : static Type For(MapRef const& type) {
407 24853 : return NewBitset(BitsetType::ExpandInternals(BitsetType::Lub(type)));
408 : }
409 :
410 : // Predicates.
411 838791579 : bool IsNone() const { return payload_ == None().payload_; }
412 389402 : bool IsInvalid() const { return payload_ == 0u; }
413 :
414 46559377 : bool Is(Type that) const {
415 411150845 : return payload_ == that.payload_ || this->SlowIs(that);
416 : }
417 : bool Maybe(Type that) const;
418 363114 : bool Equals(Type that) const { return this->Is(that) && that.Is(*this); }
419 :
420 : // Inspection.
421 1438710529 : bool IsBitset() const { return payload_ & 1; }
422 : bool IsRange() const { return IsKind(TypeBase::kRange); }
423 : bool IsHeapConstant() const { return IsKind(TypeBase::kHeapConstant); }
424 : bool IsOtherNumberConstant() const {
425 : return IsKind(TypeBase::kOtherNumberConstant);
426 : }
427 : bool IsTuple() const { return IsKind(TypeBase::kTuple); }
428 :
429 : const HeapConstantType* AsHeapConstant() const;
430 : const OtherNumberConstantType* AsOtherNumberConstant() const;
431 : const RangeType* AsRange() const;
432 : const TupleType* AsTuple() const;
433 :
434 : // Minimum and maximum of a numeric type.
435 : // These functions do not distinguish between -0 and +0. NaN is ignored.
436 : // Only call them on subtypes of Number whose intersection with OrderedNumber
437 : // is not empty.
438 : double Min() const;
439 : double Max() const;
440 :
441 : // Extracts a range from the type: if the type is a range or a union
442 : // containing a range, that range is returned; otherwise, nullptr is returned.
443 : Type GetRange() const;
444 :
445 : int NumConstants() const;
446 :
447 : static Type Invalid() { return Type(); }
448 :
449 4085 : bool operator==(Type other) const { return payload_ == other.payload_; }
450 : bool operator!=(Type other) const { return payload_ != other.payload_; }
451 :
452 : // Printing.
453 :
454 : void PrintTo(std::ostream& os) const;
455 :
456 : #ifdef DEBUG
457 : void Print() const;
458 : #endif
459 :
460 : // Helpers for testing.
461 : bool IsUnionForTesting() { return IsUnion(); }
462 : bitset AsBitsetForTesting() { return AsBitset(); }
463 3516 : const UnionType* AsUnionForTesting() { return AsUnion(); }
464 50052 : Type BitsetGlbForTesting() { return NewBitset(BitsetGlb()); }
465 50068 : Type BitsetLubForTesting() { return NewBitset(BitsetLub()); }
466 :
467 : private:
468 : // Friends.
469 : template <class>
470 : friend class Iterator;
471 : friend BitsetType;
472 : friend UnionType;
473 : friend size_t hash_value(Type type);
474 :
475 59725962 : explicit Type(bitset bits) : payload_(bits | 1u) {}
476 : Type(TypeBase* type_base) // NOLINT(runtime/explicit)
477 58178480 : : payload_(reinterpret_cast<uintptr_t>(type_base)) {}
478 :
479 : // Internal inspection.
480 : bool IsKind(TypeBase::Kind kind) const {
481 1222750066 : if (IsBitset()) return false;
482 : const TypeBase* base = ToTypeBase();
483 1141125093 : return base->kind() == kind;
484 : }
485 :
486 : const TypeBase* ToTypeBase() const {
487 1647120939 : return reinterpret_cast<TypeBase*>(payload_);
488 : }
489 : static Type FromTypeBase(TypeBase* type) { return Type(type); }
490 :
491 42475824 : bool IsAny() const { return payload_ == Any().payload_; }
492 : bool IsUnion() const { return IsKind(TypeBase::kUnion); }
493 :
494 : bitset AsBitset() const {
495 : DCHECK(IsBitset());
496 642825279 : return static_cast<bitset>(payload_) ^ 1u;
497 : }
498 :
499 : const UnionType* AsUnion() const;
500 :
501 : bitset BitsetGlb() const; // greatest lower bound that's a bitset
502 : bitset BitsetLub() const; // least upper bound that's a bitset
503 :
504 : bool SlowIs(Type that) const;
505 :
506 : static Type NewBitset(bitset bits) { return Type(bits); }
507 :
508 : static bool Overlap(const RangeType* lhs, const RangeType* rhs);
509 : static bool Contains(const RangeType* lhs, const RangeType* rhs);
510 :
511 : static int UpdateRange(Type type, UnionType* result, int size, Zone* zone);
512 :
513 : static RangeType::Limits IntersectRangeAndBitset(Type range, Type bits,
514 : Zone* zone);
515 : static RangeType::Limits ToLimits(bitset bits, Zone* zone);
516 :
517 : bool SimplyEquals(Type that) const;
518 :
519 : static int AddToUnion(Type type, UnionType* result, int size, Zone* zone);
520 : static int IntersectAux(Type type, Type other, UnionType* result, int size,
521 : RangeType::Limits* limits, Zone* zone);
522 : static Type NormalizeUnion(UnionType* unioned, int size, Zone* zone);
523 : static Type NormalizeRangeAndBitset(Type range, bitset* bits, Zone* zone);
524 :
525 : // If LSB is set, the payload is a bitset; if LSB is clear, the payload is
526 : // a pointer to a subtype of the TypeBase class.
527 : uintptr_t payload_;
528 : };
529 :
530 : inline size_t hash_value(Type type) { return type.payload_; }
531 : V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, Type type);
532 :
533 : // -----------------------------------------------------------------------------
534 : // Constant types.
535 :
536 : class OtherNumberConstantType : public TypeBase {
537 : public:
538 : double Value() const { return value_; }
539 :
540 : static bool IsOtherNumberConstant(double value);
541 :
542 : private:
543 : friend class Type;
544 : friend class BitsetType;
545 :
546 1640802 : static OtherNumberConstantType* New(double value, Zone* zone) {
547 : return new (zone->New(sizeof(OtherNumberConstantType)))
548 1640802 : OtherNumberConstantType(value); // NOLINT
549 : }
550 :
551 1640802 : explicit OtherNumberConstantType(double value)
552 1640802 : : TypeBase(kOtherNumberConstant), value_(value) {
553 1640802 : CHECK(IsOtherNumberConstant(value));
554 1640802 : }
555 :
556 : BitsetType::bitset Lub() const { return BitsetType::kOtherNumber; }
557 :
558 : double value_;
559 : };
560 :
561 : class V8_EXPORT_PRIVATE HeapConstantType : public NON_EXPORTED_BASE(TypeBase) {
562 : public:
563 : Handle<HeapObject> Value() const;
564 : const HeapObjectRef& Ref() const { return heap_ref_; }
565 :
566 : private:
567 : friend class Type;
568 : friend class BitsetType;
569 :
570 18423320 : static HeapConstantType* New(const HeapObjectRef& heap_ref, Zone* zone) {
571 : DCHECK(!heap_ref.IsHeapNumber());
572 : DCHECK_IMPLIES(heap_ref.IsString(), heap_ref.IsInternalizedString());
573 36846638 : BitsetType::bitset bitset = BitsetType::Lub(heap_ref.GetHeapObjectType());
574 : return new (zone->New(sizeof(HeapConstantType)))
575 36846620 : HeapConstantType(bitset, heap_ref);
576 : }
577 :
578 : HeapConstantType(BitsetType::bitset bitset, const HeapObjectRef& heap_ref);
579 :
580 : BitsetType::bitset Lub() const { return bitset_; }
581 :
582 : BitsetType::bitset bitset_;
583 : HeapObjectRef heap_ref_;
584 : };
585 :
586 : // -----------------------------------------------------------------------------
587 : // Superclass for types with variable number of type fields.
588 : class StructuralType : public TypeBase {
589 : public:
590 : int LengthForTesting() const { return Length(); }
591 :
592 : protected:
593 : friend class Type;
594 :
595 : int Length() const { return length_; }
596 :
597 : Type Get(int i) const {
598 : DCHECK(0 <= i && i < this->Length());
599 256324461 : return elements_[i];
600 : }
601 :
602 : void Set(int i, Type type) {
603 : DCHECK(0 <= i && i < this->Length());
604 54733222 : elements_[i] = type;
605 : }
606 :
607 : void Shrink(int length) {
608 : DCHECK(2 <= length && length <= this->Length());
609 16716659 : length_ = length;
610 : }
611 :
612 : StructuralType(Kind kind, int length, Zone* zone)
613 20345232 : : TypeBase(kind), length_(length) {
614 20345232 : elements_ = reinterpret_cast<Type*>(zone->New(sizeof(Type) * length));
615 : }
616 :
617 : private:
618 : int length_;
619 : Type* elements_;
620 : };
621 :
622 : // -----------------------------------------------------------------------------
623 : // Tuple types.
624 :
625 : class TupleType : public StructuralType {
626 : public:
627 : int Arity() const { return this->Length(); }
628 : Type Element(int i) const { return this->Get(i); }
629 :
630 : void InitElement(int i, Type type) { this->Set(i, type); }
631 :
632 : private:
633 : friend class Type;
634 :
635 : TupleType(int length, Zone* zone) : StructuralType(kTuple, length, zone) {}
636 :
637 1386 : static TupleType* New(int length, Zone* zone) {
638 2772 : return new (zone->New(sizeof(TupleType))) TupleType(length, zone);
639 : }
640 : };
641 :
642 : // -----------------------------------------------------------------------------
643 : // Union types (internal).
644 : // A union is a structured type with the following invariants:
645 : // - its length is at least 2
646 : // - at most one field is a bitset, and it must go into index 0
647 : // - no field is a union
648 : // - no field is a subtype of any other field
649 : class UnionType : public StructuralType {
650 : private:
651 : friend Type;
652 : friend BitsetType;
653 :
654 : UnionType(int length, Zone* zone) : StructuralType(kUnion, length, zone) {}
655 :
656 20343849 : static UnionType* New(int length, Zone* zone) {
657 40687676 : return new (zone->New(sizeof(UnionType))) UnionType(length, zone);
658 : }
659 :
660 : bool Wellformed() const;
661 : };
662 :
663 : } // namespace compiler
664 : } // namespace internal
665 : } // namespace v8
666 :
667 : #endif // V8_COMPILER_TYPES_H_
|