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 | 60 // Allocated = Receiver \/ Number \/ Name |
58 // Detectable = Allocated - Undetectable | 61 // Detectable = Allocated - Undetectable |
59 // Undetectable < Object | 62 // Undetectable < Object |
60 // Receiver = Object \/ Proxy | 63 // Receiver = Object \/ Proxy |
61 // Array < Object | 64 // Array < Object |
62 // Function < Object | 65 // Function < Object |
63 // RegExp < Object | 66 // RegExp < Object |
64 // | 67 // |
65 // Class(map) < T iff instance_type(map) < T | 68 // Class(map) < T iff instance_type(map) < T |
66 // Constant(x) < T iff instance_type(map(x)) < T | 69 // Constant(x) < T iff instance_type(map(x)) < T |
67 // | 70 // |
68 // Note that Constant(x) < Class(map(x)) does _not_ hold, since x's map can | 71 // Note that Constant(x) < Class(map(x)) does _not_ hold, since x's map can |
69 // change! (Its instance type cannot, however.) | 72 // change! (Its instance type cannot, however.) |
70 // TODO(rossberg): the latter is not currently true for proxies, because of fix, | 73 // TODO(rossberg): the latter is not currently true for proxies, because of fix, |
71 // but will hold once we implement direct proxies. | 74 // but will hold once we implement direct proxies. |
72 // | 75 // |
76 // For the representation axis, the following holds: | |
77 // | |
78 // None <= R | |
79 // R <= Representation | |
80 // | |
81 // UntaggedInt <= UntaggedInt8 \/ UntaggedInt16 \/ UntaggedInt32) | |
82 // UntaggedFloat <= UntaggedFloat32 \/ UntaggedFloat64 | |
83 // UntaggedNumber <= UntaggedInt \/ UntaggedFloat | |
84 // Untagged <= UntaggedNumber \/ UntaggedPtr | |
85 // Tagged <= TaggedInt \/ TaggedPtr | |
86 // | |
87 // Subtyping relates the two dimensions, for example: | |
88 // | |
89 // Number <= Tagged \/ UntaggedNumber | |
90 // Object <= TaggedPtr \/ UntaggedPtr | |
91 // | |
92 // Representations can be narrowed for a given semantic type using intersection: | |
93 // | |
94 // SignedSmall /\ TaggedInt (a 'smi') | |
95 // Number /\ TaggedPtr (a heap number) | |
96 // | |
73 // There are two main functions for testing types: | 97 // There are two main functions for testing types: |
74 // | 98 // |
75 // T1->Is(T2) -- tests whether T1 is included in T2 (i.e., T1 <= T2) | 99 // 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) | 100 // T1->Maybe(T2) -- tests whether T1 and T2 overlap (i.e., T1 /\ T2 =/= 0) |
77 // | 101 // |
78 // Typically, the former is to be used to select representations (e.g., via | 102 // 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 | 103 // T->Is(SignedSmall())), and the to check whether a specific case needs |
Michael Starzinger
2014/03/04 11:59:58
nit: Seems to be a "latter" missing.
rossberg
2014/03/04 13:53:11
Done.
| |
80 // (e.g., via T->Maybe(Number())). | 104 // handling (e.g., via T->Maybe(Number())). |
81 // | 105 // |
82 // There is no functionality to discover whether a type is a leaf in the | 106 // 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 | 107 // lattice. That is intentional. It should always be possible to refine the |
84 // lattice (e.g., splitting up number types further) without invalidating any | 108 // lattice (e.g., splitting up number types further) without invalidating any |
85 // existing assumptions or tests. | 109 // existing assumptions or tests. |
86 // | |
87 // Consequently, do not use pointer equality for type tests, always use Is! | 110 // Consequently, do not use pointer equality for type tests, always use Is! |
88 // | 111 // |
89 // Internally, all 'primitive' types, and their unions, are represented as | 112 // Internally, all 'primitive' types, and their unions, are represented as |
90 // bitsets via smis. Class is a heap pointer to the respective map. Only | 113 // 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. | 114 // unions containing Class'es or Constant's, currently require allocation. |
92 // Note that the bitset representation is closed under both Union and Intersect. | 115 // Note that the bitset representation is closed under both Union and Intersect. |
93 // | 116 // |
94 // The type representation is heap-allocated, so cannot (currently) be used in | 117 // There are two type representations, using different allocation: |
95 // a concurrent compilation context. | 118 // |
119 // - class Type (zone-allocated, for compiler and concurrent compilation) | |
120 // - class HeapType (heap-allocated, for persistent types) | |
121 // | |
122 // Both provide the same API, and the Convert method can be used to interconvert | |
123 // them. | |
96 | 124 |
97 | 125 |
98 #define BITSET_TYPE_LIST(V) \ | 126 #define RAW_REPRESENTATION_BITSET_TYPE_LIST(V) /* internal */ \ |
99 V(None, 0) \ | 127 V(RUntaggedInt8, 1 << 29) \ |
100 V(Null, 1 << 0) \ | 128 V(RUntaggedInt16, 1 << 28) \ |
101 V(Undefined, 1 << 1) \ | 129 V(RUntaggedInt32, 1 << 27) \ |
102 V(Boolean, 1 << 2) \ | 130 V(RUntaggedFloat32, 1 << 26) \ |
103 V(Smi, 1 << 3) \ | 131 V(RUntaggedFloat64, 1 << 25) \ |
104 V(OtherSigned32, 1 << 4) \ | 132 V(RUntaggedPtr, 1 << 24) \ |
105 V(Unsigned32, 1 << 5) \ | 133 V(RTaggedInt, 1 << 23) \ |
106 V(Double, 1 << 6) \ | 134 V(RTaggedPtr, 1 << 22) \ |
107 V(Symbol, 1 << 7) \ | |
108 V(InternalizedString, 1 << 8) \ | |
109 V(OtherString, 1 << 9) \ | |
110 V(Undetectable, 1 << 10) \ | |
111 V(Array, 1 << 11) \ | |
112 V(Function, 1 << 12) \ | |
113 V(RegExp, 1 << 13) \ | |
114 V(OtherObject, 1 << 14) \ | |
115 V(Proxy, 1 << 15) \ | |
116 V(Internal, 1 << 16) \ | |
117 \ | 135 \ |
118 V(Oddball, kBoolean | kNull | kUndefined) \ | 136 V(RUntaggedInt, kRUntaggedInt8 | kRUntaggedInt16 | kRUntaggedInt32) \ |
119 V(Signed32, kSmi | kOtherSigned32) \ | 137 V(RUntaggedFloat, kRUntaggedFloat32 | kRUntaggedFloat64) \ |
120 V(Number, kSigned32 | kUnsigned32 | kDouble) \ | 138 V(RUntaggedNumber, kRUntaggedInt | kRUntaggedFloat) \ |
121 V(String, kInternalizedString | kOtherString) \ | 139 V(RUntagged, kRUntaggedNumber | kRUntaggedPtr) \ |
122 V(UniqueName, kSymbol | kInternalizedString) \ | 140 V(RTagged, kRTaggedInt | kRTaggedPtr) |
123 V(Name, kSymbol | kString) \ | 141 |
124 V(NumberOrString, kNumber | kString) \ | 142 #define SEMANTIC_BITSET_TYPE_LIST(V) \ |
125 V(Object, kUndetectable | kArray | kFunction | \ | 143 V(None, 0) \ |
126 kRegExp | kOtherObject) \ | 144 V(Null, 1 << 0 | kRTaggedPtr | kRUntaggedPtr) \ |
127 V(Receiver, kObject | kProxy) \ | 145 V(Undefined, 1 << 1 | kRTaggedPtr | kRUntaggedPtr) \ |
128 V(Allocated, kDouble | kName | kReceiver) \ | 146 V(Boolean, 1 << 2 | kRTaggedPtr | kRUntaggedPtr) \ |
129 V(Any, kOddball | kNumber | kAllocated | kInternal) \ | 147 V(SignedSmall, 1 << 3 | kRTagged | kRUntaggedNumber) \ |
130 V(NonNumber, kAny - kNumber) \ | 148 V(OtherSigned32, 1 << 4 | kRTagged | kRUntaggedNumber) \ |
131 V(Detectable, kAllocated - kUndetectable) | 149 V(Unsigned32, 1 << 5 | kRTagged | kRUntaggedNumber) \ |
150 V(Float, 1 << 6 | kRTagged | kRUntaggedNumber) \ | |
151 V(Symbol, 1 << 7 | kRTaggedPtr | kRUntaggedPtr) \ | |
152 V(InternalizedString, 1 << 8 | kRTaggedPtr | kRUntaggedPtr) \ | |
153 V(OtherString, 1 << 9 | kRTaggedPtr | kRUntaggedPtr) \ | |
154 V(Undetectable, 1 << 10 | kRTaggedPtr | kRUntaggedPtr) \ | |
155 V(Array, 1 << 11 | kRTaggedPtr | kRUntaggedPtr) \ | |
156 V(Function, 1 << 12 | kRTaggedPtr | kRUntaggedPtr) \ | |
157 V(RegExp, 1 << 13 | kRTaggedPtr | kRUntaggedPtr) \ | |
158 V(OtherObject, 1 << 14 | kRTaggedPtr | kRUntaggedPtr) \ | |
159 V(Proxy, 1 << 15 | kRTaggedPtr | kRUntaggedPtr) \ | |
160 V(Internal, 1 << 16 | kRTagged | kRUntagged) \ | |
161 \ | |
162 V(Oddball, kBoolean | kNull | kUndefined) \ | |
163 V(Signed32, kSignedSmall | kOtherSigned32) \ | |
164 V(Number, kSigned32 | kUnsigned32 | kFloat) \ | |
165 V(String, kInternalizedString | kOtherString) \ | |
166 V(UniqueName, kSymbol | kInternalizedString) \ | |
167 V(Name, kSymbol | kString) \ | |
168 V(NumberOrString, kNumber | kString) \ | |
169 V(DetectableObject, kArray | kFunction | kRegExp | kOtherObject) \ | |
170 V(Object, kDetectableObject | kUndetectable) \ | |
171 V(Receiver, kObject | kProxy) \ | |
172 V(Allocated, kReceiver | kFloat | kName) \ | |
Michael Starzinger
2014/03/04 11:59:58
Why kFloat here?
rossberg
2014/03/04 13:53:11
Good question. I removed this thing entirely, sinc
| |
173 V(DetectableReceiver, kDetectableObject | kProxy) \ | |
174 V(Detectable, kDetectableReceiver | kFloat | kName) \ | |
Michael Starzinger
2014/03/04 11:59:58
Why kFloat here?
rossberg
2014/03/04 13:53:11
Changed to Number.
| |
175 V(NonNumber, kOddball | kAllocated | kInternal) \ | |
Michael Starzinger
2014/03/04 11:59:58
This way kNonNumber contains kFloat, this seems wr
rossberg
2014/03/04 13:53:11
Done.
| |
176 V(Any, kNumber | kNonNumber) | |
177 | |
178 #define MASK_BITSET_TYPE_LIST(V) \ | |
179 V(Representation, kRTagged | kRUntagged) \ | |
180 V(Semantic, kAny & ~kRepresentation) | |
181 | |
182 #define REPRESENTATION_BITSET_TYPE_LIST(V) \ | |
183 V(UntaggedInt8, kSemantic | kRUntaggedInt8) \ | |
184 V(UntaggedInt16, kSemantic | kRUntaggedInt16) \ | |
185 V(UntaggedInt32, kSemantic | kRUntaggedInt32) \ | |
186 V(UntaggedFloat32, kSemantic | kRUntaggedFloat32) \ | |
187 V(UntaggedFloat64, kSemantic | kRUntaggedFloat64) \ | |
188 V(UntaggedPtr, kSemantic | kRUntaggedPtr) \ | |
189 V(TaggedInt, kSemantic | kRTaggedInt) \ | |
190 V(TaggedPtr, kSemantic | kRTaggedPtr) \ | |
191 \ | |
192 V(UntaggedInt, kSemantic | kRUntaggedInt) \ | |
193 V(UntaggedFloat, kSemantic | kRUntaggedFloat) \ | |
194 V(UntaggedNumber, kSemantic | kRUntaggedNumber) \ | |
195 V(Untagged, kSemantic | kRUntagged) \ | |
196 V(Tagged, kSemantic | kRTagged) | |
197 | |
198 #define BITSET_TYPE_LIST(V) \ | |
199 SEMANTIC_BITSET_TYPE_LIST(V) \ | |
200 MASK_BITSET_TYPE_LIST(V) \ | |
201 REPRESENTATION_BITSET_TYPE_LIST(V) | |
132 | 202 |
133 | 203 |
134 // struct Config { | 204 // struct Config { |
135 // typedef Base; | 205 // typedef Base; |
136 // typedef Unioned; | 206 // typedef Unioned; |
137 // typedef Region; | 207 // typedef Region; |
138 // template<class> struct Handle { typedef type; } // No template typedefs... | 208 // template<class> struct Handle { typedef type; } // No template typedefs... |
139 // static Handle<Type>::type handle(Type* type); // !is_bitset(type) | 209 // static Handle<Type>::type handle(Type* type); // !is_bitset(type) |
140 // static bool is_bitset(Type*); | 210 // static bool is_bitset(Type*); |
141 // static bool is_class(Type*); | 211 // 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); | 311 TypeImpl* t = static_cast<TypeImpl*>(object); |
242 ASSERT(t->IsBitset() || t->IsClass() || t->IsConstant() || t->IsUnion()); | 312 ASSERT(t->IsBitset() || t->IsClass() || t->IsConstant() || t->IsUnion()); |
243 return t; | 313 return t; |
244 } | 314 } |
245 | 315 |
246 template<class OtherTypeImpl> | 316 template<class OtherTypeImpl> |
247 static TypeHandle Convert( | 317 static TypeHandle Convert( |
248 typename OtherTypeImpl::TypeHandle type, Region* region); | 318 typename OtherTypeImpl::TypeHandle type, Region* region); |
249 | 319 |
250 #ifdef OBJECT_PRINT | 320 #ifdef OBJECT_PRINT |
251 void TypePrint(); | 321 enum PrintDim { BOTH_DIMS, SEMANTIC_DIM, REPRESENTATION_DIM }; |
Michael Starzinger
2014/03/04 11:59:58
nit: Can we write out "PrintDimension" at least fo
rossberg
2014/03/04 13:53:11
Done.
| |
252 void TypePrint(FILE* out); | 322 void TypePrint(PrintDim = BOTH_DIMS); |
323 void TypePrint(FILE* out, PrintDim = BOTH_DIMS); | |
253 #endif | 324 #endif |
254 | 325 |
255 private: | 326 private: |
256 template<class> friend class Iterator; | 327 template<class> friend class Iterator; |
257 template<class> friend class TypeImpl; | 328 template<class> friend class TypeImpl; |
258 | 329 |
259 // A union is a fixed array containing types. Invariants: | 330 // A union is a fixed array containing types. Invariants: |
260 // - its length is at least 2 | 331 // - its length is at least 2 |
261 // - at most one field is a bitset, and it must go into index 0 | 332 // - at most one field is a bitset, and it must go into index 0 |
262 // - no field is a union | 333 // - no field is a union |
263 typedef typename Config::Unioned Unioned; | 334 typedef typename Config::Unioned Unioned; |
264 typedef typename Config::template Handle<Unioned>::type UnionedHandle; | 335 typedef typename Config::template Handle<Unioned>::type UnionedHandle; |
265 | 336 |
266 enum { | 337 enum { |
267 #define DECLARE_TYPE(type, value) k##type = (value), | 338 #define DECLARE_TYPE(type, value) k##type = (value), |
339 RAW_REPRESENTATION_BITSET_TYPE_LIST(DECLARE_TYPE) | |
268 BITSET_TYPE_LIST(DECLARE_TYPE) | 340 BITSET_TYPE_LIST(DECLARE_TYPE) |
269 #undef DECLARE_TYPE | 341 #undef DECLARE_TYPE |
270 kUnusedEOL = 0 | 342 kUnusedEOL = 0 |
271 }; | 343 }; |
272 | 344 |
273 bool IsNone() { return this == None(); } | 345 bool IsNone() { return this == None(); } |
274 bool IsAny() { return this == Any(); } | 346 bool IsAny() { return this == Any(); } |
275 bool IsBitset() { return Config::is_bitset(this); } | 347 bool IsBitset() { return Config::is_bitset(this); } |
276 bool IsUnion() { return Config::is_union(this); } | 348 bool IsUnion() { return Config::is_union(this); } |
277 int AsBitset() { return Config::as_bitset(this); } | 349 int AsBitset() { return Config::as_bitset(this); } |
278 UnionedHandle AsUnion() { return Config::as_union(this); } | 350 UnionedHandle AsUnion() { return Config::as_union(this); } |
279 | 351 |
280 static int UnionLength(UnionedHandle unioned) { | 352 static int UnionLength(UnionedHandle unioned) { |
281 return Config::union_length(unioned); | 353 return Config::union_length(unioned); |
282 } | 354 } |
283 static TypeHandle UnionGet(UnionedHandle unioned, int i) { | 355 static TypeHandle UnionGet(UnionedHandle unioned, int i) { |
284 return Config::union_get(unioned, i); | 356 return Config::union_get(unioned, i); |
285 } | 357 } |
286 | 358 |
287 bool SlowIs(TypeImpl* that); | 359 bool SlowIs(TypeImpl* that); |
288 | 360 |
361 static bool IsInhabited(int bitset) { | |
362 return (bitset & kRepresentation) && (bitset & kSemantic); | |
363 } | |
364 | |
289 int LubBitset(); // least upper bound that's a bitset | 365 int LubBitset(); // least upper bound that's a bitset |
290 int GlbBitset(); // greatest lower bound that's a bitset | 366 int GlbBitset(); // greatest lower bound that's a bitset |
291 | 367 |
292 static int LubBitset(i::Object* value); | 368 static int LubBitset(i::Object* value); |
293 static int LubBitset(i::Map* map); | 369 static int LubBitset(i::Map* map); |
294 | 370 |
295 bool InUnion(UnionedHandle unioned, int current_size); | 371 bool InUnion(UnionedHandle unioned, int current_size); |
296 static int ExtendUnion( | 372 static int ExtendUnion( |
297 UnionedHandle unioned, TypeHandle t, int current_size); | 373 UnionedHandle unioned, TypeHandle t, int current_size); |
298 static int ExtendIntersection( | 374 static int ExtendIntersection( |
299 UnionedHandle unioned, TypeHandle t, TypeHandle other, int current_size); | 375 UnionedHandle unioned, TypeHandle t, TypeHandle other, int current_size); |
300 | 376 |
301 #ifdef OBJECT_PRINT | 377 #ifdef OBJECT_PRINT |
302 static const char* bitset_name(int bitset); | 378 static const char* bitset_name(int bitset); |
379 static void BitsetTypePrint(FILE* out, int bitset); | |
303 #endif | 380 #endif |
304 }; | 381 }; |
305 | 382 |
306 | 383 |
307 // Zone-allocated types are either (odd) integers to represent bitsets, or | 384 // 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 | 385 // (even) pointers to zone lists for everything else. The first slot of every |
309 // list is an explicit tag value to distinguish representation. | 386 // list is an explicit tag value to distinguish representation. |
310 struct ZoneTypeConfig { | 387 struct ZoneTypeConfig { |
311 private: | 388 private: |
312 typedef i::ZoneList<void*> Tagged; | 389 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); | 642 return that.lower->Is(this->lower) && this->upper->Is(that.upper); |
566 } | 643 } |
567 }; | 644 }; |
568 | 645 |
569 typedef BoundsImpl<ZoneTypeConfig> Bounds; | 646 typedef BoundsImpl<ZoneTypeConfig> Bounds; |
570 | 647 |
571 | 648 |
572 } } // namespace v8::internal | 649 } } // namespace v8::internal |
573 | 650 |
574 #endif // V8_TYPES_H_ | 651 #endif // V8_TYPES_H_ |
OLD | NEW |