OLD | NEW |
---|---|
1 // Copyright 2014 the V8 project authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef V8_TYPES_H_ | 5 #ifndef V8_TYPES_H_ |
6 #define V8_TYPES_H_ | 6 #define V8_TYPES_H_ |
7 | 7 |
8 #include "src/conversions.h" | |
8 #include "src/factory.h" | 9 #include "src/factory.h" |
9 #include "src/handles.h" | 10 #include "src/handles.h" |
10 #include "src/ostreams.h" | 11 #include "src/ostreams.h" |
11 | 12 |
12 namespace v8 { | 13 namespace v8 { |
13 namespace internal { | 14 namespace internal { |
14 | 15 |
15 // SUMMARY | 16 // SUMMARY |
16 // | 17 // |
17 // A simple type system for compiler-internal use. It is based entirely on | 18 // A simple type system for compiler-internal use. It is based entirely on |
18 // union types, and all subtyping hence amounts to set inclusion. Besides the | 19 // union types, and all subtyping hence amounts to set inclusion. Besides the |
19 // obvious primitive types and some predefined unions, the type language also | 20 // obvious primitive types and some predefined unions, the type language also |
20 // can express class types (a.k.a. specific maps) and singleton types (i.e., | 21 // can express class types (a.k.a. specific maps) and singleton types (i.e., |
21 // concrete constants). | 22 // concrete constants). |
22 // | 23 // |
23 // Types consist of two dimensions: semantic (value range) and representation. | 24 // Types consist of two dimensions: semantic (value range) and representation. |
24 // Both are related through subtyping. | 25 // Both are related through subtyping. |
25 // | 26 // |
27 // | |
26 // SEMANTIC DIMENSION | 28 // SEMANTIC DIMENSION |
27 // | 29 // |
28 // The following equations and inequations hold for the semantic axis: | 30 // The following equations and inequations hold for the semantic axis: |
29 // | 31 // |
30 // None <= T | 32 // None <= T |
31 // T <= Any | 33 // T <= Any |
32 // | 34 // |
33 // Number = Signed32 \/ Unsigned32 \/ Double | 35 // Number = Signed32 \/ Unsigned32 \/ Double |
34 // Smi <= Signed32 | 36 // Smi <= Signed32 |
35 // Name = String \/ Symbol | 37 // Name = String \/ Symbol |
(...skipping 18 matching lines...) Expand all Loading... | |
54 // There is no subtyping relation between Array, Function, or Context types | 56 // There is no subtyping relation between Array, Function, or Context types |
55 // and respective Constant types, since these types cannot be reconstructed | 57 // and respective Constant types, since these types cannot be reconstructed |
56 // for arbitrary heap values. | 58 // for arbitrary heap values. |
57 // Note also that Constant(x) < Class(map(x)) does _not_ hold, since x's map can | 59 // Note also that Constant(x) < Class(map(x)) does _not_ hold, since x's map can |
58 // change! (Its instance type cannot, however.) | 60 // change! (Its instance type cannot, however.) |
59 // TODO(rossberg): the latter is not currently true for proxies, because of fix, | 61 // TODO(rossberg): the latter is not currently true for proxies, because of fix, |
60 // but will hold once we implement direct proxies. | 62 // but will hold once we implement direct proxies. |
61 // However, we also define a 'temporal' variant of the subtyping relation that | 63 // However, we also define a 'temporal' variant of the subtyping relation that |
62 // considers the _current_ state only, i.e., Constant(x) <_now Class(map(x)). | 64 // considers the _current_ state only, i.e., Constant(x) <_now Class(map(x)). |
63 // | 65 // |
66 // | |
64 // REPRESENTATIONAL DIMENSION | 67 // REPRESENTATIONAL DIMENSION |
65 // | 68 // |
66 // For the representation axis, the following holds: | 69 // For the representation axis, the following holds: |
67 // | 70 // |
68 // None <= R | 71 // None <= R |
69 // R <= Any | 72 // R <= Any |
70 // | 73 // |
71 // UntaggedInt = UntaggedInt1 \/ UntaggedInt8 \/ | 74 // UntaggedInt = UntaggedInt1 \/ UntaggedInt8 \/ |
72 // UntaggedInt16 \/ UntaggedInt32 | 75 // UntaggedInt16 \/ UntaggedInt32 |
73 // UntaggedFloat = UntaggedFloat32 \/ UntaggedFloat64 | 76 // UntaggedFloat = UntaggedFloat32 \/ UntaggedFloat64 |
74 // UntaggedNumber = UntaggedInt \/ UntaggedFloat | 77 // UntaggedNumber = UntaggedInt \/ UntaggedFloat |
75 // Untagged = UntaggedNumber \/ UntaggedPtr | 78 // Untagged = UntaggedNumber \/ UntaggedPtr |
76 // Tagged = TaggedInt \/ TaggedPtr | 79 // Tagged = TaggedInt \/ TaggedPtr |
77 // | 80 // |
78 // Subtyping relates the two dimensions, for example: | 81 // Subtyping relates the two dimensions, for example: |
79 // | 82 // |
80 // Number <= Tagged \/ UntaggedNumber | 83 // Number <= Tagged \/ UntaggedNumber |
81 // Object <= TaggedPtr \/ UntaggedPtr | 84 // Object <= TaggedPtr \/ UntaggedPtr |
82 // | 85 // |
83 // That holds because the semantic type constructors defined by the API create | 86 // That holds because the semantic type constructors defined by the API create |
84 // types that allow for all possible representations, and dually, the ones for | 87 // types that allow for all possible representations, and dually, the ones for |
85 // representation types initially include all semantic ranges. Representations | 88 // representation types initially include all semantic ranges. Representations |
86 // can then e.g. be narrowed for a given semantic type using intersection: | 89 // can then e.g. be narrowed for a given semantic type using intersection: |
87 // | 90 // |
88 // SignedSmall /\ TaggedInt (a 'smi') | 91 // SignedSmall /\ TaggedInt (a 'smi') |
89 // Number /\ TaggedPtr (a heap number) | 92 // Number /\ TaggedPtr (a heap number) |
90 // | 93 // |
94 // | |
95 // RANGE TYPES | |
96 // | |
97 // A range type represents a continuous integer interval by its minimum and | |
98 // maximum value. Either value might be an infinity. | |
99 // | |
100 // Constant(v) is considered a subtype of Range(x..y) if v happens to be an | |
101 // integer between x and y. | |
102 // | |
103 // | |
91 // PREDICATES | 104 // PREDICATES |
92 // | 105 // |
93 // There are two main functions for testing types: | 106 // There are two main functions for testing types: |
94 // | 107 // |
95 // T1->Is(T2) -- tests whether T1 is included in T2 (i.e., T1 <= T2) | 108 // T1->Is(T2) -- tests whether T1 is included in T2 (i.e., T1 <= T2) |
96 // T1->Maybe(T2) -- tests whether T1 and T2 overlap (i.e., T1 /\ T2 =/= 0) | 109 // T1->Maybe(T2) -- tests whether T1 and T2 overlap (i.e., T1 /\ T2 =/= 0) |
97 // | 110 // |
98 // Typically, the former is to be used to select representations (e.g., via | 111 // Typically, the former is to be used to select representations (e.g., via |
99 // T->Is(SignedSmall())), and the latter to check whether a specific case needs | 112 // T->Is(SignedSmall())), and the latter to check whether a specific case needs |
100 // handling (e.g., via T->Maybe(Number())). | 113 // handling (e.g., via T->Maybe(Number())). |
101 // | 114 // |
102 // There is no functionality to discover whether a type is a leaf in the | 115 // There is no functionality to discover whether a type is a leaf in the |
103 // lattice. That is intentional. It should always be possible to refine the | 116 // lattice. That is intentional. It should always be possible to refine the |
104 // lattice (e.g., splitting up number types further) without invalidating any | 117 // lattice (e.g., splitting up number types further) without invalidating any |
105 // existing assumptions or tests. | 118 // existing assumptions or tests. |
106 // Consequently, do not normally use Equals for type tests, always use Is! | 119 // Consequently, do not normally use Equals for type tests, always use Is! |
107 // | 120 // |
108 // The NowIs operator implements state-sensitive subtying, as described above. | 121 // The NowIs operator implements state-sensitive subtying, as described above. |
109 // Any compilation decision based on such temporary properties requires runtime | 122 // Any compilation decision based on such temporary properties requires runtime |
110 // guarding! | 123 // guarding! |
111 // | 124 // |
125 // | |
112 // PROPERTIES | 126 // PROPERTIES |
113 // | 127 // |
114 // Various formal properties hold for constructors, operators, and predicates | 128 // Various formal properties hold for constructors, operators, and predicates |
115 // over types. For example, constructors are injective, subtyping is a complete | 129 // over types. For example, constructors are injective and subtyping is a |
116 // partial order, union and intersection satisfy the usual algebraic properties. | 130 // complete partial order. |
117 // | 131 // |
118 // See test/cctest/test-types.cc for a comprehensive executable specification, | 132 // See test/cctest/test-types.cc for a comprehensive executable specification, |
119 // especially with respect to the properties of the more exotic 'temporal' | 133 // especially with respect to the properties of the more exotic 'temporal' |
120 // constructors and predicates (those prefixed 'Now'). | 134 // constructors and predicates (those prefixed 'Now'). |
121 // | 135 // |
136 // | |
122 // IMPLEMENTATION | 137 // IMPLEMENTATION |
123 // | 138 // |
124 // Internally, all 'primitive' types, and their unions, are represented as | 139 // Internally, all 'primitive' types, and their unions, are represented as |
125 // bitsets. Class is a heap pointer to the respective map. Only Constant's, or | 140 // bitsets. Class is a heap pointer to the respective map. Only Constant's, or |
126 // unions containing Class'es or Constant's, currently require allocation. | 141 // unions containing Class'es or Constant's, currently require allocation. |
127 // Note that the bitset representation is closed under both Union and Intersect. | 142 // Note that the bitset representation is closed under both Union and Intersect. |
128 // | 143 // |
129 // There are two type representations, using different allocation: | 144 // There are two type representations, using different allocation: |
130 // | 145 // |
131 // - class Type (zone-allocated, for compiler and concurrent compilation) | 146 // - class Type (zone-allocated, for compiler and concurrent compilation) |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
201 V(Primitive, kNumber | kName | kBoolean | kNull | kUndefined) \ | 216 V(Primitive, kNumber | kName | kBoolean | kNull | kUndefined) \ |
202 V(DetectableObject, kArray | kFunction | kRegExp | kOtherObject) \ | 217 V(DetectableObject, kArray | kFunction | kRegExp | kOtherObject) \ |
203 V(DetectableReceiver, kDetectableObject | kProxy) \ | 218 V(DetectableReceiver, kDetectableObject | kProxy) \ |
204 V(Detectable, kDetectableReceiver | kNumber | kName) \ | 219 V(Detectable, kDetectableReceiver | kNumber | kName) \ |
205 V(Object, kDetectableObject | kUndetectable) \ | 220 V(Object, kDetectableObject | kUndetectable) \ |
206 V(Receiver, kObject | kProxy) \ | 221 V(Receiver, kObject | kProxy) \ |
207 V(NonNumber, kBoolean | kName | kNull | kReceiver | \ | 222 V(NonNumber, kBoolean | kName | kNull | kReceiver | \ |
208 kUndefined | kInternal) \ | 223 kUndefined | kInternal) \ |
209 V(Any, -1) | 224 V(Any, -1) |
210 | 225 |
226 /* | |
227 * The following diagrams show how integers (in the mathematical sense) are | |
228 * divided among the different atomic numerical types. | |
229 * | |
230 * If SmiValuesAre31Bits(): | |
231 * | |
232 * ON OS32 OSS US OU31 OU32 ON | |
233 * ______[_______[_______[_______[_______[_______[_______ | |
234 * -2^31 -2^30 0 2^30 2^31 2^32 | |
235 * | |
236 * Otherwise: | |
237 * | |
238 * ON OSS US OU32 ON | |
239 * ______[_______________[_______________[_______[_______ | |
240 * -2^31 0 2^31 2^32 | |
241 * | |
242 * | |
243 * E.g., OtherUnsigned32 (OU32) covers all integers from 2^31 to 2^32-1. | |
244 * | |
245 */ | |
246 | |
247 #define PROPER_BITSET_TYPE_LIST(V) \ | |
248 REPRESENTATION_BITSET_TYPE_LIST(V) \ | |
249 SEMANTIC_BITSET_TYPE_LIST(V) | |
250 | |
211 #define BITSET_TYPE_LIST(V) \ | 251 #define BITSET_TYPE_LIST(V) \ |
212 MASK_BITSET_TYPE_LIST(V) \ | 252 MASK_BITSET_TYPE_LIST(V) \ |
213 REPRESENTATION_BITSET_TYPE_LIST(V) \ | 253 PROPER_BITSET_TYPE_LIST(V) |
214 SEMANTIC_BITSET_TYPE_LIST(V) | |
215 | 254 |
216 | 255 |
217 // ----------------------------------------------------------------------------- | 256 // ----------------------------------------------------------------------------- |
218 // The abstract Type class, parameterized over the low-level representation. | 257 // The abstract Type class, parameterized over the low-level representation. |
219 | 258 |
220 // struct Config { | 259 // struct Config { |
221 // typedef TypeImpl<Config> Type; | 260 // typedef TypeImpl<Config> Type; |
222 // typedef Base; | 261 // typedef Base; |
223 // typedef Struct; | 262 // typedef Struct; |
224 // typedef Region; | 263 // typedef Region; |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
272 typedef typename Config::template Handle<UnionType>::type UnionHandle; | 311 typedef typename Config::template Handle<UnionType>::type UnionHandle; |
273 typedef typename Config::Region Region; | 312 typedef typename Config::Region Region; |
274 | 313 |
275 // Constructors. | 314 // Constructors. |
276 | 315 |
277 #define DEFINE_TYPE_CONSTRUCTOR(type, value) \ | 316 #define DEFINE_TYPE_CONSTRUCTOR(type, value) \ |
278 static TypeImpl* type() { return BitsetType::New(BitsetType::k##type); } \ | 317 static TypeImpl* type() { return BitsetType::New(BitsetType::k##type); } \ |
279 static TypeHandle type(Region* region) { \ | 318 static TypeHandle type(Region* region) { \ |
280 return BitsetType::New(BitsetType::k##type, region); \ | 319 return BitsetType::New(BitsetType::k##type, region); \ |
281 } | 320 } |
282 BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR) | 321 PROPER_BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR) |
283 #undef DEFINE_TYPE_CONSTRUCTOR | 322 #undef DEFINE_TYPE_CONSTRUCTOR |
284 | 323 |
285 static TypeHandle Class(i::Handle<i::Map> map, Region* region) { | 324 static TypeHandle Class(i::Handle<i::Map> map, Region* region) { |
286 return ClassType::New(map, region); | 325 return ClassType::New(map, region); |
287 } | 326 } |
288 static TypeHandle Constant(i::Handle<i::Object> value, Region* region) { | 327 static TypeHandle Constant(i::Handle<i::Object> value, Region* region) { |
289 // TODO(neis): Return RangeType for numerical values. | |
290 return ConstantType::New(value, region); | 328 return ConstantType::New(value, region); |
291 } | 329 } |
292 static TypeHandle Range(double min, double max, Region* region) { | 330 static TypeHandle Range( |
331 i::Handle<i::Object> min, i::Handle<i::Object> max, Region* region) { | |
293 return RangeType::New(min, max, region); | 332 return RangeType::New(min, max, region); |
294 } | 333 } |
295 static TypeHandle Context(TypeHandle outer, Region* region) { | 334 static TypeHandle Context(TypeHandle outer, Region* region) { |
296 return ContextType::New(outer, region); | 335 return ContextType::New(outer, region); |
297 } | 336 } |
298 static TypeHandle Array(TypeHandle element, Region* region) { | 337 static TypeHandle Array(TypeHandle element, Region* region) { |
299 return ArrayType::New(element, region); | 338 return ArrayType::New(element, region); |
300 } | 339 } |
301 static FunctionHandle Function( | 340 static FunctionHandle Function( |
302 TypeHandle result, TypeHandle receiver, int arity, Region* region) { | 341 TypeHandle result, TypeHandle receiver, int arity, Region* region) { |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
350 bool Is(TypeHandle that) { return this->Is(*that); } | 389 bool Is(TypeHandle that) { return this->Is(*that); } |
351 | 390 |
352 bool Maybe(TypeImpl* that); | 391 bool Maybe(TypeImpl* that); |
353 template<class TypeHandle> | 392 template<class TypeHandle> |
354 bool Maybe(TypeHandle that) { return this->Maybe(*that); } | 393 bool Maybe(TypeHandle that) { return this->Maybe(*that); } |
355 | 394 |
356 bool Equals(TypeImpl* that) { return this->Is(that) && that->Is(this); } | 395 bool Equals(TypeImpl* that) { return this->Is(that) && that->Is(this); } |
357 template<class TypeHandle> | 396 template<class TypeHandle> |
358 bool Equals(TypeHandle that) { return this->Equals(*that); } | 397 bool Equals(TypeHandle that) { return this->Equals(*that); } |
359 | 398 |
360 // Equivalent to Constant(value)->Is(this), but avoiding allocation. | 399 // Equivalent to Constant(val)->Is(this), but avoiding allocation. |
361 bool Contains(i::Object* val); | 400 bool Contains(i::Object* val); |
362 bool Contains(i::Handle<i::Object> val) { return this->Contains(*val); } | 401 bool Contains(i::Handle<i::Object> val) { return this->Contains(*val); } |
363 | 402 |
364 // State-dependent versions of the above that consider subtyping between | 403 // State-dependent versions of the above that consider subtyping between |
365 // a constant and its map class. | 404 // a constant and its map class. |
366 inline static TypeHandle NowOf(i::Object* value, Region* region); | 405 inline static TypeHandle NowOf(i::Object* value, Region* region); |
367 static TypeHandle NowOf(i::Handle<i::Object> value, Region* region) { | 406 static TypeHandle NowOf(i::Handle<i::Object> value, Region* region) { |
368 return NowOf(*value, region); | 407 return NowOf(*value, region); |
369 } | 408 } |
370 bool NowIs(TypeImpl* that); | 409 bool NowIs(TypeImpl* that); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
459 int AsBitset() { | 498 int AsBitset() { |
460 DCHECK(this->IsBitset()); | 499 DCHECK(this->IsBitset()); |
461 return static_cast<BitsetType*>(this)->Bitset(); | 500 return static_cast<BitsetType*>(this)->Bitset(); |
462 } | 501 } |
463 UnionType* AsUnion() { return UnionType::cast(this); } | 502 UnionType* AsUnion() { return UnionType::cast(this); } |
464 | 503 |
465 // Auxiliary functions. | 504 // Auxiliary functions. |
466 | 505 |
467 int BitsetGlb() { return BitsetType::Glb(this); } | 506 int BitsetGlb() { return BitsetType::Glb(this); } |
468 int BitsetLub() { return BitsetType::Lub(this); } | 507 int BitsetLub() { return BitsetType::Lub(this); } |
469 int InherentBitsetLub() { return BitsetType::InherentLub(this); } | |
470 | 508 |
471 bool SlowIs(TypeImpl* that); | 509 bool SlowIs(TypeImpl* that); |
472 | 510 |
473 TypeHandle Rebound(int bitset, Region* region); | 511 static bool IsInteger(double x) { |
474 int BoundBy(TypeImpl* that); | 512 return nearbyint(x) == x && !i::IsMinusZero(x); // Allows for infinities. |
475 int IndexInUnion(int bound, UnionHandle unioned, int current_size); | 513 } |
476 static int ExtendUnion( | 514 static bool IsInteger(i::Object* x) { |
477 UnionHandle unioned, int current_size, TypeHandle t, | 515 return x->IsNumber() && IsInteger(x->Number()); |
478 TypeHandle other, bool is_intersect, Region* region); | 516 } |
517 | |
518 struct Limits { | |
519 i::Handle<i::Object> min; | |
520 i::Handle<i::Object> max; | |
521 Limits(i::Handle<i::Object> min, i::Handle<i::Object> max) : | |
522 min(min), max(max) {} | |
523 explicit Limits(RangeType* range) : | |
524 min(range->MinV()), max(range->MaxV()) {} | |
525 }; | |
526 | |
527 static Limits intersect(Limits lhs, Limits rhs); | |
rossberg
2014/09/15 15:58:30
Nit: use uppercase names.
neis1
2014/09/16 10:04:00
Done.
| |
528 static Limits union_(Limits lhs, Limits rhs); | |
529 static bool overlap(RangeType* lhs, RangeType* rhs); | |
530 static bool contains(RangeType* lhs, RangeType* rhs); | |
531 static bool contains(RangeType* range, i::Object* val); | |
532 | |
533 RangeType* GetRange(); | |
534 static int UpdateRange( | |
535 RangeHandle type, UnionHandle result, int size, Region* region); | |
536 | |
537 bool SimplyEquals(TypeImpl* that); | |
538 static int AddToUnion( | |
539 TypeHandle type, UnionHandle result, int size, Region* region); | |
540 static int IntersectAux( | |
541 TypeHandle type, TypeHandle other, | |
542 UnionHandle result, int size, Region* region); | |
543 static TypeHandle NormalizeUnion(UnionHandle unioned, int size); | |
479 }; | 544 }; |
480 | 545 |
481 | 546 |
482 // ----------------------------------------------------------------------------- | 547 // ----------------------------------------------------------------------------- |
483 // Bitset types (internal). | 548 // Bitset types (internal). |
484 | 549 |
485 template<class Config> | 550 template<class Config> |
486 class TypeImpl<Config>::BitsetType : public TypeImpl<Config> { | 551 class TypeImpl<Config>::BitsetType : public TypeImpl<Config> { |
487 protected: | 552 protected: |
488 friend class TypeImpl<Config>; | 553 friend class TypeImpl<Config>; |
489 | 554 |
490 enum { | 555 enum { |
491 #define DECLARE_TYPE(type, value) k##type = (value), | 556 #define DECLARE_TYPE(type, value) k##type = (value), |
492 BITSET_TYPE_LIST(DECLARE_TYPE) | 557 BITSET_TYPE_LIST(DECLARE_TYPE) |
493 #undef DECLARE_TYPE | 558 #undef DECLARE_TYPE |
494 kUnusedEOL = 0 | 559 kUnusedEOL = 0 |
495 }; | 560 }; |
496 | 561 |
497 int Bitset() { return Config::as_bitset(this); } | 562 int Bitset() { return Config::as_bitset(this); } |
498 | 563 |
499 static TypeImpl* New(int bitset) { | 564 static TypeImpl* New(int bitset) { |
565 DCHECK(bitset == kNone || IsInhabited(bitset)); | |
500 return static_cast<BitsetType*>(Config::from_bitset(bitset)); | 566 return static_cast<BitsetType*>(Config::from_bitset(bitset)); |
501 } | 567 } |
502 static TypeHandle New(int bitset, Region* region) { | 568 static TypeHandle New(int bitset, Region* region) { |
569 DCHECK(bitset == kNone || IsInhabited(bitset)); | |
503 return Config::from_bitset(bitset, region); | 570 return Config::from_bitset(bitset, region); |
504 } | 571 } |
505 | 572 |
506 static bool IsInhabited(int bitset) { | 573 static bool IsInhabited(int bitset) { |
507 return (bitset & kRepresentation) && (bitset & kSemantic); | 574 return bitset & kSemantic; |
rossberg
2014/09/15 15:58:30
Hm, well, this doesn't really reflect the function
neis1
2014/09/16 10:04:00
Depends on your definition of inhabited ;) I have
| |
508 } | 575 } |
509 | 576 |
510 static bool Is(int bitset1, int bitset2) { | 577 static bool Is(int bitset1, int bitset2) { |
511 return (bitset1 | bitset2) == bitset2; | 578 return (bitset1 | bitset2) == bitset2; |
512 } | 579 } |
513 | 580 |
514 static int Glb(TypeImpl* type); // greatest lower bound that's a bitset | 581 static int Glb(TypeImpl* type); // greatest lower bound that's a bitset |
515 static int Lub(TypeImpl* type); // least upper bound that's a bitset | 582 static int Lub(TypeImpl* type); // least upper bound that's a bitset |
516 static int Lub(i::Object* value); | 583 static int Lub(i::Object* value); |
517 static int Lub(double value); | 584 static int Lub(double value); |
518 static int Lub(int32_t value); | 585 static int Lub(int32_t value); |
519 static int Lub(uint32_t value); | 586 static int Lub(uint32_t value); |
520 static int Lub(i::Map* map); | 587 static int Lub(i::Map* map); |
521 static int Lub(double min, double max); | 588 static int Lub(Limits lim); |
522 static int InherentLub(TypeImpl* type); | |
523 | 589 |
524 static const char* Name(int bitset); | 590 static const char* Name(int bitset); |
525 static void Print(OStream& os, int bitset); // NOLINT | 591 static void Print(OStream& os, int bitset); // NOLINT |
526 using TypeImpl::PrintTo; | 592 #ifdef DEBUG |
593 static void Print(int bitset); | |
594 #endif | |
527 }; | 595 }; |
528 | 596 |
529 | 597 |
530 // ----------------------------------------------------------------------------- | 598 // ----------------------------------------------------------------------------- |
531 // Superclass for non-bitset types (internal). | 599 // Superclass for non-bitset types (internal). |
532 // Contains a tag and a variable number of type or value fields. | 600 // Contains a tag and a variable number of type or value fields. |
533 | 601 |
534 template<class Config> | 602 template<class Config> |
535 class TypeImpl<Config>::StructuralType : public TypeImpl<Config> { | 603 class TypeImpl<Config>::StructuralType : public TypeImpl<Config> { |
536 protected: | 604 protected: |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
602 bool Wellformed(); | 670 bool Wellformed(); |
603 }; | 671 }; |
604 | 672 |
605 | 673 |
606 // ----------------------------------------------------------------------------- | 674 // ----------------------------------------------------------------------------- |
607 // Class types. | 675 // Class types. |
608 | 676 |
609 template<class Config> | 677 template<class Config> |
610 class TypeImpl<Config>::ClassType : public StructuralType { | 678 class TypeImpl<Config>::ClassType : public StructuralType { |
611 public: | 679 public: |
612 TypeHandle Bound(Region* region) { | |
613 return Config::is_class(this) | |
614 ? BitsetType::New(BitsetType::Lub(*Config::as_class(this)), region) | |
615 : this->Get(0); | |
616 } | |
617 i::Handle<i::Map> Map() { | 680 i::Handle<i::Map> Map() { |
618 return Config::is_class(this) | 681 return Config::is_class(this) |
619 ? Config::as_class(this) | 682 ? Config::as_class(this) |
620 : this->template GetValue<i::Map>(1); | 683 : this->template GetValue<i::Map>(0); |
621 } | |
622 | |
623 static ClassHandle New( | |
624 i::Handle<i::Map> map, TypeHandle bound, Region* region) { | |
625 DCHECK(BitsetType::Is(bound->AsBitset(), BitsetType::Lub(*map))); | |
626 ClassHandle type = Config::template cast<ClassType>( | |
627 StructuralType::New(StructuralType::kClassTag, 2, region)); | |
628 type->Set(0, bound); | |
629 type->SetValue(1, map); | |
630 return type; | |
631 } | 684 } |
632 | 685 |
633 static ClassHandle New(i::Handle<i::Map> map, Region* region) { | 686 static ClassHandle New(i::Handle<i::Map> map, Region* region) { |
634 ClassHandle type = | 687 ClassHandle type = |
635 Config::template cast<ClassType>(Config::from_class(map, region)); | 688 Config::template cast<ClassType>(Config::from_class(map, region)); |
636 if (type->IsClass()) { | 689 if (!type->IsClass()) { |
637 return type; | 690 type = Config::template cast<ClassType>( |
638 } else { | 691 StructuralType::New(StructuralType::kClassTag, 1, region)); |
639 TypeHandle bound = BitsetType::New(BitsetType::Lub(*map), region); | 692 type->SetValue(0, map); |
640 return New(map, bound, region); | |
641 } | 693 } |
694 return type; | |
642 } | 695 } |
643 | 696 |
644 static ClassType* cast(TypeImpl* type) { | 697 static ClassType* cast(TypeImpl* type) { |
645 DCHECK(type->IsClass()); | 698 DCHECK(type->IsClass()); |
646 return static_cast<ClassType*>(type); | 699 return static_cast<ClassType*>(type); |
647 } | 700 } |
648 }; | 701 }; |
649 | 702 |
650 | 703 |
651 // ----------------------------------------------------------------------------- | 704 // ----------------------------------------------------------------------------- |
652 // Constant types. | 705 // Constant types. |
653 | 706 |
654 template<class Config> | 707 template<class Config> |
655 class TypeImpl<Config>::ConstantType : public StructuralType { | 708 class TypeImpl<Config>::ConstantType : public StructuralType { |
656 public: | 709 public: |
657 TypeHandle Bound() { return this->Get(0); } | 710 i::Handle<i::Object> Value() { return this->template GetValue<i::Object>(0); } |
658 i::Handle<i::Object> Value() { return this->template GetValue<i::Object>(1); } | |
659 | |
660 static ConstantHandle New( | |
661 i::Handle<i::Object> value, TypeHandle bound, Region* region) { | |
662 DCHECK(BitsetType::Is(bound->AsBitset(), BitsetType::Lub(*value))); | |
663 ConstantHandle type = Config::template cast<ConstantType>( | |
664 StructuralType::New(StructuralType::kConstantTag, 2, region)); | |
665 type->Set(0, bound); | |
666 type->SetValue(1, value); | |
667 return type; | |
668 } | |
669 | 711 |
670 static ConstantHandle New(i::Handle<i::Object> value, Region* region) { | 712 static ConstantHandle New(i::Handle<i::Object> value, Region* region) { |
671 TypeHandle bound = BitsetType::New(BitsetType::Lub(*value), region); | 713 ConstantHandle type = Config::template cast<ConstantType>( |
672 return New(value, bound, region); | 714 StructuralType::New(StructuralType::kConstantTag, 1, region)); |
715 type->SetValue(0, value); | |
716 return type; | |
673 } | 717 } |
674 | 718 |
675 static ConstantType* cast(TypeImpl* type) { | 719 static ConstantType* cast(TypeImpl* type) { |
676 DCHECK(type->IsConstant()); | 720 DCHECK(type->IsConstant()); |
677 return static_cast<ConstantType*>(type); | 721 return static_cast<ConstantType*>(type); |
678 } | 722 } |
679 }; | 723 }; |
680 | 724 |
681 | 725 |
682 // ----------------------------------------------------------------------------- | 726 // ----------------------------------------------------------------------------- |
683 // Range types. | 727 // Range types. |
684 | 728 |
685 template<class Config> | 729 template<class Config> |
686 class TypeImpl<Config>::RangeType : public StructuralType { | 730 class TypeImpl<Config>::RangeType : public StructuralType { |
687 public: | 731 public: |
688 TypeHandle Bound() { return this->Get(0); } | 732 i::Handle<i::Object> MinV() { return this->template GetValue<i::Object>(0); } |
689 double Min() { return this->template GetValue<i::HeapNumber>(1)->value(); } | 733 i::Handle<i::Object> MaxV() { return this->template GetValue<i::Object>(1); } |
690 double Max() { return this->template GetValue<i::HeapNumber>(2)->value(); } | 734 double Min() { return MinV()->Number(); } |
735 double Max() { return MaxV()->Number(); } | |
691 | 736 |
692 static RangeHandle New( | 737 static RangeHandle New( |
693 double min, double max, TypeHandle bound, Region* region) { | 738 i::Handle<i::Object> min, i::Handle<i::Object> max, Region* region) { |
694 DCHECK(BitsetType::Is(bound->AsBitset(), BitsetType::Lub(min, max))); | 739 DCHECK(min->Number() <= max->Number()); |
695 RangeHandle type = Config::template cast<RangeType>( | 740 RangeHandle type = Config::template cast<RangeType>( |
696 StructuralType::New(StructuralType::kRangeTag, 3, region)); | 741 StructuralType::New(StructuralType::kRangeTag, 2, region)); |
697 type->Set(0, bound); | 742 type->SetValue(0, min); |
698 Factory* factory = Config::isolate(region)->factory(); | 743 type->SetValue(1, max); |
699 Handle<HeapNumber> minV = factory->NewHeapNumber(min); | |
700 Handle<HeapNumber> maxV = factory->NewHeapNumber(max); | |
701 type->SetValue(1, minV); | |
702 type->SetValue(2, maxV); | |
703 return type; | 744 return type; |
704 } | 745 } |
705 | 746 |
706 static RangeHandle New(double min, double max, Region* region) { | 747 static RangeHandle New(Limits lim, Region* region) { |
707 TypeHandle bound = BitsetType::New(BitsetType::Lub(min, max), region); | 748 return New(lim.min, lim.max, region); |
708 return New(min, max, bound, region); | |
709 } | 749 } |
710 | 750 |
711 static RangeType* cast(TypeImpl* type) { | 751 static RangeType* cast(TypeImpl* type) { |
712 DCHECK(type->IsRange()); | 752 DCHECK(type->IsRange()); |
713 return static_cast<RangeType*>(type); | 753 return static_cast<RangeType*>(type); |
714 } | 754 } |
715 }; | 755 }; |
716 | 756 |
717 | 757 |
718 // ----------------------------------------------------------------------------- | 758 // ----------------------------------------------------------------------------- |
719 // Context types. | 759 // Context types. |
720 | 760 |
721 template<class Config> | 761 template<class Config> |
722 class TypeImpl<Config>::ContextType : public StructuralType { | 762 class TypeImpl<Config>::ContextType : public StructuralType { |
723 public: | 763 public: |
724 TypeHandle Bound() { return this->Get(0); } | 764 TypeHandle Outer() { return this->Get(0); } |
725 TypeHandle Outer() { return this->Get(1); } | |
726 | |
727 static ContextHandle New(TypeHandle outer, TypeHandle bound, Region* region) { | |
728 DCHECK(BitsetType::Is( | |
729 bound->AsBitset(), BitsetType::kInternal & BitsetType::kTaggedPtr)); | |
730 ContextHandle type = Config::template cast<ContextType>( | |
731 StructuralType::New(StructuralType::kContextTag, 2, region)); | |
732 type->Set(0, bound); | |
733 type->Set(1, outer); | |
734 return type; | |
735 } | |
736 | 765 |
737 static ContextHandle New(TypeHandle outer, Region* region) { | 766 static ContextHandle New(TypeHandle outer, Region* region) { |
738 TypeHandle bound = BitsetType::New( | 767 ContextHandle type = Config::template cast<ContextType>( |
739 BitsetType::kInternal & BitsetType::kTaggedPtr, region); | 768 StructuralType::New(StructuralType::kContextTag, 1, region)); |
740 return New(outer, bound, region); | 769 type->Set(0, outer); |
770 return type; | |
741 } | 771 } |
742 | 772 |
743 static ContextType* cast(TypeImpl* type) { | 773 static ContextType* cast(TypeImpl* type) { |
744 DCHECK(type->IsContext()); | 774 DCHECK(type->IsContext()); |
745 return static_cast<ContextType*>(type); | 775 return static_cast<ContextType*>(type); |
746 } | 776 } |
747 }; | 777 }; |
748 | 778 |
749 | 779 |
750 // ----------------------------------------------------------------------------- | 780 // ----------------------------------------------------------------------------- |
751 // Array types. | 781 // Array types. |
752 | 782 |
753 template<class Config> | 783 template<class Config> |
754 class TypeImpl<Config>::ArrayType : public StructuralType { | 784 class TypeImpl<Config>::ArrayType : public StructuralType { |
755 public: | 785 public: |
756 TypeHandle Bound() { return this->Get(0); } | 786 TypeHandle Element() { return this->Get(0); } |
757 TypeHandle Element() { return this->Get(1); } | |
758 | |
759 static ArrayHandle New(TypeHandle element, TypeHandle bound, Region* region) { | |
760 DCHECK(BitsetType::Is(bound->AsBitset(), BitsetType::kArray)); | |
761 ArrayHandle type = Config::template cast<ArrayType>( | |
762 StructuralType::New(StructuralType::kArrayTag, 2, region)); | |
763 type->Set(0, bound); | |
764 type->Set(1, element); | |
765 return type; | |
766 } | |
767 | 787 |
768 static ArrayHandle New(TypeHandle element, Region* region) { | 788 static ArrayHandle New(TypeHandle element, Region* region) { |
769 TypeHandle bound = BitsetType::New(BitsetType::kArray, region); | 789 ArrayHandle type = Config::template cast<ArrayType>( |
770 return New(element, bound, region); | 790 StructuralType::New(StructuralType::kArrayTag, 1, region)); |
791 type->Set(0, element); | |
792 return type; | |
771 } | 793 } |
772 | 794 |
773 static ArrayType* cast(TypeImpl* type) { | 795 static ArrayType* cast(TypeImpl* type) { |
774 DCHECK(type->IsArray()); | 796 DCHECK(type->IsArray()); |
775 return static_cast<ArrayType*>(type); | 797 return static_cast<ArrayType*>(type); |
776 } | 798 } |
777 }; | 799 }; |
778 | 800 |
779 | 801 |
780 // ----------------------------------------------------------------------------- | 802 // ----------------------------------------------------------------------------- |
781 // Function types. | 803 // Function types. |
782 | 804 |
783 template<class Config> | 805 template<class Config> |
784 class TypeImpl<Config>::FunctionType : public StructuralType { | 806 class TypeImpl<Config>::FunctionType : public StructuralType { |
785 public: | 807 public: |
786 int Arity() { return this->Length() - 3; } | 808 int Arity() { return this->Length() - 2; } |
787 TypeHandle Bound() { return this->Get(0); } | 809 TypeHandle Result() { return this->Get(0); } |
788 TypeHandle Result() { return this->Get(1); } | 810 TypeHandle Receiver() { return this->Get(1); } |
789 TypeHandle Receiver() { return this->Get(2); } | 811 TypeHandle Parameter(int i) { return this->Get(2 + i); } |
790 TypeHandle Parameter(int i) { return this->Get(3 + i); } | |
791 | 812 |
792 void InitParameter(int i, TypeHandle type) { this->Set(3 + i, type); } | 813 void InitParameter(int i, TypeHandle type) { this->Set(2 + i, type); } |
793 | |
794 static FunctionHandle New( | |
795 TypeHandle result, TypeHandle receiver, TypeHandle bound, | |
796 int arity, Region* region) { | |
797 DCHECK(BitsetType::Is(bound->AsBitset(), BitsetType::kFunction)); | |
798 FunctionHandle type = Config::template cast<FunctionType>( | |
799 StructuralType::New(StructuralType::kFunctionTag, 3 + arity, region)); | |
800 type->Set(0, bound); | |
801 type->Set(1, result); | |
802 type->Set(2, receiver); | |
803 return type; | |
804 } | |
805 | 814 |
806 static FunctionHandle New( | 815 static FunctionHandle New( |
807 TypeHandle result, TypeHandle receiver, int arity, Region* region) { | 816 TypeHandle result, TypeHandle receiver, int arity, Region* region) { |
808 TypeHandle bound = BitsetType::New(BitsetType::kFunction, region); | 817 FunctionHandle type = Config::template cast<FunctionType>( |
809 return New(result, receiver, bound, arity, region); | 818 StructuralType::New(StructuralType::kFunctionTag, 2 + arity, region)); |
819 type->Set(0, result); | |
820 type->Set(1, receiver); | |
821 return type; | |
810 } | 822 } |
811 | 823 |
812 static FunctionType* cast(TypeImpl* type) { | 824 static FunctionType* cast(TypeImpl* type) { |
813 DCHECK(type->IsFunction()); | 825 DCHECK(type->IsFunction()); |
814 return static_cast<FunctionType*>(type); | 826 return static_cast<FunctionType*>(type); |
815 } | 827 } |
816 }; | 828 }; |
817 | 829 |
818 | 830 |
819 // ----------------------------------------------------------------------------- | 831 // ----------------------------------------------------------------------------- |
(...skipping 26 matching lines...) Expand all Loading... | |
846 // Zone-allocated types; they are either (odd) integers to represent bitsets, or | 858 // Zone-allocated types; they are either (odd) integers to represent bitsets, or |
847 // (even) pointers to structures for everything else. | 859 // (even) pointers to structures for everything else. |
848 | 860 |
849 struct ZoneTypeConfig { | 861 struct ZoneTypeConfig { |
850 typedef TypeImpl<ZoneTypeConfig> Type; | 862 typedef TypeImpl<ZoneTypeConfig> Type; |
851 class Base {}; | 863 class Base {}; |
852 typedef void* Struct; | 864 typedef void* Struct; |
853 typedef i::Zone Region; | 865 typedef i::Zone Region; |
854 template<class T> struct Handle { typedef T* type; }; | 866 template<class T> struct Handle { typedef T* type; }; |
855 | 867 |
856 // TODO(neis): This will be removed again once we have struct_get_double(). | |
857 static inline i::Isolate* isolate(Region* region) { | |
858 return region->isolate(); | |
859 } | |
860 | |
861 template<class T> static inline T* handle(T* type); | 868 template<class T> static inline T* handle(T* type); |
862 template<class T> static inline T* cast(Type* type); | 869 template<class T> static inline T* cast(Type* type); |
863 | 870 |
864 static inline bool is_bitset(Type* type); | 871 static inline bool is_bitset(Type* type); |
865 static inline bool is_class(Type* type); | 872 static inline bool is_class(Type* type); |
866 static inline bool is_struct(Type* type, int tag); | 873 static inline bool is_struct(Type* type, int tag); |
867 | 874 |
868 static inline int as_bitset(Type* type); | 875 static inline int as_bitset(Type* type); |
869 static inline i::Handle<i::Map> as_class(Type* type); | 876 static inline i::Handle<i::Map> as_class(Type* type); |
870 static inline Struct* as_struct(Type* type); | 877 static inline Struct* as_struct(Type* type); |
(...skipping 22 matching lines...) Expand all Loading... | |
893 // Heap-allocated types; either smis for bitsets, maps for classes, boxes for | 900 // Heap-allocated types; either smis for bitsets, maps for classes, boxes for |
894 // constants, or fixed arrays for unions. | 901 // constants, or fixed arrays for unions. |
895 | 902 |
896 struct HeapTypeConfig { | 903 struct HeapTypeConfig { |
897 typedef TypeImpl<HeapTypeConfig> Type; | 904 typedef TypeImpl<HeapTypeConfig> Type; |
898 typedef i::Object Base; | 905 typedef i::Object Base; |
899 typedef i::FixedArray Struct; | 906 typedef i::FixedArray Struct; |
900 typedef i::Isolate Region; | 907 typedef i::Isolate Region; |
901 template<class T> struct Handle { typedef i::Handle<T> type; }; | 908 template<class T> struct Handle { typedef i::Handle<T> type; }; |
902 | 909 |
903 // TODO(neis): This will be removed again once we have struct_get_double(). | |
904 static inline i::Isolate* isolate(Region* region) { | |
905 return region; | |
906 } | |
907 | |
908 template<class T> static inline i::Handle<T> handle(T* type); | 910 template<class T> static inline i::Handle<T> handle(T* type); |
909 template<class T> static inline i::Handle<T> cast(i::Handle<Type> type); | 911 template<class T> static inline i::Handle<T> cast(i::Handle<Type> type); |
910 | 912 |
911 static inline bool is_bitset(Type* type); | 913 static inline bool is_bitset(Type* type); |
912 static inline bool is_class(Type* type); | 914 static inline bool is_class(Type* type); |
913 static inline bool is_struct(Type* type, int tag); | 915 static inline bool is_struct(Type* type, int tag); |
914 | 916 |
915 static inline int as_bitset(Type* type); | 917 static inline int as_bitset(Type* type); |
916 static inline i::Handle<i::Map> as_class(Type* type); | 918 static inline i::Handle<i::Map> as_class(Type* type); |
917 static inline i::Handle<Struct> as_struct(Type* type); | 919 static inline i::Handle<Struct> as_struct(Type* type); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
995 bool Narrows(BoundsImpl that) { | 997 bool Narrows(BoundsImpl that) { |
996 return that.lower->Is(this->lower) && this->upper->Is(that.upper); | 998 return that.lower->Is(this->lower) && this->upper->Is(that.upper); |
997 } | 999 } |
998 }; | 1000 }; |
999 | 1001 |
1000 typedef BoundsImpl<ZoneTypeConfig> Bounds; | 1002 typedef BoundsImpl<ZoneTypeConfig> Bounds; |
1001 | 1003 |
1002 } } // namespace v8::internal | 1004 } } // namespace v8::internal |
1003 | 1005 |
1004 #endif // V8_TYPES_H_ | 1006 #endif // V8_TYPES_H_ |
OLD | NEW |