Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(73)

Side by Side Diff: src/types.h

Issue 2309823002: [turbofan] put src/types.[h/cc] into src/compiler/types.[h/cc] (Closed)
Patch Set: Updates/comments. Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/property-details.h ('k') | src/types.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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_TYPES_H_
6 #define V8_TYPES_H_
7
8 #include "src/conversions.h"
9 #include "src/handles.h"
10 #include "src/objects.h"
11 #include "src/ostreams.h"
12
13 namespace v8 {
14 namespace internal {
15
16 // SUMMARY
17 //
18 // A simple type system for compiler-internal use. It is based entirely on
19 // union types, and all subtyping hence amounts to set inclusion. Besides the
20 // obvious primitive types and some predefined unions, the type language also
21 // can express class types (a.k.a. specific maps) and singleton types (i.e.,
22 // concrete constants).
23 //
24 // Types consist of two dimensions: semantic (value range) and representation.
25 // Both are related through subtyping.
26 //
27 //
28 // SEMANTIC DIMENSION
29 //
30 // The following equations and inequations hold for the semantic axis:
31 //
32 // None <= T
33 // T <= Any
34 //
35 // Number = Signed32 \/ Unsigned32 \/ Double
36 // Smi <= Signed32
37 // Name = String \/ Symbol
38 // UniqueName = InternalizedString \/ Symbol
39 // InternalizedString < String
40 //
41 // Receiver = Object \/ Proxy
42 // RegExp < Object
43 // OtherUndetectable < Object
44 // DetectableReceiver = Receiver - OtherUndetectable
45 //
46 // Constant(x) < T iff instance_type(map(x)) < T
47 //
48 //
49 // REPRESENTATIONAL DIMENSION
50 //
51 // For the representation axis, the following holds:
52 //
53 // None <= R
54 // R <= Any
55 //
56 // UntaggedInt = UntaggedInt1 \/ UntaggedInt8 \/
57 // UntaggedInt16 \/ UntaggedInt32
58 // UntaggedFloat = UntaggedFloat32 \/ UntaggedFloat64
59 // UntaggedNumber = UntaggedInt \/ UntaggedFloat
60 // Untagged = UntaggedNumber \/ UntaggedPtr
61 // Tagged = TaggedInt \/ TaggedPtr
62 //
63 // Subtyping relates the two dimensions, for example:
64 //
65 // Number <= Tagged \/ UntaggedNumber
66 // Object <= TaggedPtr \/ UntaggedPtr
67 //
68 // That holds because the semantic type constructors defined by the API create
69 // types that allow for all possible representations, and dually, the ones for
70 // representation types initially include all semantic ranges. Representations
71 // can then e.g. be narrowed for a given semantic type using intersection:
72 //
73 // SignedSmall /\ TaggedInt (a 'smi')
74 // Number /\ TaggedPtr (a heap number)
75 //
76 //
77 // RANGE TYPES
78 //
79 // A range type represents a continuous integer interval by its minimum and
80 // maximum value. Either value may be an infinity, in which case that infinity
81 // itself is also included in the range. A range never contains NaN or -0.
82 //
83 // If a value v happens to be an integer n, then Constant(v) is considered a
84 // subtype of Range(n, n) (and therefore also a subtype of any larger range).
85 // In order to avoid large unions, however, it is usually a good idea to use
86 // Range rather than Constant.
87 //
88 //
89 // PREDICATES
90 //
91 // There are two main functions for testing types:
92 //
93 // T1->Is(T2) -- tests whether T1 is included in T2 (i.e., T1 <= T2)
94 // T1->Maybe(T2) -- tests whether T1 and T2 overlap (i.e., T1 /\ T2 =/= 0)
95 //
96 // Typically, the former is to be used to select representations (e.g., via
97 // T->Is(SignedSmall())), and the latter to check whether a specific case needs
98 // handling (e.g., via T->Maybe(Number())).
99 //
100 // There is no functionality to discover whether a type is a leaf in the
101 // lattice. That is intentional. It should always be possible to refine the
102 // lattice (e.g., splitting up number types further) without invalidating any
103 // existing assumptions or tests.
104 // Consequently, do not normally use Equals for type tests, always use Is!
105 //
106 // The NowIs operator implements state-sensitive subtying, as described above.
107 // Any compilation decision based on such temporary properties requires runtime
108 // guarding!
109 //
110 //
111 // PROPERTIES
112 //
113 // Various formal properties hold for constructors, operators, and predicates
114 // over types. For example, constructors are injective and subtyping is a
115 // complete partial order.
116 //
117 // See test/cctest/test-types.cc for a comprehensive executable specification,
118 // especially with respect to the properties of the more exotic 'temporal'
119 // constructors and predicates (those prefixed 'Now').
120 //
121 //
122 // IMPLEMENTATION
123 //
124 // Internally, all 'primitive' types, and their unions, are represented as
125 // bitsets. Bit 0 is reserved for tagging. Only structured types require
126 // allocation.
127 // Note that the bitset representation is closed under both Union and Intersect.
128
129 // -----------------------------------------------------------------------------
130 // Values for bitset types
131
132 // clang-format off
133
134 #define MASK_BITSET_TYPE_LIST(V) \
135 V(Representation, 0xffc00000u) \
136 V(Semantic, 0x003ffffeu)
137
138 #define REPRESENTATION(k) ((k) & BitsetType::kRepresentation)
139 #define SEMANTIC(k) ((k) & BitsetType::kSemantic)
140
141 #define REPRESENTATION_BITSET_TYPE_LIST(V) \
142 V(None, 0) \
143 V(UntaggedBit, 1u << 22 | kSemantic) \
144 V(UntaggedIntegral8, 1u << 23 | kSemantic) \
145 V(UntaggedIntegral16, 1u << 24 | kSemantic) \
146 V(UntaggedIntegral32, 1u << 25 | kSemantic) \
147 V(UntaggedFloat32, 1u << 26 | kSemantic) \
148 V(UntaggedFloat64, 1u << 27 | kSemantic) \
149 V(UntaggedSimd128, 1u << 28 | kSemantic) \
150 V(UntaggedPointer, 1u << 29 | kSemantic) \
151 V(TaggedSigned, 1u << 30 | kSemantic) \
152 V(TaggedPointer, 1u << 31 | kSemantic) \
153 \
154 V(UntaggedIntegral, kUntaggedBit | kUntaggedIntegral8 | \
155 kUntaggedIntegral16 | kUntaggedIntegral32) \
156 V(UntaggedFloat, kUntaggedFloat32 | kUntaggedFloat64) \
157 V(UntaggedNumber, kUntaggedIntegral | kUntaggedFloat) \
158 V(Untagged, kUntaggedNumber | kUntaggedPointer) \
159 V(Tagged, kTaggedSigned | kTaggedPointer)
160
161 #define INTERNAL_BITSET_TYPE_LIST(V) \
162 V(OtherUnsigned31, 1u << 1 | REPRESENTATION(kTagged | kUntaggedNumber)) \
163 V(OtherUnsigned32, 1u << 2 | REPRESENTATION(kTagged | kUntaggedNumber)) \
164 V(OtherSigned32, 1u << 3 | REPRESENTATION(kTagged | kUntaggedNumber)) \
165 V(OtherNumber, 1u << 4 | REPRESENTATION(kTagged | kUntaggedNumber))
166
167 #define SEMANTIC_BITSET_TYPE_LIST(V) \
168 V(Negative31, 1u << 5 | REPRESENTATION(kTagged | kUntaggedNumber)) \
169 V(Null, 1u << 6 | REPRESENTATION(kTaggedPointer)) \
170 V(Undefined, 1u << 7 | REPRESENTATION(kTaggedPointer)) \
171 V(Boolean, 1u << 8 | REPRESENTATION(kTaggedPointer)) \
172 V(Unsigned30, 1u << 9 | REPRESENTATION(kTagged | kUntaggedNumber)) \
173 V(MinusZero, 1u << 10 | REPRESENTATION(kTagged | kUntaggedNumber)) \
174 V(NaN, 1u << 11 | REPRESENTATION(kTagged | kUntaggedNumber)) \
175 V(Symbol, 1u << 12 | REPRESENTATION(kTaggedPointer)) \
176 V(InternalizedString, 1u << 13 | REPRESENTATION(kTaggedPointer)) \
177 V(OtherString, 1u << 14 | REPRESENTATION(kTaggedPointer)) \
178 V(Simd, 1u << 15 | REPRESENTATION(kTaggedPointer)) \
179 V(OtherObject, 1u << 17 | REPRESENTATION(kTaggedPointer)) \
180 V(OtherUndetectable, 1u << 16 | REPRESENTATION(kTaggedPointer)) \
181 V(Proxy, 1u << 18 | REPRESENTATION(kTaggedPointer)) \
182 V(Function, 1u << 19 | REPRESENTATION(kTaggedPointer)) \
183 V(Hole, 1u << 20 | REPRESENTATION(kTaggedPointer)) \
184 V(OtherInternal, 1u << 21 | REPRESENTATION(kTagged | kUntagged)) \
185 \
186 V(Signed31, kUnsigned30 | kNegative31) \
187 V(Signed32, kSigned31 | kOtherUnsigned31 | kOtherSigned32) \
188 V(Signed32OrMinusZero, kSigned32 | kMinusZero) \
189 V(Signed32OrMinusZeroOrNaN, kSigned32 | kMinusZero | kNaN) \
190 V(Negative32, kNegative31 | kOtherSigned32) \
191 V(Unsigned31, kUnsigned30 | kOtherUnsigned31) \
192 V(Unsigned32, kUnsigned30 | kOtherUnsigned31 | \
193 kOtherUnsigned32) \
194 V(Unsigned32OrMinusZero, kUnsigned32 | kMinusZero) \
195 V(Unsigned32OrMinusZeroOrNaN, kUnsigned32 | kMinusZero | kNaN) \
196 V(Integral32, kSigned32 | kUnsigned32) \
197 V(PlainNumber, kIntegral32 | kOtherNumber) \
198 V(OrderedNumber, kPlainNumber | kMinusZero) \
199 V(MinusZeroOrNaN, kMinusZero | kNaN) \
200 V(Number, kOrderedNumber | kNaN) \
201 V(String, kInternalizedString | kOtherString) \
202 V(UniqueName, kSymbol | kInternalizedString) \
203 V(Name, kSymbol | kString) \
204 V(BooleanOrNumber, kBoolean | kNumber) \
205 V(BooleanOrNullOrNumber, kBooleanOrNumber | kNull) \
206 V(BooleanOrNullOrUndefined, kBoolean | kNull | kUndefined) \
207 V(NullOrNumber, kNull | kNumber) \
208 V(NullOrUndefined, kNull | kUndefined) \
209 V(Undetectable, kNullOrUndefined | kOtherUndetectable) \
210 V(NumberOrOddball, kNumber | kNullOrUndefined | kBoolean | kHole) \
211 V(NumberOrSimdOrString, kNumber | kSimd | kString) \
212 V(NumberOrString, kNumber | kString) \
213 V(NumberOrUndefined, kNumber | kUndefined) \
214 V(PlainPrimitive, kNumberOrString | kBoolean | kNullOrUndefined) \
215 V(Primitive, kSymbol | kSimd | kPlainPrimitive) \
216 V(DetectableReceiver, kFunction | kOtherObject | kProxy) \
217 V(Object, kFunction | kOtherObject | kOtherUndetectable) \
218 V(Receiver, kObject | kProxy) \
219 V(StringOrReceiver, kString | kReceiver) \
220 V(Unique, kBoolean | kUniqueName | kNull | kUndefined | \
221 kReceiver) \
222 V(Internal, kHole | kOtherInternal) \
223 V(NonInternal, kPrimitive | kReceiver) \
224 V(NonNumber, kUnique | kString | kInternal) \
225 V(Any, 0xfffffffeu)
226
227 // clang-format on
228
229 /*
230 * The following diagrams show how integers (in the mathematical sense) are
231 * divided among the different atomic numerical types.
232 *
233 * ON OS32 N31 U30 OU31 OU32 ON
234 * ______[_______[_______[_______[_______[_______[_______
235 * -2^31 -2^30 0 2^30 2^31 2^32
236 *
237 * E.g., OtherUnsigned32 (OU32) covers all integers from 2^31 to 2^32-1.
238 *
239 * Some of the atomic numerical bitsets are internal only (see
240 * INTERNAL_BITSET_TYPE_LIST). To a types user, they should only occur in
241 * union with certain other bitsets. For instance, OtherNumber should only
242 * occur as part of PlainNumber.
243 */
244
245 #define PROPER_BITSET_TYPE_LIST(V) \
246 REPRESENTATION_BITSET_TYPE_LIST(V) \
247 SEMANTIC_BITSET_TYPE_LIST(V)
248
249 #define BITSET_TYPE_LIST(V) \
250 MASK_BITSET_TYPE_LIST(V) \
251 REPRESENTATION_BITSET_TYPE_LIST(V) \
252 INTERNAL_BITSET_TYPE_LIST(V) \
253 SEMANTIC_BITSET_TYPE_LIST(V)
254
255 class Type;
256
257 // -----------------------------------------------------------------------------
258 // Bitset types (internal).
259
260 class BitsetType {
261 public:
262 typedef uint32_t bitset; // Internal
263
264 enum : uint32_t {
265 #define DECLARE_TYPE(type, value) k##type = (value),
266 BITSET_TYPE_LIST(DECLARE_TYPE)
267 #undef DECLARE_TYPE
268 kUnusedEOL = 0
269 };
270
271 static bitset SignedSmall();
272 static bitset UnsignedSmall();
273
274 bitset Bitset() {
275 return static_cast<bitset>(reinterpret_cast<uintptr_t>(this) ^ 1u);
276 }
277
278 static bool IsInhabited(bitset bits) {
279 return SEMANTIC(bits) != kNone && REPRESENTATION(bits) != kNone;
280 }
281
282 static bool SemanticIsInhabited(bitset bits) {
283 return SEMANTIC(bits) != kNone;
284 }
285
286 static bool Is(bitset bits1, bitset bits2) {
287 return (bits1 | bits2) == bits2;
288 }
289
290 static double Min(bitset);
291 static double Max(bitset);
292
293 static bitset Glb(Type* type); // greatest lower bound that's a bitset
294 static bitset Glb(double min, double max);
295 static bitset Lub(Type* type); // least upper bound that's a bitset
296 static bitset Lub(i::Map* map);
297 static bitset Lub(i::Object* value);
298 static bitset Lub(double value);
299 static bitset Lub(double min, double max);
300 static bitset ExpandInternals(bitset bits);
301
302 static const char* Name(bitset);
303 static void Print(std::ostream& os, bitset); // NOLINT
304 #ifdef DEBUG
305 static void Print(bitset);
306 #endif
307
308 static bitset NumberBits(bitset bits);
309
310 static bool IsBitset(Type* type) {
311 return reinterpret_cast<uintptr_t>(type) & 1;
312 }
313
314 static Type* NewForTesting(bitset bits) { return New(bits); }
315
316 private:
317 friend class Type;
318
319 static Type* New(bitset bits) {
320 return reinterpret_cast<Type*>(static_cast<uintptr_t>(bits | 1u));
321 }
322
323 struct Boundary {
324 bitset internal;
325 bitset external;
326 double min;
327 };
328 static const Boundary BoundariesArray[];
329 static inline const Boundary* Boundaries();
330 static inline size_t BoundariesSize();
331 };
332
333 // -----------------------------------------------------------------------------
334 // Superclass for non-bitset types (internal).
335 class TypeBase {
336 protected:
337 friend class Type;
338
339 enum Kind {
340 kConstant,
341 kTuple,
342 kUnion,
343 kRange
344 };
345
346 Kind kind() const { return kind_; }
347 explicit TypeBase(Kind kind) : kind_(kind) {}
348
349 static bool IsKind(Type* type, Kind kind) {
350 if (BitsetType::IsBitset(type)) return false;
351 TypeBase* base = reinterpret_cast<TypeBase*>(type);
352 return base->kind() == kind;
353 }
354
355 // The hacky conversion to/from Type*.
356 static Type* AsType(TypeBase* type) { return reinterpret_cast<Type*>(type); }
357 static TypeBase* FromType(Type* type) {
358 return reinterpret_cast<TypeBase*>(type);
359 }
360
361 private:
362 Kind kind_;
363 };
364
365 // -----------------------------------------------------------------------------
366 // Constant types.
367
368 class ConstantType : public TypeBase {
369 public:
370 i::Handle<i::Object> Value() { return object_; }
371
372 private:
373 friend class Type;
374 friend class BitsetType;
375
376 static Type* New(i::Handle<i::Object> value, Zone* zone) {
377 BitsetType::bitset bitset = BitsetType::Lub(*value);
378 return AsType(new (zone->New(sizeof(ConstantType)))
379 ConstantType(bitset, value));
380 }
381
382 static ConstantType* cast(Type* type) {
383 DCHECK(IsKind(type, kConstant));
384 return static_cast<ConstantType*>(FromType(type));
385 }
386
387 ConstantType(BitsetType::bitset bitset, i::Handle<i::Object> object)
388 : TypeBase(kConstant), bitset_(bitset), object_(object) {}
389
390 BitsetType::bitset Lub() { return bitset_; }
391
392 BitsetType::bitset bitset_;
393 Handle<i::Object> object_;
394 };
395 // TODO(neis): Also cache value if numerical.
396 // TODO(neis): Allow restricting the representation.
397
398 // -----------------------------------------------------------------------------
399 // Range types.
400
401 class RangeType : public TypeBase {
402 public:
403 struct Limits {
404 double min;
405 double max;
406 Limits(double min, double max) : min(min), max(max) {}
407 explicit Limits(RangeType* range) : min(range->Min()), max(range->Max()) {}
408 bool IsEmpty();
409 static Limits Empty() { return Limits(1, 0); }
410 static Limits Intersect(Limits lhs, Limits rhs);
411 static Limits Union(Limits lhs, Limits rhs);
412 };
413
414 double Min() { return limits_.min; }
415 double Max() { return limits_.max; }
416
417 private:
418 friend class Type;
419 friend class BitsetType;
420 friend class UnionType;
421
422 static Type* New(double min, double max, BitsetType::bitset representation,
423 Zone* zone) {
424 return New(Limits(min, max), representation, zone);
425 }
426
427 static bool IsInteger(double x) {
428 return nearbyint(x) == x && !i::IsMinusZero(x); // Allows for infinities.
429 }
430
431 static Type* New(Limits lim, BitsetType::bitset representation, Zone* zone) {
432 DCHECK(IsInteger(lim.min) && IsInteger(lim.max));
433 DCHECK(lim.min <= lim.max);
434 DCHECK(REPRESENTATION(representation) == representation);
435 BitsetType::bitset bits =
436 SEMANTIC(BitsetType::Lub(lim.min, lim.max)) | representation;
437
438 return AsType(new (zone->New(sizeof(RangeType))) RangeType(bits, lim));
439 }
440
441 static RangeType* cast(Type* type) {
442 DCHECK(IsKind(type, kRange));
443 return static_cast<RangeType*>(FromType(type));
444 }
445
446 RangeType(BitsetType::bitset bitset, Limits limits)
447 : TypeBase(kRange), bitset_(bitset), limits_(limits) {}
448
449 BitsetType::bitset Lub() { return bitset_; }
450
451 BitsetType::bitset bitset_;
452 Limits limits_;
453 };
454
455 // -----------------------------------------------------------------------------
456 // Superclass for types with variable number of type fields.
457 class StructuralType : public TypeBase {
458 public:
459 int LengthForTesting() { return Length(); }
460
461 protected:
462 friend class Type;
463
464 int Length() { return length_; }
465
466 Type* Get(int i) {
467 DCHECK(0 <= i && i < this->Length());
468 return elements_[i];
469 }
470
471 void Set(int i, Type* type) {
472 DCHECK(0 <= i && i < this->Length());
473 elements_[i] = type;
474 }
475
476 void Shrink(int length) {
477 DCHECK(2 <= length && length <= this->Length());
478 length_ = length;
479 }
480
481 StructuralType(Kind kind, int length, i::Zone* zone)
482 : TypeBase(kind), length_(length) {
483 elements_ = reinterpret_cast<Type**>(zone->New(sizeof(Type*) * length));
484 }
485
486 private:
487 int length_;
488 Type** elements_;
489 };
490
491 // -----------------------------------------------------------------------------
492 // Tuple types.
493
494 class TupleType : public StructuralType {
495 public:
496 int Arity() { return this->Length(); }
497 Type* Element(int i) { return this->Get(i); }
498
499 void InitElement(int i, Type* type) { this->Set(i, type); }
500
501 private:
502 friend class Type;
503
504 TupleType(int length, Zone* zone) : StructuralType(kTuple, length, zone) {}
505
506 static Type* New(int length, Zone* zone) {
507 return AsType(new (zone->New(sizeof(TupleType))) TupleType(length, zone));
508 }
509
510 static TupleType* cast(Type* type) {
511 DCHECK(IsKind(type, kTuple));
512 return static_cast<TupleType*>(FromType(type));
513 }
514 };
515
516 // -----------------------------------------------------------------------------
517 // Union types (internal).
518 // A union is a structured type with the following invariants:
519 // - its length is at least 2
520 // - at most one field is a bitset, and it must go into index 0
521 // - no field is a union
522 // - no field is a subtype of any other field
523 class UnionType : public StructuralType {
524 private:
525 friend Type;
526 friend BitsetType;
527
528 UnionType(int length, Zone* zone) : StructuralType(kUnion, length, zone) {}
529
530 static Type* New(int length, Zone* zone) {
531 return AsType(new (zone->New(sizeof(UnionType))) UnionType(length, zone));
532 }
533
534 static UnionType* cast(Type* type) {
535 DCHECK(IsKind(type, kUnion));
536 return static_cast<UnionType*>(FromType(type));
537 }
538
539 bool Wellformed();
540 };
541
542 class Type {
543 public:
544 typedef BitsetType::bitset bitset; // Internal
545
546 // Constructors.
547 #define DEFINE_TYPE_CONSTRUCTOR(type, value) \
548 static Type* type() { return BitsetType::New(BitsetType::k##type); }
549 PROPER_BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR)
550 #undef DEFINE_TYPE_CONSTRUCTOR
551
552 static Type* SignedSmall() {
553 return BitsetType::New(BitsetType::SignedSmall());
554 }
555 static Type* UnsignedSmall() {
556 return BitsetType::New(BitsetType::UnsignedSmall());
557 }
558
559 static Type* Constant(i::Handle<i::Object> value, Zone* zone) {
560 return ConstantType::New(value, zone);
561 }
562 static Type* Range(double min, double max, Zone* zone) {
563 return RangeType::New(min, max, REPRESENTATION(BitsetType::kTagged |
564 BitsetType::kUntaggedNumber),
565 zone);
566 }
567 static Type* Tuple(Type* first, Type* second, Type* third, Zone* zone) {
568 Type* tuple = TupleType::New(3, zone);
569 tuple->AsTuple()->InitElement(0, first);
570 tuple->AsTuple()->InitElement(1, second);
571 tuple->AsTuple()->InitElement(2, third);
572 return tuple;
573 }
574
575 static Type* Union(Type* type1, Type* type2, Zone* zone);
576 static Type* Intersect(Type* type1, Type* type2, Zone* zone);
577
578 static Type* Of(double value, Zone* zone) {
579 return BitsetType::New(BitsetType::ExpandInternals(BitsetType::Lub(value)));
580 }
581 static Type* Of(i::Object* value, Zone* zone) {
582 return BitsetType::New(BitsetType::ExpandInternals(BitsetType::Lub(value)));
583 }
584 static Type* Of(i::Handle<i::Object> value, Zone* zone) {
585 return Of(*value, zone);
586 }
587
588 static Type* For(i::Map* map) {
589 return BitsetType::New(BitsetType::ExpandInternals(BitsetType::Lub(map)));
590 }
591 static Type* For(i::Handle<i::Map> map) { return For(*map); }
592
593 // Extraction of components.
594 static Type* Representation(Type* t, Zone* zone);
595 static Type* Semantic(Type* t, Zone* zone);
596
597 // Predicates.
598 bool IsInhabited() { return BitsetType::IsInhabited(this->BitsetLub()); }
599
600 bool Is(Type* that) { return this == that || this->SlowIs(that); }
601 bool Maybe(Type* that);
602 bool Equals(Type* that) { return this->Is(that) && that->Is(this); }
603
604 // Equivalent to Constant(val)->Is(this), but avoiding allocation.
605 bool Contains(i::Object* val);
606 bool Contains(i::Handle<i::Object> val) { return this->Contains(*val); }
607
608 // Inspection.
609 bool IsRange() { return IsKind(TypeBase::kRange); }
610 bool IsConstant() { return IsKind(TypeBase::kConstant); }
611 bool IsTuple() { return IsKind(TypeBase::kTuple); }
612
613 ConstantType* AsConstant() { return ConstantType::cast(this); }
614 RangeType* AsRange() { return RangeType::cast(this); }
615 TupleType* AsTuple() { return TupleType::cast(this); }
616
617 // Minimum and maximum of a numeric type.
618 // These functions do not distinguish between -0 and +0. If the type equals
619 // kNaN, they return NaN; otherwise kNaN is ignored. Only call these
620 // functions on subtypes of Number.
621 double Min();
622 double Max();
623
624 // Extracts a range from the type: if the type is a range or a union
625 // containing a range, that range is returned; otherwise, NULL is returned.
626 Type* GetRange();
627
628 static bool IsInteger(i::Object* x);
629 static bool IsInteger(double x) {
630 return nearbyint(x) == x && !i::IsMinusZero(x); // Allows for infinities.
631 }
632
633 int NumConstants();
634
635 template <class T>
636 class Iterator {
637 public:
638 bool Done() const { return index_ < 0; }
639 i::Handle<T> Current();
640 void Advance();
641
642 private:
643 friend class Type;
644
645 Iterator() : index_(-1) {}
646 explicit Iterator(Type* type) : type_(type), index_(-1) { Advance(); }
647
648 inline bool matches(Type* type);
649 inline Type* get_type();
650
651 Type* type_;
652 int index_;
653 };
654
655 Iterator<i::Object> Constants() {
656 if (this->IsBitset()) return Iterator<i::Object>();
657 return Iterator<i::Object>(this);
658 }
659
660 // Printing.
661
662 enum PrintDimension { BOTH_DIMS, SEMANTIC_DIM, REPRESENTATION_DIM };
663
664 void PrintTo(std::ostream& os, PrintDimension dim = BOTH_DIMS); // NOLINT
665
666 #ifdef DEBUG
667 void Print();
668 #endif
669
670 // Helpers for testing.
671 bool IsBitsetForTesting() { return IsBitset(); }
672 bool IsUnionForTesting() { return IsUnion(); }
673 bitset AsBitsetForTesting() { return AsBitset(); }
674 UnionType* AsUnionForTesting() { return AsUnion(); }
675
676 private:
677 // Friends.
678 template <class>
679 friend class Iterator;
680 friend BitsetType;
681 friend UnionType;
682
683 // Internal inspection.
684 bool IsKind(TypeBase::Kind kind) { return TypeBase::IsKind(this, kind); }
685
686 bool IsNone() { return this == None(); }
687 bool IsAny() { return this == Any(); }
688 bool IsBitset() { return BitsetType::IsBitset(this); }
689 bool IsUnion() { return IsKind(TypeBase::kUnion); }
690
691 bitset AsBitset() {
692 DCHECK(this->IsBitset());
693 return reinterpret_cast<BitsetType*>(this)->Bitset();
694 }
695 UnionType* AsUnion() { return UnionType::cast(this); }
696
697 bitset Representation();
698
699 // Auxiliary functions.
700 bool SemanticMaybe(Type* that);
701
702 bitset BitsetGlb() { return BitsetType::Glb(this); }
703 bitset BitsetLub() { return BitsetType::Lub(this); }
704
705 bool SlowIs(Type* that);
706 bool SemanticIs(Type* that);
707
708 static bool Overlap(RangeType* lhs, RangeType* rhs);
709 static bool Contains(RangeType* lhs, RangeType* rhs);
710 static bool Contains(RangeType* range, ConstantType* constant);
711 static bool Contains(RangeType* range, i::Object* val);
712
713 static int UpdateRange(Type* type, UnionType* result, int size, Zone* zone);
714
715 static RangeType::Limits IntersectRangeAndBitset(Type* range, Type* bits,
716 Zone* zone);
717 static RangeType::Limits ToLimits(bitset bits, Zone* zone);
718
719 bool SimplyEquals(Type* that);
720
721 static int AddToUnion(Type* type, UnionType* result, int size, Zone* zone);
722 static int IntersectAux(Type* type, Type* other, UnionType* result, int size,
723 RangeType::Limits* limits, Zone* zone);
724 static Type* NormalizeUnion(Type* unioned, int size, Zone* zone);
725 static Type* NormalizeRangeAndBitset(Type* range, bitset* bits, Zone* zone);
726 };
727
728 // -----------------------------------------------------------------------------
729 // Type bounds. A simple struct to represent a pair of lower/upper types.
730
731 struct Bounds {
732 Type* lower;
733 Type* upper;
734
735 Bounds()
736 : // Make sure accessing uninitialized bounds crashes big-time.
737 lower(nullptr),
738 upper(nullptr) {}
739 explicit Bounds(Type* t) : lower(t), upper(t) {}
740 Bounds(Type* l, Type* u) : lower(l), upper(u) { DCHECK(lower->Is(upper)); }
741
742 // Unrestricted bounds.
743 static Bounds Unbounded() { return Bounds(Type::None(), Type::Any()); }
744
745 // Meet: both b1 and b2 are known to hold.
746 static Bounds Both(Bounds b1, Bounds b2, Zone* zone) {
747 Type* lower = Type::Union(b1.lower, b2.lower, zone);
748 Type* upper = Type::Intersect(b1.upper, b2.upper, zone);
749 // Lower bounds are considered approximate, correct as necessary.
750 if (!lower->Is(upper)) lower = upper;
751 return Bounds(lower, upper);
752 }
753
754 // Join: either b1 or b2 is known to hold.
755 static Bounds Either(Bounds b1, Bounds b2, Zone* zone) {
756 Type* lower = Type::Intersect(b1.lower, b2.lower, zone);
757 Type* upper = Type::Union(b1.upper, b2.upper, zone);
758 return Bounds(lower, upper);
759 }
760
761 static Bounds NarrowLower(Bounds b, Type* t, Zone* zone) {
762 Type* lower = Type::Union(b.lower, t, zone);
763 // Lower bounds are considered approximate, correct as necessary.
764 if (!lower->Is(b.upper)) lower = b.upper;
765 return Bounds(lower, b.upper);
766 }
767 static Bounds NarrowUpper(Bounds b, Type* t, Zone* zone) {
768 Type* lower = b.lower;
769 Type* upper = Type::Intersect(b.upper, t, zone);
770 // Lower bounds are considered approximate, correct as necessary.
771 if (!lower->Is(upper)) lower = upper;
772 return Bounds(lower, upper);
773 }
774
775 bool Narrows(Bounds that) {
776 return that.lower->Is(this->lower) && this->upper->Is(that.upper);
777 }
778 };
779 } // namespace internal
780 } // namespace v8
781
782 #endif // V8_TYPES_H_
OLDNEW
« no previous file with comments | « src/property-details.h ('k') | src/types.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698