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

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: Use smi MSB 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') | no next file with comments »
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
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
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
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
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_
OLDNEW
« no previous file with comments | « src/ic.cc ('k') | src/types.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698