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 26 matching lines...) Expand all Loading... | |
397 return Config::is_struct(this, StructuralType::kFunctionTag); | 436 return Config::is_struct(this, StructuralType::kFunctionTag); |
398 } | 437 } |
399 | 438 |
400 ClassType* AsClass() { return ClassType::cast(this); } | 439 ClassType* AsClass() { return ClassType::cast(this); } |
401 ConstantType* AsConstant() { return ConstantType::cast(this); } | 440 ConstantType* AsConstant() { return ConstantType::cast(this); } |
402 RangeType* AsRange() { return RangeType::cast(this); } | 441 RangeType* AsRange() { return RangeType::cast(this); } |
403 ContextType* AsContext() { return ContextType::cast(this); } | 442 ContextType* AsContext() { return ContextType::cast(this); } |
404 ArrayType* AsArray() { return ArrayType::cast(this); } | 443 ArrayType* AsArray() { return ArrayType::cast(this); } |
405 FunctionType* AsFunction() { return FunctionType::cast(this); } | 444 FunctionType* AsFunction() { return FunctionType::cast(this); } |
406 | 445 |
446 // Minimum and maximum of a numeric type. | |
447 // These functions ignore NaN and do not distinguish between -0 and +0. | |
448 double Min(); | |
rossberg
2014/09/16 14:04:40
These really only make sense on number types. So t
neis1
2014/09/18 13:05:18
As discussed, I kept it double but added an assert
| |
449 double Max(); | |
450 | |
407 int NumClasses(); | 451 int NumClasses(); |
408 int NumConstants(); | 452 int NumConstants(); |
409 | 453 |
410 template<class T> class Iterator; | 454 template<class T> class Iterator; |
411 Iterator<i::Map> Classes() { | 455 Iterator<i::Map> Classes() { |
412 if (this->IsBitset()) return Iterator<i::Map>(); | 456 if (this->IsBitset()) return Iterator<i::Map>(); |
413 return Iterator<i::Map>(Config::handle(this)); | 457 return Iterator<i::Map>(Config::handle(this)); |
414 } | 458 } |
415 Iterator<i::Object> Constants() { | 459 Iterator<i::Object> Constants() { |
416 if (this->IsBitset()) return Iterator<i::Object>(); | 460 if (this->IsBitset()) return Iterator<i::Object>(); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
459 int AsBitset() { | 503 int AsBitset() { |
460 DCHECK(this->IsBitset()); | 504 DCHECK(this->IsBitset()); |
461 return static_cast<BitsetType*>(this)->Bitset(); | 505 return static_cast<BitsetType*>(this)->Bitset(); |
462 } | 506 } |
463 UnionType* AsUnion() { return UnionType::cast(this); } | 507 UnionType* AsUnion() { return UnionType::cast(this); } |
464 | 508 |
465 // Auxiliary functions. | 509 // Auxiliary functions. |
466 | 510 |
467 int BitsetGlb() { return BitsetType::Glb(this); } | 511 int BitsetGlb() { return BitsetType::Glb(this); } |
468 int BitsetLub() { return BitsetType::Lub(this); } | 512 int BitsetLub() { return BitsetType::Lub(this); } |
469 int InherentBitsetLub() { return BitsetType::InherentLub(this); } | |
470 | 513 |
471 bool SlowIs(TypeImpl* that); | 514 bool SlowIs(TypeImpl* that); |
472 | 515 |
473 TypeHandle Rebound(int bitset, Region* region); | 516 static bool IsInteger(double x) { |
474 int BoundBy(TypeImpl* that); | 517 return nearbyint(x) == x && !i::IsMinusZero(x); // Allows for infinities. |
475 int IndexInUnion(int bound, UnionHandle unioned, int current_size); | 518 } |
476 static int ExtendUnion( | 519 static bool IsInteger(i::Object* x) { |
477 UnionHandle unioned, int current_size, TypeHandle t, | 520 return x->IsNumber() && IsInteger(x->Number()); |
478 TypeHandle other, bool is_intersect, Region* region); | 521 } |
522 | |
523 struct Limits { | |
524 i::Handle<i::Object> min; | |
525 i::Handle<i::Object> max; | |
526 Limits(i::Handle<i::Object> min, i::Handle<i::Object> max) : | |
527 min(min), max(max) {} | |
528 explicit Limits(RangeType* range) : | |
529 min(range->MinV()), max(range->MaxV()) {} | |
530 }; | |
531 | |
532 static Limits Intersect(Limits lhs, Limits rhs); | |
533 static Limits Union(Limits lhs, Limits rhs); | |
534 static bool Overlap(RangeType* lhs, RangeType* rhs); | |
535 static bool Contains(RangeType* lhs, RangeType* rhs); | |
536 static bool Contains(RangeType* range, i::Object* val); | |
537 | |
538 RangeType* GetRange(); | |
539 static int UpdateRange( | |
540 RangeHandle type, UnionHandle result, int size, Region* region); | |
541 | |
542 bool SimplyEquals(TypeImpl* that); | |
543 static int AddToUnion( | |
544 TypeHandle type, UnionHandle result, int size, Region* region); | |
545 static int IntersectAux( | |
546 TypeHandle type, TypeHandle other, | |
547 UnionHandle result, int size, Region* region); | |
548 static TypeHandle NormalizeUnion(UnionHandle unioned, int size); | |
479 }; | 549 }; |
480 | 550 |
481 | 551 |
482 // ----------------------------------------------------------------------------- | 552 // ----------------------------------------------------------------------------- |
483 // Bitset types (internal). | 553 // Bitset types (internal). |
484 | 554 |
485 template<class Config> | 555 template<class Config> |
486 class TypeImpl<Config>::BitsetType : public TypeImpl<Config> { | 556 class TypeImpl<Config>::BitsetType : public TypeImpl<Config> { |
487 protected: | 557 protected: |
488 friend class TypeImpl<Config>; | 558 friend class TypeImpl<Config>; |
489 | 559 |
490 enum { | 560 enum { |
491 #define DECLARE_TYPE(type, value) k##type = (value), | 561 #define DECLARE_TYPE(type, value) k##type = (value), |
492 BITSET_TYPE_LIST(DECLARE_TYPE) | 562 BITSET_TYPE_LIST(DECLARE_TYPE) |
493 #undef DECLARE_TYPE | 563 #undef DECLARE_TYPE |
494 kUnusedEOL = 0 | 564 kUnusedEOL = 0 |
495 }; | 565 }; |
496 | 566 |
497 int Bitset() { return Config::as_bitset(this); } | 567 int Bitset() { return Config::as_bitset(this); } |
498 | 568 |
499 static TypeImpl* New(int bitset) { | 569 static TypeImpl* New(int bitset) { |
570 DCHECK(bitset == kNone || IsInhabited(bitset)); | |
500 return static_cast<BitsetType*>(Config::from_bitset(bitset)); | 571 return static_cast<BitsetType*>(Config::from_bitset(bitset)); |
501 } | 572 } |
502 static TypeHandle New(int bitset, Region* region) { | 573 static TypeHandle New(int bitset, Region* region) { |
574 DCHECK(bitset == kNone || IsInhabited(bitset)); | |
503 return Config::from_bitset(bitset, region); | 575 return Config::from_bitset(bitset, region); |
504 } | 576 } |
505 | 577 |
506 static bool IsInhabited(int bitset) { | 578 static bool IsInhabited(int bitset) { |
507 return (bitset & kRepresentation) && (bitset & kSemantic); | 579 return bitset & kSemantic; |
508 } | 580 } |
509 | 581 |
510 static bool Is(int bitset1, int bitset2) { | 582 static bool Is(int bitset1, int bitset2) { |
511 return (bitset1 | bitset2) == bitset2; | 583 return (bitset1 | bitset2) == bitset2; |
512 } | 584 } |
513 | 585 |
586 struct Numeral { | |
rossberg
2014/09/16 14:04:40
Can't type and tables be moved to the private sect
neis1
2014/09/18 13:05:18
Done.
| |
587 int bitset; | |
588 double min; | |
589 }; | |
590 | |
591 static const Numeral* Numerals() { | |
592 return i::SmiValuesAre31Bits() ? Numerals31 : Numerals32; | |
593 } | |
594 | |
595 static size_t NumeralsSize() { | |
596 return i::SmiValuesAre31Bits() ? | |
597 arraysize(Numerals31) : arraysize(Numerals32); | |
598 } | |
599 | |
600 static double Min(int bitset); | |
601 static double Max(int bitset); | |
602 | |
514 static int Glb(TypeImpl* type); // greatest lower bound that's a bitset | 603 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 | 604 static int Lub(TypeImpl* type); // least upper bound that's a bitset |
516 static int Lub(i::Object* value); | 605 static int Lub(i::Object* value); |
517 static int Lub(double value); | 606 static int Lub(double value); |
518 static int Lub(int32_t value); | 607 static int Lub(int32_t value); |
519 static int Lub(uint32_t value); | 608 static int Lub(uint32_t value); |
520 static int Lub(i::Map* map); | 609 static int Lub(i::Map* map); |
521 static int Lub(double min, double max); | 610 static int Lub(Limits lim); |
522 static int InherentLub(TypeImpl* type); | |
523 | 611 |
524 static const char* Name(int bitset); | 612 static const char* Name(int bitset); |
525 static void Print(OStream& os, int bitset); // NOLINT | 613 static void Print(OStream& os, int bitset); // NOLINT |
526 using TypeImpl::PrintTo; | 614 #ifdef DEBUG |
615 static void Print(int bitset); | |
616 #endif | |
617 | |
618 private: | |
619 static const Numeral Numerals31[]; | |
620 static const Numeral Numerals32[]; | |
527 }; | 621 }; |
528 | 622 |
529 | 623 |
530 // ----------------------------------------------------------------------------- | 624 // ----------------------------------------------------------------------------- |
531 // Superclass for non-bitset types (internal). | 625 // Superclass for non-bitset types (internal). |
532 // Contains a tag and a variable number of type or value fields. | 626 // Contains a tag and a variable number of type or value fields. |
533 | 627 |
534 template<class Config> | 628 template<class Config> |
535 class TypeImpl<Config>::StructuralType : public TypeImpl<Config> { | 629 class TypeImpl<Config>::StructuralType : public TypeImpl<Config> { |
536 protected: | 630 protected: |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
602 bool Wellformed(); | 696 bool Wellformed(); |
603 }; | 697 }; |
604 | 698 |
605 | 699 |
606 // ----------------------------------------------------------------------------- | 700 // ----------------------------------------------------------------------------- |
607 // Class types. | 701 // Class types. |
608 | 702 |
609 template<class Config> | 703 template<class Config> |
610 class TypeImpl<Config>::ClassType : public StructuralType { | 704 class TypeImpl<Config>::ClassType : public StructuralType { |
611 public: | 705 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() { | 706 i::Handle<i::Map> Map() { |
618 return Config::is_class(this) | 707 return Config::is_class(this) |
619 ? Config::as_class(this) | 708 ? Config::as_class(this) |
620 : this->template GetValue<i::Map>(1); | 709 : 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 } | 710 } |
632 | 711 |
633 static ClassHandle New(i::Handle<i::Map> map, Region* region) { | 712 static ClassHandle New(i::Handle<i::Map> map, Region* region) { |
634 ClassHandle type = | 713 ClassHandle type = |
635 Config::template cast<ClassType>(Config::from_class(map, region)); | 714 Config::template cast<ClassType>(Config::from_class(map, region)); |
636 if (type->IsClass()) { | 715 if (!type->IsClass()) { |
637 return type; | 716 type = Config::template cast<ClassType>( |
638 } else { | 717 StructuralType::New(StructuralType::kClassTag, 1, region)); |
639 TypeHandle bound = BitsetType::New(BitsetType::Lub(*map), region); | 718 type->SetValue(0, map); |
640 return New(map, bound, region); | |
641 } | 719 } |
720 return type; | |
642 } | 721 } |
643 | 722 |
644 static ClassType* cast(TypeImpl* type) { | 723 static ClassType* cast(TypeImpl* type) { |
645 DCHECK(type->IsClass()); | 724 DCHECK(type->IsClass()); |
646 return static_cast<ClassType*>(type); | 725 return static_cast<ClassType*>(type); |
647 } | 726 } |
648 }; | 727 }; |
649 | 728 |
650 | 729 |
651 // ----------------------------------------------------------------------------- | 730 // ----------------------------------------------------------------------------- |
652 // Constant types. | 731 // Constant types. |
653 | 732 |
654 template<class Config> | 733 template<class Config> |
655 class TypeImpl<Config>::ConstantType : public StructuralType { | 734 class TypeImpl<Config>::ConstantType : public StructuralType { |
656 public: | 735 public: |
657 TypeHandle Bound() { return this->Get(0); } | 736 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 | 737 |
670 static ConstantHandle New(i::Handle<i::Object> value, Region* region) { | 738 static ConstantHandle New(i::Handle<i::Object> value, Region* region) { |
671 TypeHandle bound = BitsetType::New(BitsetType::Lub(*value), region); | 739 ConstantHandle type = Config::template cast<ConstantType>( |
672 return New(value, bound, region); | 740 StructuralType::New(StructuralType::kConstantTag, 1, region)); |
741 type->SetValue(0, value); | |
742 return type; | |
673 } | 743 } |
674 | 744 |
675 static ConstantType* cast(TypeImpl* type) { | 745 static ConstantType* cast(TypeImpl* type) { |
676 DCHECK(type->IsConstant()); | 746 DCHECK(type->IsConstant()); |
677 return static_cast<ConstantType*>(type); | 747 return static_cast<ConstantType*>(type); |
678 } | 748 } |
679 }; | 749 }; |
680 | 750 |
681 | 751 |
682 // ----------------------------------------------------------------------------- | 752 // ----------------------------------------------------------------------------- |
683 // Range types. | 753 // Range types. |
684 | 754 |
685 template<class Config> | 755 template<class Config> |
686 class TypeImpl<Config>::RangeType : public StructuralType { | 756 class TypeImpl<Config>::RangeType : public StructuralType { |
687 public: | 757 public: |
688 TypeHandle Bound() { return this->Get(0); } | 758 i::Handle<i::Object> MinV() { return this->template GetValue<i::Object>(0); } |
689 double Min() { return this->template GetValue<i::HeapNumber>(1)->value(); } | 759 i::Handle<i::Object> MaxV() { return this->template GetValue<i::Object>(1); } |
690 double Max() { return this->template GetValue<i::HeapNumber>(2)->value(); } | 760 double Min() { return MinV()->Number(); } |
761 double Max() { return MaxV()->Number(); } | |
691 | 762 |
692 static RangeHandle New( | 763 static RangeHandle New( |
693 double min, double max, TypeHandle bound, Region* region) { | 764 i::Handle<i::Object> min, i::Handle<i::Object> max, Region* region) { |
694 DCHECK(BitsetType::Is(bound->AsBitset(), BitsetType::Lub(min, max))); | 765 DCHECK(min->Number() <= max->Number()); |
695 RangeHandle type = Config::template cast<RangeType>( | 766 RangeHandle type = Config::template cast<RangeType>( |
696 StructuralType::New(StructuralType::kRangeTag, 3, region)); | 767 StructuralType::New(StructuralType::kRangeTag, 2, region)); |
697 type->Set(0, bound); | 768 type->SetValue(0, min); |
698 Factory* factory = Config::isolate(region)->factory(); | 769 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; | 770 return type; |
704 } | 771 } |
705 | 772 |
706 static RangeHandle New(double min, double max, Region* region) { | 773 static RangeHandle New(Limits lim, Region* region) { |
707 TypeHandle bound = BitsetType::New(BitsetType::Lub(min, max), region); | 774 return New(lim.min, lim.max, region); |
708 return New(min, max, bound, region); | |
709 } | 775 } |
710 | 776 |
711 static RangeType* cast(TypeImpl* type) { | 777 static RangeType* cast(TypeImpl* type) { |
712 DCHECK(type->IsRange()); | 778 DCHECK(type->IsRange()); |
713 return static_cast<RangeType*>(type); | 779 return static_cast<RangeType*>(type); |
714 } | 780 } |
715 }; | 781 }; |
716 | 782 |
717 | 783 |
718 // ----------------------------------------------------------------------------- | 784 // ----------------------------------------------------------------------------- |
719 // Context types. | 785 // Context types. |
720 | 786 |
721 template<class Config> | 787 template<class Config> |
722 class TypeImpl<Config>::ContextType : public StructuralType { | 788 class TypeImpl<Config>::ContextType : public StructuralType { |
723 public: | 789 public: |
724 TypeHandle Bound() { return this->Get(0); } | 790 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 | 791 |
737 static ContextHandle New(TypeHandle outer, Region* region) { | 792 static ContextHandle New(TypeHandle outer, Region* region) { |
738 TypeHandle bound = BitsetType::New( | 793 ContextHandle type = Config::template cast<ContextType>( |
739 BitsetType::kInternal & BitsetType::kTaggedPtr, region); | 794 StructuralType::New(StructuralType::kContextTag, 1, region)); |
740 return New(outer, bound, region); | 795 type->Set(0, outer); |
796 return type; | |
741 } | 797 } |
742 | 798 |
743 static ContextType* cast(TypeImpl* type) { | 799 static ContextType* cast(TypeImpl* type) { |
744 DCHECK(type->IsContext()); | 800 DCHECK(type->IsContext()); |
745 return static_cast<ContextType*>(type); | 801 return static_cast<ContextType*>(type); |
746 } | 802 } |
747 }; | 803 }; |
748 | 804 |
749 | 805 |
750 // ----------------------------------------------------------------------------- | 806 // ----------------------------------------------------------------------------- |
751 // Array types. | 807 // Array types. |
752 | 808 |
753 template<class Config> | 809 template<class Config> |
754 class TypeImpl<Config>::ArrayType : public StructuralType { | 810 class TypeImpl<Config>::ArrayType : public StructuralType { |
755 public: | 811 public: |
756 TypeHandle Bound() { return this->Get(0); } | 812 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 | 813 |
768 static ArrayHandle New(TypeHandle element, Region* region) { | 814 static ArrayHandle New(TypeHandle element, Region* region) { |
769 TypeHandle bound = BitsetType::New(BitsetType::kArray, region); | 815 ArrayHandle type = Config::template cast<ArrayType>( |
770 return New(element, bound, region); | 816 StructuralType::New(StructuralType::kArrayTag, 1, region)); |
817 type->Set(0, element); | |
818 return type; | |
771 } | 819 } |
772 | 820 |
773 static ArrayType* cast(TypeImpl* type) { | 821 static ArrayType* cast(TypeImpl* type) { |
774 DCHECK(type->IsArray()); | 822 DCHECK(type->IsArray()); |
775 return static_cast<ArrayType*>(type); | 823 return static_cast<ArrayType*>(type); |
776 } | 824 } |
777 }; | 825 }; |
778 | 826 |
779 | 827 |
780 // ----------------------------------------------------------------------------- | 828 // ----------------------------------------------------------------------------- |
781 // Function types. | 829 // Function types. |
782 | 830 |
783 template<class Config> | 831 template<class Config> |
784 class TypeImpl<Config>::FunctionType : public StructuralType { | 832 class TypeImpl<Config>::FunctionType : public StructuralType { |
785 public: | 833 public: |
786 int Arity() { return this->Length() - 3; } | 834 int Arity() { return this->Length() - 2; } |
787 TypeHandle Bound() { return this->Get(0); } | 835 TypeHandle Result() { return this->Get(0); } |
788 TypeHandle Result() { return this->Get(1); } | 836 TypeHandle Receiver() { return this->Get(1); } |
789 TypeHandle Receiver() { return this->Get(2); } | 837 TypeHandle Parameter(int i) { return this->Get(2 + i); } |
790 TypeHandle Parameter(int i) { return this->Get(3 + i); } | |
791 | 838 |
792 void InitParameter(int i, TypeHandle type) { this->Set(3 + i, type); } | 839 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 | 840 |
806 static FunctionHandle New( | 841 static FunctionHandle New( |
807 TypeHandle result, TypeHandle receiver, int arity, Region* region) { | 842 TypeHandle result, TypeHandle receiver, int arity, Region* region) { |
808 TypeHandle bound = BitsetType::New(BitsetType::kFunction, region); | 843 FunctionHandle type = Config::template cast<FunctionType>( |
809 return New(result, receiver, bound, arity, region); | 844 StructuralType::New(StructuralType::kFunctionTag, 2 + arity, region)); |
845 type->Set(0, result); | |
846 type->Set(1, receiver); | |
847 return type; | |
810 } | 848 } |
811 | 849 |
812 static FunctionType* cast(TypeImpl* type) { | 850 static FunctionType* cast(TypeImpl* type) { |
813 DCHECK(type->IsFunction()); | 851 DCHECK(type->IsFunction()); |
814 return static_cast<FunctionType*>(type); | 852 return static_cast<FunctionType*>(type); |
815 } | 853 } |
816 }; | 854 }; |
817 | 855 |
818 | 856 |
819 // ----------------------------------------------------------------------------- | 857 // ----------------------------------------------------------------------------- |
(...skipping 26 matching lines...) Expand all Loading... | |
846 // Zone-allocated types; they are either (odd) integers to represent bitsets, or | 884 // Zone-allocated types; they are either (odd) integers to represent bitsets, or |
847 // (even) pointers to structures for everything else. | 885 // (even) pointers to structures for everything else. |
848 | 886 |
849 struct ZoneTypeConfig { | 887 struct ZoneTypeConfig { |
850 typedef TypeImpl<ZoneTypeConfig> Type; | 888 typedef TypeImpl<ZoneTypeConfig> Type; |
851 class Base {}; | 889 class Base {}; |
852 typedef void* Struct; | 890 typedef void* Struct; |
853 typedef i::Zone Region; | 891 typedef i::Zone Region; |
854 template<class T> struct Handle { typedef T* type; }; | 892 template<class T> struct Handle { typedef T* type; }; |
855 | 893 |
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); | 894 template<class T> static inline T* handle(T* type); |
862 template<class T> static inline T* cast(Type* type); | 895 template<class T> static inline T* cast(Type* type); |
863 | 896 |
864 static inline bool is_bitset(Type* type); | 897 static inline bool is_bitset(Type* type); |
865 static inline bool is_class(Type* type); | 898 static inline bool is_class(Type* type); |
866 static inline bool is_struct(Type* type, int tag); | 899 static inline bool is_struct(Type* type, int tag); |
867 | 900 |
868 static inline int as_bitset(Type* type); | 901 static inline int as_bitset(Type* type); |
869 static inline i::Handle<i::Map> as_class(Type* type); | 902 static inline i::Handle<i::Map> as_class(Type* type); |
870 static inline Struct* as_struct(Type* type); | 903 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 | 926 // Heap-allocated types; either smis for bitsets, maps for classes, boxes for |
894 // constants, or fixed arrays for unions. | 927 // constants, or fixed arrays for unions. |
895 | 928 |
896 struct HeapTypeConfig { | 929 struct HeapTypeConfig { |
897 typedef TypeImpl<HeapTypeConfig> Type; | 930 typedef TypeImpl<HeapTypeConfig> Type; |
898 typedef i::Object Base; | 931 typedef i::Object Base; |
899 typedef i::FixedArray Struct; | 932 typedef i::FixedArray Struct; |
900 typedef i::Isolate Region; | 933 typedef i::Isolate Region; |
901 template<class T> struct Handle { typedef i::Handle<T> type; }; | 934 template<class T> struct Handle { typedef i::Handle<T> type; }; |
902 | 935 |
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); | 936 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); | 937 template<class T> static inline i::Handle<T> cast(i::Handle<Type> type); |
910 | 938 |
911 static inline bool is_bitset(Type* type); | 939 static inline bool is_bitset(Type* type); |
912 static inline bool is_class(Type* type); | 940 static inline bool is_class(Type* type); |
913 static inline bool is_struct(Type* type, int tag); | 941 static inline bool is_struct(Type* type, int tag); |
914 | 942 |
915 static inline int as_bitset(Type* type); | 943 static inline int as_bitset(Type* type); |
916 static inline i::Handle<i::Map> as_class(Type* type); | 944 static inline i::Handle<i::Map> as_class(Type* type); |
917 static inline i::Handle<Struct> as_struct(Type* type); | 945 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) { | 1023 bool Narrows(BoundsImpl that) { |
996 return that.lower->Is(this->lower) && this->upper->Is(that.upper); | 1024 return that.lower->Is(this->lower) && this->upper->Is(that.upper); |
997 } | 1025 } |
998 }; | 1026 }; |
999 | 1027 |
1000 typedef BoundsImpl<ZoneTypeConfig> Bounds; | 1028 typedef BoundsImpl<ZoneTypeConfig> Bounds; |
1001 | 1029 |
1002 } } // namespace v8::internal | 1030 } } // namespace v8::internal |
1003 | 1031 |
1004 #endif // V8_TYPES_H_ | 1032 #endif // V8_TYPES_H_ |
OLD | NEW |