OLD | NEW |
---|---|
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 24 matching lines...) Expand all Loading... | |
35 namespace v8 { | 35 namespace v8 { |
36 namespace internal { | 36 namespace internal { |
37 | 37 |
38 | 38 |
39 // A simple type system for compiler-internal use. It is based entirely on | 39 // A simple type system for compiler-internal use. It is based entirely on |
40 // union types, and all subtyping hence amounts to set inclusion. Besides the | 40 // union types, and all subtyping hence amounts to set inclusion. Besides the |
41 // obvious primitive types and some predefined unions, the type language also | 41 // obvious primitive types and some predefined unions, the type language also |
42 // can express class types (a.k.a. specific maps) and singleton types (i.e., | 42 // can express class types (a.k.a. specific maps) and singleton types (i.e., |
43 // concrete constants). | 43 // concrete constants). |
44 // | 44 // |
45 // The following equations and inequations hold: | 45 // Types consist of two dimensions: semantic (value range) and representation. |
46 // Both are related through subtyping. | |
47 // | |
48 // The following equations and inequations hold for the semantic axis: | |
46 // | 49 // |
47 // None <= T | 50 // None <= T |
48 // T <= Any | 51 // T <= Any |
49 // | 52 // |
50 // Oddball = Boolean \/ Null \/ Undefined | 53 // Oddball = Boolean \/ Null \/ Undefined |
51 // Number = Signed32 \/ Unsigned32 \/ Double | 54 // Number = Signed32 \/ Unsigned32 \/ Double |
52 // Smi <= Signed32 | 55 // Smi <= Signed32 |
53 // Name = String \/ Symbol | 56 // Name = String \/ Symbol |
54 // UniqueName = InternalizedString \/ Symbol | 57 // UniqueName = InternalizedString \/ Symbol |
55 // InternalizedString < String | 58 // InternalizedString < String |
56 // | 59 // |
57 // Allocated = Receiver \/ Number \/ Name | |
58 // Detectable = Allocated - Undetectable | |
59 // Undetectable < Object | |
60 // Receiver = Object \/ Proxy | 60 // Receiver = Object \/ Proxy |
61 // Array < Object | 61 // Array < Object |
62 // Function < Object | 62 // Function < Object |
63 // RegExp < Object | 63 // RegExp < Object |
64 // Undetectable < Object | |
65 // Detectable = Receiver \/ Number \/ Name - Undetectable | |
64 // | 66 // |
65 // Class(map) < T iff instance_type(map) < T | 67 // Class(map) < T iff instance_type(map) < T |
66 // Constant(x) < T iff instance_type(map(x)) < T | 68 // Constant(x) < T iff instance_type(map(x)) < T |
67 // | 69 // |
68 // Note that Constant(x) < Class(map(x)) does _not_ hold, since x's map can | 70 // Note that Constant(x) < Class(map(x)) does _not_ hold, since x's map can |
69 // change! (Its instance type cannot, however.) | 71 // change! (Its instance type cannot, however.) |
70 // TODO(rossberg): the latter is not currently true for proxies, because of fix, | 72 // TODO(rossberg): the latter is not currently true for proxies, because of fix, |
71 // but will hold once we implement direct proxies. | 73 // but will hold once we implement direct proxies. |
72 // | 74 // |
75 // For the representation axis, the following holds: | |
76 // | |
77 // None <= R | |
78 // R <= Any | |
79 // | |
80 // UntaggedInt <= UntaggedInt8 \/ UntaggedInt16 \/ UntaggedInt32) | |
81 // UntaggedFloat <= UntaggedFloat32 \/ UntaggedFloat64 | |
82 // UntaggedNumber <= UntaggedInt \/ UntaggedFloat | |
83 // Untagged <= UntaggedNumber \/ UntaggedPtr | |
84 // Tagged <= TaggedInt \/ TaggedPtr | |
85 // | |
86 // Subtyping relates the two dimensions, for example: | |
87 // | |
88 // Number <= Tagged \/ UntaggedNumber | |
89 // Object <= TaggedPtr \/ UntaggedPtr | |
90 // | |
91 // That holds because the semantic type constructors defined by the API create | |
92 // types that allow for all possible representations, and dually, the ones for | |
93 // representation types initially include all semantic ranges. Representations | |
94 // can then e.g. be narrowed for a given semantic type using intersection: | |
95 // | |
96 // SignedSmall /\ TaggedInt (a 'smi') | |
97 // Number /\ TaggedPtr (a heap number) | |
98 // | |
73 // There are two main functions for testing types: | 99 // There are two main functions for testing types: |
74 // | 100 // |
75 // T1->Is(T2) -- tests whether T1 is included in T2 (i.e., T1 <= T2) | 101 // T1->Is(T2) -- tests whether T1 is included in T2 (i.e., T1 <= T2) |
76 // T1->Maybe(T2) -- tests whether T1 and T2 overlap (i.e., T1 /\ T2 =/= 0) | 102 // T1->Maybe(T2) -- tests whether T1 and T2 overlap (i.e., T1 /\ T2 =/= 0) |
77 // | 103 // |
78 // Typically, the former is to be used to select representations (e.g., via | 104 // Typically, the former is to be used to select representations (e.g., via |
79 // T->Is(Integer31())), and the to check whether a specific case needs handling | 105 // T->Is(SignedSmall())), and the latter to check whether a specific case needs |
80 // (e.g., via T->Maybe(Number())). | 106 // handling (e.g., via T->Maybe(Number())). |
81 // | 107 // |
82 // There is no functionality to discover whether a type is a leaf in the | 108 // There is no functionality to discover whether a type is a leaf in the |
83 // lattice. That is intentional. It should always be possible to refine the | 109 // lattice. That is intentional. It should always be possible to refine the |
84 // lattice (e.g., splitting up number types further) without invalidating any | 110 // lattice (e.g., splitting up number types further) without invalidating any |
85 // existing assumptions or tests. | 111 // existing assumptions or tests. |
86 // | |
87 // Consequently, do not use pointer equality for type tests, always use Is! | 112 // Consequently, do not use pointer equality for type tests, always use Is! |
88 // | 113 // |
89 // Internally, all 'primitive' types, and their unions, are represented as | 114 // Internally, all 'primitive' types, and their unions, are represented as |
90 // bitsets via smis. Class is a heap pointer to the respective map. Only | 115 // bitsets. Class is a heap pointer to the respective map. Only Constant's, or |
91 // Constant's, or unions containing Class'es or Constant's, require allocation. | 116 // unions containing Class'es or Constant's, currently require allocation. |
92 // Note that the bitset representation is closed under both Union and Intersect. | 117 // Note that the bitset representation is closed under both Union and Intersect. |
93 // | 118 // |
94 // The type representation is heap-allocated, so cannot (currently) be used in | 119 // There are two type representations, using different allocation: |
95 // a concurrent compilation context. | 120 // |
121 // - class Type (zone-allocated, for compiler and concurrent compilation) | |
122 // - class HeapType (heap-allocated, for persistent types) | |
123 // | |
124 // Both provide the same API, and the Convert method can be used to interconvert | |
125 // them. | |
96 | 126 |
97 | 127 |
98 #define BITSET_TYPE_LIST(V) \ | 128 #define MASK_BITSET_TYPE_LIST(V) \ |
99 V(None, 0) \ | 129 V(Representation, static_cast<int>(0xff800000)) \ |
100 V(Null, 1 << 0) \ | 130 V(Semantic, static_cast<int>(0x007fffff)) |
101 V(Undefined, 1 << 1) \ | 131 |
102 V(Boolean, 1 << 2) \ | 132 #define REPRESENTATION(k) ((k) & kRepresentation) |
103 V(Smi, 1 << 3) \ | 133 #define SEMANTIC(k) ((k) & kSemantic) |
104 V(OtherSigned32, 1 << 4) \ | 134 |
105 V(Unsigned32, 1 << 5) \ | 135 #define REPRESENTATION_BITSET_TYPE_LIST(V) \ |
106 V(Double, 1 << 6) \ | 136 V(None, 0) \ |
107 V(Symbol, 1 << 7) \ | 137 V(UntaggedInt8, 1 << 23 | kSemantic) \ |
108 V(InternalizedString, 1 << 8) \ | 138 V(UntaggedInt16, 1 << 24 | kSemantic) \ |
109 V(OtherString, 1 << 9) \ | 139 V(UntaggedInt32, 1 << 25 | kSemantic) \ |
110 V(Undetectable, 1 << 10) \ | 140 V(UntaggedFloat32, 1 << 26 | kSemantic) \ |
111 V(Array, 1 << 11) \ | 141 V(UntaggedFloat64, 1 << 27 | kSemantic) \ |
112 V(Function, 1 << 12) \ | 142 V(UntaggedPtr, 1 << 28 | kSemantic) \ |
113 V(RegExp, 1 << 13) \ | 143 V(TaggedInt, 1 << 29 | kSemantic) \ |
114 V(OtherObject, 1 << 14) \ | 144 V(TaggedPtr, -1 << 30 | kSemantic) /* MSB has to be sign-extended */ \ |
Michael Starzinger
2014/03/04 15:02:25
I would be fine with this. If either Benedikt or S
Sven Panne
2014/03/05 07:22:36
As already discussed yesterday, I consider this si
Benedikt Meurer
2014/03/05 07:28:07
I agree. We should not introduce hacks like this u
rossberg
2014/03/14 10:37:37
Michael yesterday (after you had left) expressed v
Michael Starzinger
2014/03/14 10:49:36
So just to clarify: My strong disagreement is agai
| |
115 V(Proxy, 1 << 15) \ | |
116 V(Internal, 1 << 16) \ | |
117 \ | 145 \ |
118 V(Oddball, kBoolean | kNull | kUndefined) \ | 146 V(UntaggedInt, kUntaggedInt8 | kUntaggedInt16 | kUntaggedInt32) \ |
119 V(Signed32, kSmi | kOtherSigned32) \ | 147 V(UntaggedFloat, kUntaggedFloat32 | kUntaggedFloat64) \ |
120 V(Number, kSigned32 | kUnsigned32 | kDouble) \ | 148 V(UntaggedNumber, kUntaggedInt | kUntaggedFloat) \ |
121 V(String, kInternalizedString | kOtherString) \ | 149 V(Untagged, kUntaggedNumber | kUntaggedPtr) \ |
122 V(UniqueName, kSymbol | kInternalizedString) \ | 150 V(Tagged, kTaggedInt | kTaggedPtr) |
123 V(Name, kSymbol | kString) \ | 151 |
124 V(NumberOrString, kNumber | kString) \ | 152 #define SEMANTIC_BITSET_TYPE_LIST(V) \ |
125 V(Object, kUndetectable | kArray | kFunction | \ | 153 V(Null, 1 << 0 | REPRESENTATION(kTaggedPtr)) \ |
126 kRegExp | kOtherObject) \ | 154 V(Undefined, 1 << 1 | REPRESENTATION(kTaggedPtr)) \ |
127 V(Receiver, kObject | kProxy) \ | 155 V(Boolean, 1 << 2 | REPRESENTATION(kTaggedPtr)) \ |
128 V(Allocated, kDouble | kName | kReceiver) \ | 156 V(SignedSmall, 1 << 3 | REPRESENTATION(kTagged | kUntaggedNumber)) \ |
129 V(Any, kOddball | kNumber | kAllocated | kInternal) \ | 157 V(OtherSigned32, 1 << 4 | REPRESENTATION(kTagged | kUntaggedNumber)) \ |
130 V(NonNumber, kAny - kNumber) \ | 158 V(Unsigned32, 1 << 5 | REPRESENTATION(kTagged | kUntaggedNumber)) \ |
131 V(Detectable, kAllocated - kUndetectable) | 159 V(Float, 1 << 6 | REPRESENTATION(kTagged | kUntaggedNumber)) \ |
160 V(Symbol, 1 << 7 | REPRESENTATION(kTaggedPtr)) \ | |
161 V(InternalizedString, 1 << 8 | REPRESENTATION(kTaggedPtr)) \ | |
162 V(OtherString, 1 << 9 | REPRESENTATION(kTaggedPtr)) \ | |
163 V(Undetectable, 1 << 10 | REPRESENTATION(kTaggedPtr)) \ | |
164 V(Array, 1 << 11 | REPRESENTATION(kTaggedPtr)) \ | |
165 V(Function, 1 << 12 | REPRESENTATION(kTaggedPtr)) \ | |
166 V(RegExp, 1 << 13 | REPRESENTATION(kTaggedPtr)) \ | |
167 V(OtherObject, 1 << 14 | REPRESENTATION(kTaggedPtr)) \ | |
168 V(Proxy, 1 << 15 | REPRESENTATION(kTaggedPtr)) \ | |
169 V(Internal, 1 << 16 | REPRESENTATION(kTagged | kUntagged)) \ | |
170 \ | |
171 V(Oddball, kBoolean | kNull | kUndefined) \ | |
172 V(Signed32, kSignedSmall | kOtherSigned32) \ | |
173 V(Number, kSigned32 | kUnsigned32 | kFloat) \ | |
174 V(String, kInternalizedString | kOtherString) \ | |
175 V(UniqueName, kSymbol | kInternalizedString) \ | |
176 V(Name, kSymbol | kString) \ | |
177 V(NumberOrString, kNumber | kString) \ | |
178 V(DetectableObject, kArray | kFunction | kRegExp | kOtherObject) \ | |
179 V(DetectableReceiver, kDetectableObject | kProxy) \ | |
180 V(Detectable, kDetectableReceiver | kNumber | kName) \ | |
181 V(Object, kDetectableObject | kUndetectable) \ | |
182 V(Receiver, kObject | kProxy) \ | |
183 V(NonNumber, kOddball | kName | kReceiver | kInternal) \ | |
184 V(Any, kNumber | kNonNumber) | |
185 | |
186 #define BITSET_TYPE_LIST(V) \ | |
187 MASK_BITSET_TYPE_LIST(V) \ | |
188 REPRESENTATION_BITSET_TYPE_LIST(V) \ | |
189 SEMANTIC_BITSET_TYPE_LIST(V) | |
132 | 190 |
133 | 191 |
134 // struct Config { | 192 // struct Config { |
135 // typedef Base; | 193 // typedef Base; |
136 // typedef Unioned; | 194 // typedef Unioned; |
137 // typedef Region; | 195 // typedef Region; |
138 // template<class> struct Handle { typedef type; } // No template typedefs... | 196 // template<class> struct Handle { typedef type; } // No template typedefs... |
139 // static Handle<Type>::type handle(Type* type); // !is_bitset(type) | 197 // static Handle<Type>::type handle(Type* type); // !is_bitset(type) |
140 // static bool is_bitset(Type*); | 198 // static bool is_bitset(Type*); |
141 // static bool is_class(Type*); | 199 // static bool is_class(Type*); |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
241 TypeImpl* t = static_cast<TypeImpl*>(object); | 299 TypeImpl* t = static_cast<TypeImpl*>(object); |
242 ASSERT(t->IsBitset() || t->IsClass() || t->IsConstant() || t->IsUnion()); | 300 ASSERT(t->IsBitset() || t->IsClass() || t->IsConstant() || t->IsUnion()); |
243 return t; | 301 return t; |
244 } | 302 } |
245 | 303 |
246 template<class OtherTypeImpl> | 304 template<class OtherTypeImpl> |
247 static TypeHandle Convert( | 305 static TypeHandle Convert( |
248 typename OtherTypeImpl::TypeHandle type, Region* region); | 306 typename OtherTypeImpl::TypeHandle type, Region* region); |
249 | 307 |
250 #ifdef OBJECT_PRINT | 308 #ifdef OBJECT_PRINT |
251 void TypePrint(); | 309 enum PrintDimension { BOTH_DIMS, SEMANTIC_DIM, REPRESENTATION_DIM }; |
252 void TypePrint(FILE* out); | 310 void TypePrint(PrintDimension = BOTH_DIMS); |
311 void TypePrint(FILE* out, PrintDimension = BOTH_DIMS); | |
253 #endif | 312 #endif |
254 | 313 |
255 private: | 314 private: |
256 template<class> friend class Iterator; | 315 template<class> friend class Iterator; |
257 template<class> friend class TypeImpl; | 316 template<class> friend class TypeImpl; |
258 | 317 |
259 // A union is a fixed array containing types. Invariants: | 318 // A union is a fixed array containing types. Invariants: |
260 // - its length is at least 2 | 319 // - its length is at least 2 |
261 // - at most one field is a bitset, and it must go into index 0 | 320 // - at most one field is a bitset, and it must go into index 0 |
262 // - no field is a union | 321 // - no field is a union |
(...skipping 16 matching lines...) Expand all Loading... | |
279 | 338 |
280 static int UnionLength(UnionedHandle unioned) { | 339 static int UnionLength(UnionedHandle unioned) { |
281 return Config::union_length(unioned); | 340 return Config::union_length(unioned); |
282 } | 341 } |
283 static TypeHandle UnionGet(UnionedHandle unioned, int i) { | 342 static TypeHandle UnionGet(UnionedHandle unioned, int i) { |
284 return Config::union_get(unioned, i); | 343 return Config::union_get(unioned, i); |
285 } | 344 } |
286 | 345 |
287 bool SlowIs(TypeImpl* that); | 346 bool SlowIs(TypeImpl* that); |
288 | 347 |
348 static bool IsInhabited(int bitset) { | |
349 return (bitset & kRepresentation) && (bitset & kSemantic); | |
350 } | |
351 | |
289 int LubBitset(); // least upper bound that's a bitset | 352 int LubBitset(); // least upper bound that's a bitset |
290 int GlbBitset(); // greatest lower bound that's a bitset | 353 int GlbBitset(); // greatest lower bound that's a bitset |
291 | 354 |
292 static int LubBitset(i::Object* value); | 355 static int LubBitset(i::Object* value); |
293 static int LubBitset(i::Map* map); | 356 static int LubBitset(i::Map* map); |
294 | 357 |
295 bool InUnion(UnionedHandle unioned, int current_size); | 358 bool InUnion(UnionedHandle unioned, int current_size); |
296 static int ExtendUnion( | 359 static int ExtendUnion( |
297 UnionedHandle unioned, TypeHandle t, int current_size); | 360 UnionedHandle unioned, TypeHandle t, int current_size); |
298 static int ExtendIntersection( | 361 static int ExtendIntersection( |
299 UnionedHandle unioned, TypeHandle t, TypeHandle other, int current_size); | 362 UnionedHandle unioned, TypeHandle t, TypeHandle other, int current_size); |
300 | 363 |
301 #ifdef OBJECT_PRINT | 364 #ifdef OBJECT_PRINT |
302 static const char* bitset_name(int bitset); | 365 static const char* bitset_name(int bitset); |
366 static void BitsetTypePrint(FILE* out, int bitset); | |
303 #endif | 367 #endif |
304 }; | 368 }; |
305 | 369 |
306 | 370 |
307 // Zone-allocated types are either (odd) integers to represent bitsets, or | 371 // Zone-allocated types are either (odd) integers to represent bitsets, or |
308 // (even) pointers to zone lists for everything else. The first slot of every | 372 // (even) pointers to zone lists for everything else. The first slot of every |
309 // list is an explicit tag value to distinguish representation. | 373 // list is an explicit tag value to distinguish representation. |
310 struct ZoneTypeConfig { | 374 struct ZoneTypeConfig { |
311 private: | 375 private: |
312 typedef i::ZoneList<void*> Tagged; | 376 typedef i::ZoneList<void*> Tagged; |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
565 return that.lower->Is(this->lower) && this->upper->Is(that.upper); | 629 return that.lower->Is(this->lower) && this->upper->Is(that.upper); |
566 } | 630 } |
567 }; | 631 }; |
568 | 632 |
569 typedef BoundsImpl<ZoneTypeConfig> Bounds; | 633 typedef BoundsImpl<ZoneTypeConfig> Bounds; |
570 | 634 |
571 | 635 |
572 } } // namespace v8::internal | 636 } } // namespace v8::internal |
573 | 637 |
574 #endif // V8_TYPES_H_ | 638 #endif // V8_TYPES_H_ |
OLD | NEW |