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

Side by Side Diff: src/types.h

Issue 558193003: Redesign of the internal type system. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Dito Created 6 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | src/types.cc » ('j') | src/types.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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 do not distinguish between -0 and +0. If the type equals
448 // kNaN, they return NaN; otherwise kNaN is ignored. Only call these
449 // functions on subtypes of Number.
450 double Min();
451 double Max();
452
407 int NumClasses(); 453 int NumClasses();
408 int NumConstants(); 454 int NumConstants();
409 455
410 template<class T> class Iterator; 456 template<class T> class Iterator;
411 Iterator<i::Map> Classes() { 457 Iterator<i::Map> Classes() {
412 if (this->IsBitset()) return Iterator<i::Map>(); 458 if (this->IsBitset()) return Iterator<i::Map>();
413 return Iterator<i::Map>(Config::handle(this)); 459 return Iterator<i::Map>(Config::handle(this));
414 } 460 }
415 Iterator<i::Object> Constants() { 461 Iterator<i::Object> Constants() {
416 if (this->IsBitset()) return Iterator<i::Object>(); 462 if (this->IsBitset()) return Iterator<i::Object>();
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
459 int AsBitset() { 505 int AsBitset() {
460 DCHECK(this->IsBitset()); 506 DCHECK(this->IsBitset());
461 return static_cast<BitsetType*>(this)->Bitset(); 507 return static_cast<BitsetType*>(this)->Bitset();
462 } 508 }
463 UnionType* AsUnion() { return UnionType::cast(this); } 509 UnionType* AsUnion() { return UnionType::cast(this); }
464 510
465 // Auxiliary functions. 511 // Auxiliary functions.
466 512
467 int BitsetGlb() { return BitsetType::Glb(this); } 513 int BitsetGlb() { return BitsetType::Glb(this); }
468 int BitsetLub() { return BitsetType::Lub(this); } 514 int BitsetLub() { return BitsetType::Lub(this); }
469 int InherentBitsetLub() { return BitsetType::InherentLub(this); }
470 515
471 bool SlowIs(TypeImpl* that); 516 bool SlowIs(TypeImpl* that);
472 517
473 TypeHandle Rebound(int bitset, Region* region); 518 static bool IsInteger(double x) {
474 int BoundBy(TypeImpl* that); 519 return nearbyint(x) == x && !i::IsMinusZero(x); // Allows for infinities.
475 int IndexInUnion(int bound, UnionHandle unioned, int current_size); 520 }
476 static int ExtendUnion( 521 static bool IsInteger(i::Object* x) {
477 UnionHandle unioned, int current_size, TypeHandle t, 522 return x->IsNumber() && IsInteger(x->Number());
478 TypeHandle other, bool is_intersect, Region* region); 523 }
524
525 struct Limits {
526 i::Handle<i::Object> min;
527 i::Handle<i::Object> max;
528 Limits(i::Handle<i::Object> min, i::Handle<i::Object> max) :
529 min(min), max(max) {}
530 explicit Limits(RangeType* range) :
531 min(range->Min()), max(range->Max()) {}
532 };
533
534 static Limits Intersect(Limits lhs, Limits rhs);
535 static Limits Union(Limits lhs, Limits rhs);
536 static bool Overlap(RangeType* lhs, RangeType* rhs);
537 static bool Contains(RangeType* lhs, RangeType* rhs);
538 static bool Contains(RangeType* range, i::Object* val);
539
540 RangeType* GetRange();
541 static int UpdateRange(
542 RangeHandle type, UnionHandle result, int size, Region* region);
543
544 bool SimplyEquals(TypeImpl* that);
545 template<class TypeHandle>
546 bool SimplyEquals(TypeHandle that) { return this->SimplyEquals(*that); }
547
548 static int AddToUnion(
549 TypeHandle type, UnionHandle result, int size, Region* region);
550 static int IntersectAux(
551 TypeHandle type, TypeHandle other,
552 UnionHandle result, int size, Region* region);
553 static TypeHandle NormalizeUnion(UnionHandle unioned, int size);
479 }; 554 };
480 555
481 556
482 // ----------------------------------------------------------------------------- 557 // -----------------------------------------------------------------------------
483 // Bitset types (internal). 558 // Bitset types (internal).
484 559
485 template<class Config> 560 template<class Config>
486 class TypeImpl<Config>::BitsetType : public TypeImpl<Config> { 561 class TypeImpl<Config>::BitsetType : public TypeImpl<Config> {
487 protected: 562 protected:
488 friend class TypeImpl<Config>; 563 friend class TypeImpl<Config>;
489 564
490 enum { 565 enum {
491 #define DECLARE_TYPE(type, value) k##type = (value), 566 #define DECLARE_TYPE(type, value) k##type = (value),
492 BITSET_TYPE_LIST(DECLARE_TYPE) 567 BITSET_TYPE_LIST(DECLARE_TYPE)
493 #undef DECLARE_TYPE 568 #undef DECLARE_TYPE
494 kUnusedEOL = 0 569 kUnusedEOL = 0
495 }; 570 };
496 571
497 int Bitset() { return Config::as_bitset(this); } 572 int Bitset() { return Config::as_bitset(this); }
498 573
499 static TypeImpl* New(int bitset) { 574 static TypeImpl* New(int bitset) {
575 DCHECK(bitset == kNone || IsInhabited(bitset));
500 return static_cast<BitsetType*>(Config::from_bitset(bitset)); 576 return static_cast<BitsetType*>(Config::from_bitset(bitset));
501 } 577 }
502 static TypeHandle New(int bitset, Region* region) { 578 static TypeHandle New(int bitset, Region* region) {
579 DCHECK(bitset == kNone || IsInhabited(bitset));
503 return Config::from_bitset(bitset, region); 580 return Config::from_bitset(bitset, region);
504 } 581 }
582 // TODO(neis): Eventually allow again for types with empty semantics
583 // part and modify intersection and possibly subtyping accordingly.
505 584
506 static bool IsInhabited(int bitset) { 585 static bool IsInhabited(int bitset) {
507 return (bitset & kRepresentation) && (bitset & kSemantic); 586 return bitset & kSemantic;
508 } 587 }
509 588
510 static bool Is(int bitset1, int bitset2) { 589 static bool Is(int bitset1, int bitset2) {
511 return (bitset1 | bitset2) == bitset2; 590 return (bitset1 | bitset2) == bitset2;
512 } 591 }
513 592
593 static double Min(int bitset);
594 static double Max(int bitset);
595
514 static int Glb(TypeImpl* type); // greatest lower bound that's a bitset 596 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 597 static int Lub(TypeImpl* type); // least upper bound that's a bitset
516 static int Lub(i::Object* value); 598 static int Lub(i::Object* value);
517 static int Lub(double value); 599 static int Lub(double value);
518 static int Lub(int32_t value); 600 static int Lub(int32_t value);
519 static int Lub(uint32_t value); 601 static int Lub(uint32_t value);
520 static int Lub(i::Map* map); 602 static int Lub(i::Map* map);
521 static int Lub(double min, double max); 603 static int Lub(Limits lim);
522 static int InherentLub(TypeImpl* type);
523 604
524 static const char* Name(int bitset); 605 static const char* Name(int bitset);
525 static void Print(OStream& os, int bitset); // NOLINT 606 static void Print(OStream& os, int bitset); // NOLINT
526 using TypeImpl::PrintTo; 607 #ifdef DEBUG
608 static void Print(int bitset);
609 #endif
610
611 private:
612 struct BitsetMin{
613 int bitset;
614 double min;
615 };
616 static const BitsetMin BitsetMins31[];
617 static const BitsetMin BitsetMins32[];
618 static const BitsetMin* BitsetMins() {
619 return i::SmiValuesAre31Bits() ? BitsetMins31 : BitsetMins32;
620 }
621 static size_t BitsetMinsSize() {
622 return i::SmiValuesAre31Bits() ? 7 : 5;
623 /* arraysize(BitsetMins31) : arraysize(BitsetMins32); */
624 // Using arraysize here doesn't compile on Windows.
625 }
527 }; 626 };
528 627
529 628
530 // ----------------------------------------------------------------------------- 629 // -----------------------------------------------------------------------------
531 // Superclass for non-bitset types (internal). 630 // Superclass for non-bitset types (internal).
532 // Contains a tag and a variable number of type or value fields. 631 // Contains a tag and a variable number of type or value fields.
533 632
534 template<class Config> 633 template<class Config>
535 class TypeImpl<Config>::StructuralType : public TypeImpl<Config> { 634 class TypeImpl<Config>::StructuralType : public TypeImpl<Config> {
536 protected: 635 protected:
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
602 bool Wellformed(); 701 bool Wellformed();
603 }; 702 };
604 703
605 704
606 // ----------------------------------------------------------------------------- 705 // -----------------------------------------------------------------------------
607 // Class types. 706 // Class types.
608 707
609 template<class Config> 708 template<class Config>
610 class TypeImpl<Config>::ClassType : public StructuralType { 709 class TypeImpl<Config>::ClassType : public StructuralType {
611 public: 710 public:
612 TypeHandle Bound(Region* region) { 711 int BitsetLub() {
rossberg 2014/09/23 15:20:38 This can't go here like this, as bitsets are an im
neis1 2014/09/24 07:21:38 Oops, forgot about that. I wanted to avoid the "l
613 return Config::is_class(this) 712 return Config::is_class(this) ?
614 ? BitsetType::New(BitsetType::Lub(*Config::as_class(this)), region) 713 BitsetType::Lub(*Config::as_class(this)) : this->Get(0)->AsBitset();
615 : this->Get(0);
616 } 714 }
617 i::Handle<i::Map> Map() { 715 i::Handle<i::Map> Map() {
618 return Config::is_class(this) 716 return Config::is_class(this) ?
619 ? Config::as_class(this) 717 Config::as_class(this) : this->template GetValue<i::Map>(1);
620 : this->template GetValue<i::Map>(1);
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 } 718 }
632 719
633 static ClassHandle New(i::Handle<i::Map> map, Region* region) { 720 static ClassHandle New(i::Handle<i::Map> map, Region* region) {
634 ClassHandle type = 721 ClassHandle type =
635 Config::template cast<ClassType>(Config::from_class(map, region)); 722 Config::template cast<ClassType>(Config::from_class(map, region));
636 if (type->IsClass()) { 723 if (!type->IsClass()) {
637 return type; 724 type = Config::template cast<ClassType>(
638 } else { 725 StructuralType::New(StructuralType::kClassTag, 2, region));
639 TypeHandle bound = BitsetType::New(BitsetType::Lub(*map), region); 726 type->Set(0, BitsetType::New(BitsetType::Lub(*map), region));
640 return New(map, bound, region); 727 type->SetValue(1, map);
641 } 728 }
729 return type;
642 } 730 }
643 731
644 static ClassType* cast(TypeImpl* type) { 732 static ClassType* cast(TypeImpl* type) {
645 DCHECK(type->IsClass()); 733 DCHECK(type->IsClass());
646 return static_cast<ClassType*>(type); 734 return static_cast<ClassType*>(type);
647 } 735 }
648 }; 736 };
649 737
650 738
651 // ----------------------------------------------------------------------------- 739 // -----------------------------------------------------------------------------
652 // Constant types. 740 // Constant types.
653 741
654 template<class Config> 742 template<class Config>
655 class TypeImpl<Config>::ConstantType : public StructuralType { 743 class TypeImpl<Config>::ConstantType : public StructuralType {
656 public: 744 public:
657 TypeHandle Bound() { return this->Get(0); } 745 int BitsetLub() { return this->Get(0)->AsBitset(); }
rossberg 2014/09/23 15:20:38 Same here.
neis1 2014/09/24 07:21:38 Done.
658 i::Handle<i::Object> Value() { return this->template GetValue<i::Object>(1); } 746 i::Handle<i::Object> Value() { return this->template GetValue<i::Object>(1); }
659 747
660 static ConstantHandle New( 748 static ConstantHandle New(i::Handle<i::Object> value, Region* region) {
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>( 749 ConstantHandle type = Config::template cast<ConstantType>(
664 StructuralType::New(StructuralType::kConstantTag, 2, region)); 750 StructuralType::New(StructuralType::kConstantTag, 2, region));
665 type->Set(0, bound); 751 type->Set(0, BitsetType::New(BitsetType::Lub(*value), region));
666 type->SetValue(1, value); 752 type->SetValue(1, value);
667 return type; 753 return type;
668 } 754 }
669 755
670 static ConstantHandle New(i::Handle<i::Object> value, Region* region) {
671 TypeHandle bound = BitsetType::New(BitsetType::Lub(*value), region);
672 return New(value, bound, region);
673 }
674
675 static ConstantType* cast(TypeImpl* type) { 756 static ConstantType* cast(TypeImpl* type) {
676 DCHECK(type->IsConstant()); 757 DCHECK(type->IsConstant());
677 return static_cast<ConstantType*>(type); 758 return static_cast<ConstantType*>(type);
678 } 759 }
679 }; 760 };
761 // TODO(neis): Also cache value if numerical.
762 // TODO(neis): Allow restricting the representation.
680 763
681 764
682 // ----------------------------------------------------------------------------- 765 // -----------------------------------------------------------------------------
683 // Range types. 766 // Range types.
684 767
685 template<class Config> 768 template<class Config>
686 class TypeImpl<Config>::RangeType : public StructuralType { 769 class TypeImpl<Config>::RangeType : public StructuralType {
687 public: 770 public:
688 TypeHandle Bound() { return this->Get(0); } 771 int BitsetLub() { return this->Get(0)->AsBitset(); }
689 double Min() { return this->template GetValue<i::HeapNumber>(1)->value(); } 772 i::Handle<i::Object> Min() { return this->template GetValue<i::Object>(1); }
690 double Max() { return this->template GetValue<i::HeapNumber>(2)->value(); } 773 i::Handle<i::Object> Max() { return this->template GetValue<i::Object>(2); }
691 774
692 static RangeHandle New( 775 static RangeHandle New(
693 double min, double max, TypeHandle bound, Region* region) { 776 i::Handle<i::Object> min, i::Handle<i::Object> max, Region* region) {
694 DCHECK(BitsetType::Is(bound->AsBitset(), BitsetType::Lub(min, max))); 777 DCHECK(min->Number() <= max->Number());
695 RangeHandle type = Config::template cast<RangeType>( 778 RangeHandle type = Config::template cast<RangeType>(
696 StructuralType::New(StructuralType::kRangeTag, 3, region)); 779 StructuralType::New(StructuralType::kRangeTag, 3, region));
697 type->Set(0, bound); 780 type->Set(0, BitsetType::New(BitsetType::Lub(Limits(min, max)), region));
698 Factory* factory = Config::isolate(region)->factory(); 781 type->SetValue(1, min);
699 Handle<HeapNumber> minV = factory->NewHeapNumber(min); 782 type->SetValue(2, max);
700 Handle<HeapNumber> maxV = factory->NewHeapNumber(max);
701 type->SetValue(1, minV);
702 type->SetValue(2, maxV);
703 return type; 783 return type;
704 } 784 }
705 785
706 static RangeHandle New(double min, double max, Region* region) { 786 static RangeHandle New(Limits lim, Region* region) {
707 TypeHandle bound = BitsetType::New(BitsetType::Lub(min, max), region); 787 return New(lim.min, lim.max, region);
708 return New(min, max, bound, region);
709 } 788 }
710 789
711 static RangeType* cast(TypeImpl* type) { 790 static RangeType* cast(TypeImpl* type) {
712 DCHECK(type->IsRange()); 791 DCHECK(type->IsRange());
713 return static_cast<RangeType*>(type); 792 return static_cast<RangeType*>(type);
714 } 793 }
715 }; 794 };
795 // TODO(neis): Also cache min and max values.
796 // TODO(neis): Allow restricting the representation.
716 797
717 798
718 // ----------------------------------------------------------------------------- 799 // -----------------------------------------------------------------------------
719 // Context types. 800 // Context types.
720 801
721 template<class Config> 802 template<class Config>
722 class TypeImpl<Config>::ContextType : public StructuralType { 803 class TypeImpl<Config>::ContextType : public StructuralType {
723 public: 804 public:
724 TypeHandle Bound() { return this->Get(0); } 805 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 806
737 static ContextHandle New(TypeHandle outer, Region* region) { 807 static ContextHandle New(TypeHandle outer, Region* region) {
738 TypeHandle bound = BitsetType::New( 808 ContextHandle type = Config::template cast<ContextType>(
739 BitsetType::kInternal & BitsetType::kTaggedPtr, region); 809 StructuralType::New(StructuralType::kContextTag, 1, region));
740 return New(outer, bound, region); 810 type->Set(0, outer);
811 return type;
741 } 812 }
742 813
743 static ContextType* cast(TypeImpl* type) { 814 static ContextType* cast(TypeImpl* type) {
744 DCHECK(type->IsContext()); 815 DCHECK(type->IsContext());
745 return static_cast<ContextType*>(type); 816 return static_cast<ContextType*>(type);
746 } 817 }
747 }; 818 };
748 819
749 820
750 // ----------------------------------------------------------------------------- 821 // -----------------------------------------------------------------------------
751 // Array types. 822 // Array types.
752 823
753 template<class Config> 824 template<class Config>
754 class TypeImpl<Config>::ArrayType : public StructuralType { 825 class TypeImpl<Config>::ArrayType : public StructuralType {
755 public: 826 public:
756 TypeHandle Bound() { return this->Get(0); } 827 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 828
768 static ArrayHandle New(TypeHandle element, Region* region) { 829 static ArrayHandle New(TypeHandle element, Region* region) {
769 TypeHandle bound = BitsetType::New(BitsetType::kArray, region); 830 ArrayHandle type = Config::template cast<ArrayType>(
770 return New(element, bound, region); 831 StructuralType::New(StructuralType::kArrayTag, 1, region));
832 type->Set(0, element);
833 return type;
771 } 834 }
772 835
773 static ArrayType* cast(TypeImpl* type) { 836 static ArrayType* cast(TypeImpl* type) {
774 DCHECK(type->IsArray()); 837 DCHECK(type->IsArray());
775 return static_cast<ArrayType*>(type); 838 return static_cast<ArrayType*>(type);
776 } 839 }
777 }; 840 };
778 841
779 842
780 // ----------------------------------------------------------------------------- 843 // -----------------------------------------------------------------------------
781 // Function types. 844 // Function types.
782 845
783 template<class Config> 846 template<class Config>
784 class TypeImpl<Config>::FunctionType : public StructuralType { 847 class TypeImpl<Config>::FunctionType : public StructuralType {
785 public: 848 public:
786 int Arity() { return this->Length() - 3; } 849 int Arity() { return this->Length() - 2; }
787 TypeHandle Bound() { return this->Get(0); } 850 TypeHandle Result() { return this->Get(0); }
788 TypeHandle Result() { return this->Get(1); } 851 TypeHandle Receiver() { return this->Get(1); }
789 TypeHandle Receiver() { return this->Get(2); } 852 TypeHandle Parameter(int i) { return this->Get(2 + i); }
790 TypeHandle Parameter(int i) { return this->Get(3 + i); }
791 853
792 void InitParameter(int i, TypeHandle type) { this->Set(3 + i, type); } 854 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 855
806 static FunctionHandle New( 856 static FunctionHandle New(
807 TypeHandle result, TypeHandle receiver, int arity, Region* region) { 857 TypeHandle result, TypeHandle receiver, int arity, Region* region) {
808 TypeHandle bound = BitsetType::New(BitsetType::kFunction, region); 858 FunctionHandle type = Config::template cast<FunctionType>(
809 return New(result, receiver, bound, arity, region); 859 StructuralType::New(StructuralType::kFunctionTag, 2 + arity, region));
860 type->Set(0, result);
861 type->Set(1, receiver);
862 return type;
810 } 863 }
811 864
812 static FunctionType* cast(TypeImpl* type) { 865 static FunctionType* cast(TypeImpl* type) {
813 DCHECK(type->IsFunction()); 866 DCHECK(type->IsFunction());
814 return static_cast<FunctionType*>(type); 867 return static_cast<FunctionType*>(type);
815 } 868 }
816 }; 869 };
817 870
818 871
819 // ----------------------------------------------------------------------------- 872 // -----------------------------------------------------------------------------
(...skipping 26 matching lines...) Expand all
846 // Zone-allocated types; they are either (odd) integers to represent bitsets, or 899 // Zone-allocated types; they are either (odd) integers to represent bitsets, or
847 // (even) pointers to structures for everything else. 900 // (even) pointers to structures for everything else.
848 901
849 struct ZoneTypeConfig { 902 struct ZoneTypeConfig {
850 typedef TypeImpl<ZoneTypeConfig> Type; 903 typedef TypeImpl<ZoneTypeConfig> Type;
851 class Base {}; 904 class Base {};
852 typedef void* Struct; 905 typedef void* Struct;
853 typedef i::Zone Region; 906 typedef i::Zone Region;
854 template<class T> struct Handle { typedef T* type; }; 907 template<class T> struct Handle { typedef T* type; };
855 908
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); 909 template<class T> static inline T* handle(T* type);
862 template<class T> static inline T* cast(Type* type); 910 template<class T> static inline T* cast(Type* type);
863 911
864 static inline bool is_bitset(Type* type); 912 static inline bool is_bitset(Type* type);
865 static inline bool is_class(Type* type); 913 static inline bool is_class(Type* type);
866 static inline bool is_struct(Type* type, int tag); 914 static inline bool is_struct(Type* type, int tag);
867 915
868 static inline int as_bitset(Type* type); 916 static inline int as_bitset(Type* type);
869 static inline i::Handle<i::Map> as_class(Type* type); 917 static inline i::Handle<i::Map> as_class(Type* type);
870 static inline Struct* as_struct(Type* type); 918 static inline Struct* as_struct(Type* type);
(...skipping 22 matching lines...) Expand all
893 // Heap-allocated types; either smis for bitsets, maps for classes, boxes for 941 // Heap-allocated types; either smis for bitsets, maps for classes, boxes for
894 // constants, or fixed arrays for unions. 942 // constants, or fixed arrays for unions.
895 943
896 struct HeapTypeConfig { 944 struct HeapTypeConfig {
897 typedef TypeImpl<HeapTypeConfig> Type; 945 typedef TypeImpl<HeapTypeConfig> Type;
898 typedef i::Object Base; 946 typedef i::Object Base;
899 typedef i::FixedArray Struct; 947 typedef i::FixedArray Struct;
900 typedef i::Isolate Region; 948 typedef i::Isolate Region;
901 template<class T> struct Handle { typedef i::Handle<T> type; }; 949 template<class T> struct Handle { typedef i::Handle<T> type; };
902 950
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); 951 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); 952 template<class T> static inline i::Handle<T> cast(i::Handle<Type> type);
910 953
911 static inline bool is_bitset(Type* type); 954 static inline bool is_bitset(Type* type);
912 static inline bool is_class(Type* type); 955 static inline bool is_class(Type* type);
913 static inline bool is_struct(Type* type, int tag); 956 static inline bool is_struct(Type* type, int tag);
914 957
915 static inline int as_bitset(Type* type); 958 static inline int as_bitset(Type* type);
916 static inline i::Handle<i::Map> as_class(Type* type); 959 static inline i::Handle<i::Map> as_class(Type* type);
917 static inline i::Handle<Struct> as_struct(Type* type); 960 static inline i::Handle<Struct> as_struct(Type* type);
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
995 bool Narrows(BoundsImpl that) { 1038 bool Narrows(BoundsImpl that) {
996 return that.lower->Is(this->lower) && this->upper->Is(that.upper); 1039 return that.lower->Is(this->lower) && this->upper->Is(that.upper);
997 } 1040 }
998 }; 1041 };
999 1042
1000 typedef BoundsImpl<ZoneTypeConfig> Bounds; 1043 typedef BoundsImpl<ZoneTypeConfig> Bounds;
1001 1044
1002 } } // namespace v8::internal 1045 } } // namespace v8::internal
1003 1046
1004 #endif // V8_TYPES_H_ 1047 #endif // V8_TYPES_H_
OLDNEW
« no previous file with comments | « no previous file | src/types.cc » ('j') | src/types.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698