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