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

Side by Side Diff: src/types.h

Issue 176843006: Introduce representation types (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 9 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 | « src/ic.cc ('k') | 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 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
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
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
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_
OLDNEW
« no previous file with comments | « src/ic.cc ('k') | src/types.cc » ('j') | src/types.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698