Chromium Code Reviews| 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 |