Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef V8_TYPES_H_ | 5 #ifndef V8_TYPES_H_ |
| 6 #define V8_TYPES_H_ | 6 #define V8_TYPES_H_ |
| 7 | 7 |
| 8 #include "src/conversions.h" | |
| 8 #include "src/factory.h" | 9 #include "src/factory.h" |
| 9 #include "src/handles.h" | 10 #include "src/handles.h" |
| 10 #include "src/ostreams.h" | 11 #include "src/ostreams.h" |
| 11 | 12 |
| 12 namespace v8 { | 13 namespace v8 { |
| 13 namespace internal { | 14 namespace internal { |
| 14 | 15 |
| 15 // SUMMARY | 16 // SUMMARY |
| 16 // | 17 // |
| 17 // A simple type system for compiler-internal use. It is based entirely on | 18 // A simple type system for compiler-internal use. It is based entirely on |
| 18 // union types, and all subtyping hence amounts to set inclusion. Besides the | 19 // union types, and all subtyping hence amounts to set inclusion. Besides the |
| 19 // obvious primitive types and some predefined unions, the type language also | 20 // obvious primitive types and some predefined unions, the type language also |
| 20 // can express class types (a.k.a. specific maps) and singleton types (i.e., | 21 // can express class types (a.k.a. specific maps) and singleton types (i.e., |
| 21 // concrete constants). | 22 // concrete constants). |
| 22 // | 23 // |
| 23 // Types consist of two dimensions: semantic (value range) and representation. | 24 // Types consist of two dimensions: semantic (value range) and representation. |
| 24 // Both are related through subtyping. | 25 // Both are related through subtyping. |
| 25 // | 26 // |
| 27 // | |
| 26 // SEMANTIC DIMENSION | 28 // SEMANTIC DIMENSION |
| 27 // | 29 // |
| 28 // The following equations and inequations hold for the semantic axis: | 30 // The following equations and inequations hold for the semantic axis: |
| 29 // | 31 // |
| 30 // None <= T | 32 // None <= T |
| 31 // T <= Any | 33 // T <= Any |
| 32 // | 34 // |
| 33 // Number = Signed32 \/ Unsigned32 \/ Double | 35 // Number = Signed32 \/ Unsigned32 \/ Double |
| 34 // Smi <= Signed32 | 36 // Smi <= Signed32 |
| 35 // Name = String \/ Symbol | 37 // Name = String \/ Symbol |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 54 // There is no subtyping relation between Array, Function, or Context types | 56 // There is no subtyping relation between Array, Function, or Context types |
| 55 // and respective Constant types, since these types cannot be reconstructed | 57 // and respective Constant types, since these types cannot be reconstructed |
| 56 // for arbitrary heap values. | 58 // for arbitrary heap values. |
| 57 // Note also that Constant(x) < Class(map(x)) does _not_ hold, since x's map can | 59 // Note also that Constant(x) < Class(map(x)) does _not_ hold, since x's map can |
| 58 // change! (Its instance type cannot, however.) | 60 // change! (Its instance type cannot, however.) |
| 59 // TODO(rossberg): the latter is not currently true for proxies, because of fix, | 61 // TODO(rossberg): the latter is not currently true for proxies, because of fix, |
| 60 // but will hold once we implement direct proxies. | 62 // but will hold once we implement direct proxies. |
| 61 // However, we also define a 'temporal' variant of the subtyping relation that | 63 // However, we also define a 'temporal' variant of the subtyping relation that |
| 62 // considers the _current_ state only, i.e., Constant(x) <_now Class(map(x)). | 64 // considers the _current_ state only, i.e., Constant(x) <_now Class(map(x)). |
| 63 // | 65 // |
| 66 // | |
| 64 // REPRESENTATIONAL DIMENSION | 67 // REPRESENTATIONAL DIMENSION |
| 65 // | 68 // |
| 66 // For the representation axis, the following holds: | 69 // For the representation axis, the following holds: |
| 67 // | 70 // |
| 68 // None <= R | 71 // None <= R |
| 69 // R <= Any | 72 // R <= Any |
| 70 // | 73 // |
| 71 // UntaggedInt = UntaggedInt1 \/ UntaggedInt8 \/ | 74 // UntaggedInt = UntaggedInt1 \/ UntaggedInt8 \/ |
| 72 // UntaggedInt16 \/ UntaggedInt32 | 75 // UntaggedInt16 \/ UntaggedInt32 |
| 73 // UntaggedFloat = UntaggedFloat32 \/ UntaggedFloat64 | 76 // UntaggedFloat = UntaggedFloat32 \/ UntaggedFloat64 |
| 74 // UntaggedNumber = UntaggedInt \/ UntaggedFloat | 77 // UntaggedNumber = UntaggedInt \/ UntaggedFloat |
| 75 // Untagged = UntaggedNumber \/ UntaggedPtr | 78 // Untagged = UntaggedNumber \/ UntaggedPtr |
| 76 // Tagged = TaggedInt \/ TaggedPtr | 79 // Tagged = TaggedInt \/ TaggedPtr |
| 77 // | 80 // |
| 78 // Subtyping relates the two dimensions, for example: | 81 // Subtyping relates the two dimensions, for example: |
| 79 // | 82 // |
| 80 // Number <= Tagged \/ UntaggedNumber | 83 // Number <= Tagged \/ UntaggedNumber |
| 81 // Object <= TaggedPtr \/ UntaggedPtr | 84 // Object <= TaggedPtr \/ UntaggedPtr |
| 82 // | 85 // |
| 83 // That holds because the semantic type constructors defined by the API create | 86 // That holds because the semantic type constructors defined by the API create |
| 84 // types that allow for all possible representations, and dually, the ones for | 87 // types that allow for all possible representations, and dually, the ones for |
| 85 // representation types initially include all semantic ranges. Representations | 88 // representation types initially include all semantic ranges. Representations |
| 86 // can then e.g. be narrowed for a given semantic type using intersection: | 89 // can then e.g. be narrowed for a given semantic type using intersection: |
| 87 // | 90 // |
| 88 // SignedSmall /\ TaggedInt (a 'smi') | 91 // SignedSmall /\ TaggedInt (a 'smi') |
| 89 // Number /\ TaggedPtr (a heap number) | 92 // Number /\ TaggedPtr (a heap number) |
| 90 // | 93 // |
| 94 // | |
| 95 // RANGE TYPES | |
| 96 // | |
| 97 // A range type represents a continuous integer interval by its minimum and | |
| 98 // maximum value. Either value might be an infinity. | |
| 99 // | |
| 100 // Constant(v) is considered a subtype of Range(x..y) if v happens to be an | |
| 101 // integer between x and y. | |
| 102 // | |
| 103 // | |
| 91 // PREDICATES | 104 // PREDICATES |
| 92 // | 105 // |
| 93 // There are two main functions for testing types: | 106 // There are two main functions for testing types: |
| 94 // | 107 // |
| 95 // T1->Is(T2) -- tests whether T1 is included in T2 (i.e., T1 <= T2) | 108 // T1->Is(T2) -- tests whether T1 is included in T2 (i.e., T1 <= T2) |
| 96 // T1->Maybe(T2) -- tests whether T1 and T2 overlap (i.e., T1 /\ T2 =/= 0) | 109 // T1->Maybe(T2) -- tests whether T1 and T2 overlap (i.e., T1 /\ T2 =/= 0) |
| 97 // | 110 // |
| 98 // Typically, the former is to be used to select representations (e.g., via | 111 // Typically, the former is to be used to select representations (e.g., via |
| 99 // T->Is(SignedSmall())), and the latter to check whether a specific case needs | 112 // T->Is(SignedSmall())), and the latter to check whether a specific case needs |
| 100 // handling (e.g., via T->Maybe(Number())). | 113 // handling (e.g., via T->Maybe(Number())). |
| 101 // | 114 // |
| 102 // There is no functionality to discover whether a type is a leaf in the | 115 // There is no functionality to discover whether a type is a leaf in the |
| 103 // lattice. That is intentional. It should always be possible to refine the | 116 // lattice. That is intentional. It should always be possible to refine the |
| 104 // lattice (e.g., splitting up number types further) without invalidating any | 117 // lattice (e.g., splitting up number types further) without invalidating any |
| 105 // existing assumptions or tests. | 118 // existing assumptions or tests. |
| 106 // Consequently, do not normally use Equals for type tests, always use Is! | 119 // Consequently, do not normally use Equals for type tests, always use Is! |
| 107 // | 120 // |
| 108 // The NowIs operator implements state-sensitive subtying, as described above. | 121 // The NowIs operator implements state-sensitive subtying, as described above. |
| 109 // Any compilation decision based on such temporary properties requires runtime | 122 // Any compilation decision based on such temporary properties requires runtime |
| 110 // guarding! | 123 // guarding! |
| 111 // | 124 // |
| 125 // | |
| 112 // PROPERTIES | 126 // PROPERTIES |
| 113 // | 127 // |
| 114 // Various formal properties hold for constructors, operators, and predicates | 128 // Various formal properties hold for constructors, operators, and predicates |
| 115 // over types. For example, constructors are injective, subtyping is a complete | 129 // over types. For example, constructors are injective and subtyping is a |
| 116 // partial order, union and intersection satisfy the usual algebraic properties. | 130 // complete partial order. |
| 117 // | 131 // |
| 118 // See test/cctest/test-types.cc for a comprehensive executable specification, | 132 // See test/cctest/test-types.cc for a comprehensive executable specification, |
| 119 // especially with respect to the properties of the more exotic 'temporal' | 133 // especially with respect to the properties of the more exotic 'temporal' |
| 120 // constructors and predicates (those prefixed 'Now'). | 134 // constructors and predicates (those prefixed 'Now'). |
| 121 // | 135 // |
| 136 // | |
| 122 // IMPLEMENTATION | 137 // IMPLEMENTATION |
| 123 // | 138 // |
| 124 // Internally, all 'primitive' types, and their unions, are represented as | 139 // Internally, all 'primitive' types, and their unions, are represented as |
| 125 // bitsets. Class is a heap pointer to the respective map. Only Constant's, or | 140 // bitsets. Class is a heap pointer to the respective map. Only Constant's, or |
| 126 // unions containing Class'es or Constant's, currently require allocation. | 141 // unions containing Class'es or Constant's, currently require allocation. |
| 127 // Note that the bitset representation is closed under both Union and Intersect. | 142 // Note that the bitset representation is closed under both Union and Intersect. |
| 128 // | 143 // |
| 129 // There are two type representations, using different allocation: | 144 // There are two type representations, using different allocation: |
| 130 // | 145 // |
| 131 // - class Type (zone-allocated, for compiler and concurrent compilation) | 146 // - class Type (zone-allocated, for compiler and concurrent compilation) |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 201 V(Primitive, kNumber | kName | kBoolean | kNull | kUndefined) \ | 216 V(Primitive, kNumber | kName | kBoolean | kNull | kUndefined) \ |
| 202 V(DetectableObject, kArray | kFunction | kRegExp | kOtherObject) \ | 217 V(DetectableObject, kArray | kFunction | kRegExp | kOtherObject) \ |
| 203 V(DetectableReceiver, kDetectableObject | kProxy) \ | 218 V(DetectableReceiver, kDetectableObject | kProxy) \ |
| 204 V(Detectable, kDetectableReceiver | kNumber | kName) \ | 219 V(Detectable, kDetectableReceiver | kNumber | kName) \ |
| 205 V(Object, kDetectableObject | kUndetectable) \ | 220 V(Object, kDetectableObject | kUndetectable) \ |
| 206 V(Receiver, kObject | kProxy) \ | 221 V(Receiver, kObject | kProxy) \ |
| 207 V(NonNumber, kBoolean | kName | kNull | kReceiver | \ | 222 V(NonNumber, kBoolean | kName | kNull | kReceiver | \ |
| 208 kUndefined | kInternal) \ | 223 kUndefined | kInternal) \ |
| 209 V(Any, -1) | 224 V(Any, -1) |
| 210 | 225 |
| 226 /* | |
| 227 * The following diagrams show how integers (in the mathematical sense) are | |
| 228 * divided among the different atomic numerical types. | |
| 229 * | |
| 230 * If SmiValuesAre31Bits(): | |
| 231 * | |
| 232 * ON OS32 OSS US OU31 OU32 ON | |
| 233 * ______[_______[_______[_______[_______[_______[_______ | |
| 234 * -2^31 -2^30 0 2^30 2^31 2^32 | |
| 235 * | |
| 236 * Otherwise: | |
| 237 * | |
| 238 * ON OSS US OU32 ON | |
| 239 * ______[_______________[_______________[_______[_______ | |
| 240 * -2^31 0 2^31 2^32 | |
| 241 * | |
| 242 * | |
| 243 * E.g., OtherUnsigned32 (OU32) covers all integers from 2^31 to 2^32-1. | |
| 244 * | |
| 245 */ | |
| 246 | |
| 247 #define PROPER_BITSET_TYPE_LIST(V) \ | |
| 248 REPRESENTATION_BITSET_TYPE_LIST(V) \ | |
| 249 SEMANTIC_BITSET_TYPE_LIST(V) | |
| 250 | |
| 211 #define BITSET_TYPE_LIST(V) \ | 251 #define BITSET_TYPE_LIST(V) \ |
| 212 MASK_BITSET_TYPE_LIST(V) \ | 252 MASK_BITSET_TYPE_LIST(V) \ |
| 213 REPRESENTATION_BITSET_TYPE_LIST(V) \ | 253 PROPER_BITSET_TYPE_LIST(V) |
| 214 SEMANTIC_BITSET_TYPE_LIST(V) | |
| 215 | 254 |
| 216 | 255 |
| 217 // ----------------------------------------------------------------------------- | 256 // ----------------------------------------------------------------------------- |
| 218 // The abstract Type class, parameterized over the low-level representation. | 257 // The abstract Type class, parameterized over the low-level representation. |
| 219 | 258 |
| 220 // struct Config { | 259 // struct Config { |
| 221 // typedef TypeImpl<Config> Type; | 260 // typedef TypeImpl<Config> Type; |
| 222 // typedef Base; | 261 // typedef Base; |
| 223 // typedef Struct; | 262 // typedef Struct; |
| 224 // typedef Region; | 263 // typedef Region; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 272 typedef typename Config::template Handle<UnionType>::type UnionHandle; | 311 typedef typename Config::template Handle<UnionType>::type UnionHandle; |
| 273 typedef typename Config::Region Region; | 312 typedef typename Config::Region Region; |
| 274 | 313 |
| 275 // Constructors. | 314 // Constructors. |
| 276 | 315 |
| 277 #define DEFINE_TYPE_CONSTRUCTOR(type, value) \ | 316 #define DEFINE_TYPE_CONSTRUCTOR(type, value) \ |
| 278 static TypeImpl* type() { return BitsetType::New(BitsetType::k##type); } \ | 317 static TypeImpl* type() { return BitsetType::New(BitsetType::k##type); } \ |
| 279 static TypeHandle type(Region* region) { \ | 318 static TypeHandle type(Region* region) { \ |
| 280 return BitsetType::New(BitsetType::k##type, region); \ | 319 return BitsetType::New(BitsetType::k##type, region); \ |
| 281 } | 320 } |
| 282 BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR) | 321 PROPER_BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR) |
| 283 #undef DEFINE_TYPE_CONSTRUCTOR | 322 #undef DEFINE_TYPE_CONSTRUCTOR |
| 284 | 323 |
| 285 static TypeHandle Class(i::Handle<i::Map> map, Region* region) { | 324 static TypeHandle Class(i::Handle<i::Map> map, Region* region) { |
| 286 return ClassType::New(map, region); | 325 return ClassType::New(map, region); |
| 287 } | 326 } |
| 288 static TypeHandle Constant(i::Handle<i::Object> value, Region* region) { | 327 static TypeHandle Constant(i::Handle<i::Object> value, Region* region) { |
| 289 // TODO(neis): Return RangeType for numerical values. | |
| 290 return ConstantType::New(value, region); | 328 return ConstantType::New(value, region); |
| 291 } | 329 } |
| 292 static TypeHandle Range(double min, double max, Region* region) { | 330 static TypeHandle Range( |
| 331 i::Handle<i::Object> min, i::Handle<i::Object> max, Region* region) { | |
| 293 return RangeType::New(min, max, region); | 332 return RangeType::New(min, max, region); |
| 294 } | 333 } |
| 295 static TypeHandle Context(TypeHandle outer, Region* region) { | 334 static TypeHandle Context(TypeHandle outer, Region* region) { |
| 296 return ContextType::New(outer, region); | 335 return ContextType::New(outer, region); |
| 297 } | 336 } |
| 298 static TypeHandle Array(TypeHandle element, Region* region) { | 337 static TypeHandle Array(TypeHandle element, Region* region) { |
| 299 return ArrayType::New(element, region); | 338 return ArrayType::New(element, region); |
| 300 } | 339 } |
| 301 static FunctionHandle Function( | 340 static FunctionHandle Function( |
| 302 TypeHandle result, TypeHandle receiver, int arity, Region* region) { | 341 TypeHandle result, TypeHandle receiver, int arity, Region* region) { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 350 bool Is(TypeHandle that) { return this->Is(*that); } | 389 bool Is(TypeHandle that) { return this->Is(*that); } |
| 351 | 390 |
| 352 bool Maybe(TypeImpl* that); | 391 bool Maybe(TypeImpl* that); |
| 353 template<class TypeHandle> | 392 template<class TypeHandle> |
| 354 bool Maybe(TypeHandle that) { return this->Maybe(*that); } | 393 bool Maybe(TypeHandle that) { return this->Maybe(*that); } |
| 355 | 394 |
| 356 bool Equals(TypeImpl* that) { return this->Is(that) && that->Is(this); } | 395 bool Equals(TypeImpl* that) { return this->Is(that) && that->Is(this); } |
| 357 template<class TypeHandle> | 396 template<class TypeHandle> |
| 358 bool Equals(TypeHandle that) { return this->Equals(*that); } | 397 bool Equals(TypeHandle that) { return this->Equals(*that); } |
| 359 | 398 |
| 360 // Equivalent to Constant(value)->Is(this), but avoiding allocation. | 399 // Equivalent to Constant(val)->Is(this), but avoiding allocation. |
| 361 bool Contains(i::Object* val); | 400 bool Contains(i::Object* val); |
| 362 bool Contains(i::Handle<i::Object> val) { return this->Contains(*val); } | 401 bool Contains(i::Handle<i::Object> val) { return this->Contains(*val); } |
| 363 | 402 |
| 364 // State-dependent versions of the above that consider subtyping between | 403 // State-dependent versions of the above that consider subtyping between |
| 365 // a constant and its map class. | 404 // a constant and its map class. |
| 366 inline static TypeHandle NowOf(i::Object* value, Region* region); | 405 inline static TypeHandle NowOf(i::Object* value, Region* region); |
| 367 static TypeHandle NowOf(i::Handle<i::Object> value, Region* region) { | 406 static TypeHandle NowOf(i::Handle<i::Object> value, Region* region) { |
| 368 return NowOf(*value, region); | 407 return NowOf(*value, region); |
| 369 } | 408 } |
| 370 bool NowIs(TypeImpl* that); | 409 bool NowIs(TypeImpl* that); |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 397 return Config::is_struct(this, StructuralType::kFunctionTag); | 436 return Config::is_struct(this, StructuralType::kFunctionTag); |
| 398 } | 437 } |
| 399 | 438 |
| 400 ClassType* AsClass() { return ClassType::cast(this); } | 439 ClassType* AsClass() { return ClassType::cast(this); } |
| 401 ConstantType* AsConstant() { return ConstantType::cast(this); } | 440 ConstantType* AsConstant() { return ConstantType::cast(this); } |
| 402 RangeType* AsRange() { return RangeType::cast(this); } | 441 RangeType* AsRange() { return RangeType::cast(this); } |
| 403 ContextType* AsContext() { return ContextType::cast(this); } | 442 ContextType* AsContext() { return ContextType::cast(this); } |
| 404 ArrayType* AsArray() { return ArrayType::cast(this); } | 443 ArrayType* AsArray() { return ArrayType::cast(this); } |
| 405 FunctionType* AsFunction() { return FunctionType::cast(this); } | 444 FunctionType* AsFunction() { return FunctionType::cast(this); } |
| 406 | 445 |
| 446 // Minimum and maximum of a numeric type. | |
| 447 // These functions do not distinguish between -0 and +0. If the type equals | |
| 448 // kNaN, they return NaN; otherwise kNaN is ignored. Only call these | |
| 449 // functions on subtypes of Number. | |
| 450 double Min(); | |
| 451 double Max(); | |
| 452 | |
| 407 int NumClasses(); | 453 int NumClasses(); |
| 408 int NumConstants(); | 454 int NumConstants(); |
| 409 | 455 |
| 410 template<class T> class Iterator; | 456 template<class T> class Iterator; |
| 411 Iterator<i::Map> Classes() { | 457 Iterator<i::Map> Classes() { |
| 412 if (this->IsBitset()) return Iterator<i::Map>(); | 458 if (this->IsBitset()) return Iterator<i::Map>(); |
| 413 return Iterator<i::Map>(Config::handle(this)); | 459 return Iterator<i::Map>(Config::handle(this)); |
| 414 } | 460 } |
| 415 Iterator<i::Object> Constants() { | 461 Iterator<i::Object> Constants() { |
| 416 if (this->IsBitset()) return Iterator<i::Object>(); | 462 if (this->IsBitset()) return Iterator<i::Object>(); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 459 int AsBitset() { | 505 int AsBitset() { |
| 460 DCHECK(this->IsBitset()); | 506 DCHECK(this->IsBitset()); |
| 461 return static_cast<BitsetType*>(this)->Bitset(); | 507 return static_cast<BitsetType*>(this)->Bitset(); |
| 462 } | 508 } |
| 463 UnionType* AsUnion() { return UnionType::cast(this); } | 509 UnionType* AsUnion() { return UnionType::cast(this); } |
| 464 | 510 |
| 465 // Auxiliary functions. | 511 // Auxiliary functions. |
| 466 | 512 |
| 467 int BitsetGlb() { return BitsetType::Glb(this); } | 513 int BitsetGlb() { return BitsetType::Glb(this); } |
| 468 int BitsetLub() { return BitsetType::Lub(this); } | 514 int BitsetLub() { return BitsetType::Lub(this); } |
| 469 int InherentBitsetLub() { return BitsetType::InherentLub(this); } | |
| 470 | 515 |
| 471 bool SlowIs(TypeImpl* that); | 516 bool SlowIs(TypeImpl* that); |
| 472 | 517 |
| 473 TypeHandle Rebound(int bitset, Region* region); | 518 static bool IsInteger(double x) { |
| 474 int BoundBy(TypeImpl* that); | 519 return nearbyint(x) == x && !i::IsMinusZero(x); // Allows for infinities. |
| 475 int IndexInUnion(int bound, UnionHandle unioned, int current_size); | 520 } |
| 476 static int ExtendUnion( | 521 static bool IsInteger(i::Object* x) { |
| 477 UnionHandle unioned, int current_size, TypeHandle t, | 522 return x->IsNumber() && IsInteger(x->Number()); |
| 478 TypeHandle other, bool is_intersect, Region* region); | 523 } |
| 524 | |
| 525 struct Limits { | |
| 526 i::Handle<i::Object> min; | |
| 527 i::Handle<i::Object> max; | |
| 528 Limits(i::Handle<i::Object> min, i::Handle<i::Object> max) : | |
| 529 min(min), max(max) {} | |
| 530 explicit Limits(RangeType* range) : | |
| 531 min(range->Min()), max(range->Max()) {} | |
| 532 }; | |
| 533 | |
| 534 static Limits Intersect(Limits lhs, Limits rhs); | |
| 535 static Limits Union(Limits lhs, Limits rhs); | |
| 536 static bool Overlap(RangeType* lhs, RangeType* rhs); | |
| 537 static bool Contains(RangeType* lhs, RangeType* rhs); | |
| 538 static bool Contains(RangeType* range, i::Object* val); | |
| 539 | |
| 540 RangeType* GetRange(); | |
| 541 static int UpdateRange( | |
| 542 RangeHandle type, UnionHandle result, int size, Region* region); | |
| 543 | |
| 544 bool SimplyEquals(TypeImpl* that); | |
| 545 template<class TypeHandle> | |
| 546 bool SimplyEquals(TypeHandle that) { return this->SimplyEquals(*that); } | |
| 547 | |
| 548 static int AddToUnion( | |
| 549 TypeHandle type, UnionHandle result, int size, Region* region); | |
| 550 static int IntersectAux( | |
| 551 TypeHandle type, TypeHandle other, | |
| 552 UnionHandle result, int size, Region* region); | |
| 553 static TypeHandle NormalizeUnion(UnionHandle unioned, int size); | |
| 479 }; | 554 }; |
| 480 | 555 |
| 481 | 556 |
| 482 // ----------------------------------------------------------------------------- | 557 // ----------------------------------------------------------------------------- |
| 483 // Bitset types (internal). | 558 // Bitset types (internal). |
| 484 | 559 |
| 485 template<class Config> | 560 template<class Config> |
| 486 class TypeImpl<Config>::BitsetType : public TypeImpl<Config> { | 561 class TypeImpl<Config>::BitsetType : public TypeImpl<Config> { |
| 487 protected: | 562 protected: |
| 488 friend class TypeImpl<Config>; | 563 friend class TypeImpl<Config>; |
| 489 | 564 |
| 490 enum { | 565 enum { |
| 491 #define DECLARE_TYPE(type, value) k##type = (value), | 566 #define DECLARE_TYPE(type, value) k##type = (value), |
| 492 BITSET_TYPE_LIST(DECLARE_TYPE) | 567 BITSET_TYPE_LIST(DECLARE_TYPE) |
| 493 #undef DECLARE_TYPE | 568 #undef DECLARE_TYPE |
| 494 kUnusedEOL = 0 | 569 kUnusedEOL = 0 |
| 495 }; | 570 }; |
| 496 | 571 |
| 497 int Bitset() { return Config::as_bitset(this); } | 572 int Bitset() { return Config::as_bitset(this); } |
| 498 | 573 |
| 499 static TypeImpl* New(int bitset) { | 574 static TypeImpl* New(int bitset) { |
| 575 DCHECK(bitset == kNone || IsInhabited(bitset)); | |
| 500 return static_cast<BitsetType*>(Config::from_bitset(bitset)); | 576 return static_cast<BitsetType*>(Config::from_bitset(bitset)); |
| 501 } | 577 } |
| 502 static TypeHandle New(int bitset, Region* region) { | 578 static TypeHandle New(int bitset, Region* region) { |
| 579 DCHECK(bitset == kNone || IsInhabited(bitset)); | |
| 503 return Config::from_bitset(bitset, region); | 580 return Config::from_bitset(bitset, region); |
| 504 } | 581 } |
| 582 // TODO(neis): Eventually allow again for types with empty semantics | |
| 583 // part and modify intersection and possibly subtyping accordingly. | |
| 505 | 584 |
| 506 static bool IsInhabited(int bitset) { | 585 static bool IsInhabited(int bitset) { |
| 507 return (bitset & kRepresentation) && (bitset & kSemantic); | 586 return bitset & kSemantic; |
| 508 } | 587 } |
| 509 | 588 |
| 510 static bool Is(int bitset1, int bitset2) { | 589 static bool Is(int bitset1, int bitset2) { |
| 511 return (bitset1 | bitset2) == bitset2; | 590 return (bitset1 | bitset2) == bitset2; |
| 512 } | 591 } |
| 513 | 592 |
| 593 static double Min(int bitset); | |
| 594 static double Max(int bitset); | |
| 595 | |
| 514 static int Glb(TypeImpl* type); // greatest lower bound that's a bitset | 596 static int Glb(TypeImpl* type); // greatest lower bound that's a bitset |
| 515 static int Lub(TypeImpl* type); // least upper bound that's a bitset | 597 static int Lub(TypeImpl* type); // least upper bound that's a bitset |
| 516 static int Lub(i::Object* value); | 598 static int Lub(i::Object* value); |
| 517 static int Lub(double value); | 599 static int Lub(double value); |
| 518 static int Lub(int32_t value); | 600 static int Lub(int32_t value); |
| 519 static int Lub(uint32_t value); | 601 static int Lub(uint32_t value); |
| 520 static int Lub(i::Map* map); | 602 static int Lub(i::Map* map); |
| 521 static int Lub(double min, double max); | 603 static int Lub(Limits lim); |
| 522 static int InherentLub(TypeImpl* type); | |
| 523 | 604 |
| 524 static const char* Name(int bitset); | 605 static const char* Name(int bitset); |
| 525 static void Print(OStream& os, int bitset); // NOLINT | 606 static void Print(OStream& os, int bitset); // NOLINT |
| 526 using TypeImpl::PrintTo; | 607 #ifdef DEBUG |
| 608 static void Print(int bitset); | |
| 609 #endif | |
| 610 | |
| 611 private: | |
| 612 struct BitsetMin{ | |
| 613 int bitset; | |
| 614 double min; | |
| 615 }; | |
| 616 static const BitsetMin BitsetMins31[]; | |
| 617 static const BitsetMin BitsetMins32[]; | |
| 618 static const BitsetMin* BitsetMins() { | |
| 619 return i::SmiValuesAre31Bits() ? BitsetMins31 : BitsetMins32; | |
| 620 } | |
| 621 static size_t BitsetMinsSize() { | |
| 622 return i::SmiValuesAre31Bits() ? 7 : 5; | |
| 623 /* arraysize(BitsetMins31) : arraysize(BitsetMins32); */ | |
| 624 // Using arraysize here doesn't compile on Windows. | |
| 625 } | |
| 527 }; | 626 }; |
| 528 | 627 |
| 529 | 628 |
| 530 // ----------------------------------------------------------------------------- | 629 // ----------------------------------------------------------------------------- |
| 531 // Superclass for non-bitset types (internal). | 630 // Superclass for non-bitset types (internal). |
| 532 // Contains a tag and a variable number of type or value fields. | 631 // Contains a tag and a variable number of type or value fields. |
| 533 | 632 |
| 534 template<class Config> | 633 template<class Config> |
| 535 class TypeImpl<Config>::StructuralType : public TypeImpl<Config> { | 634 class TypeImpl<Config>::StructuralType : public TypeImpl<Config> { |
| 536 protected: | 635 protected: |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 602 bool Wellformed(); | 701 bool Wellformed(); |
| 603 }; | 702 }; |
| 604 | 703 |
| 605 | 704 |
| 606 // ----------------------------------------------------------------------------- | 705 // ----------------------------------------------------------------------------- |
| 607 // Class types. | 706 // Class types. |
| 608 | 707 |
| 609 template<class Config> | 708 template<class Config> |
| 610 class TypeImpl<Config>::ClassType : public StructuralType { | 709 class TypeImpl<Config>::ClassType : public StructuralType { |
| 611 public: | 710 public: |
| 612 TypeHandle Bound(Region* region) { | 711 int BitsetLub() { |
|
rossberg
2014/09/23 15:20:38
This can't go here like this, as bitsets are an im
neis1
2014/09/24 07:21:38
Oops, forgot about that. I wanted to avoid the "l
| |
| 613 return Config::is_class(this) | 712 return Config::is_class(this) ? |
| 614 ? BitsetType::New(BitsetType::Lub(*Config::as_class(this)), region) | 713 BitsetType::Lub(*Config::as_class(this)) : this->Get(0)->AsBitset(); |
| 615 : this->Get(0); | |
| 616 } | 714 } |
| 617 i::Handle<i::Map> Map() { | 715 i::Handle<i::Map> Map() { |
| 618 return Config::is_class(this) | 716 return Config::is_class(this) ? |
| 619 ? Config::as_class(this) | 717 Config::as_class(this) : this->template GetValue<i::Map>(1); |
| 620 : this->template GetValue<i::Map>(1); | |
| 621 } | |
| 622 | |
| 623 static ClassHandle New( | |
| 624 i::Handle<i::Map> map, TypeHandle bound, Region* region) { | |
| 625 DCHECK(BitsetType::Is(bound->AsBitset(), BitsetType::Lub(*map))); | |
| 626 ClassHandle type = Config::template cast<ClassType>( | |
| 627 StructuralType::New(StructuralType::kClassTag, 2, region)); | |
| 628 type->Set(0, bound); | |
| 629 type->SetValue(1, map); | |
| 630 return type; | |
| 631 } | 718 } |
| 632 | 719 |
| 633 static ClassHandle New(i::Handle<i::Map> map, Region* region) { | 720 static ClassHandle New(i::Handle<i::Map> map, Region* region) { |
| 634 ClassHandle type = | 721 ClassHandle type = |
| 635 Config::template cast<ClassType>(Config::from_class(map, region)); | 722 Config::template cast<ClassType>(Config::from_class(map, region)); |
| 636 if (type->IsClass()) { | 723 if (!type->IsClass()) { |
| 637 return type; | 724 type = Config::template cast<ClassType>( |
| 638 } else { | 725 StructuralType::New(StructuralType::kClassTag, 2, region)); |
| 639 TypeHandle bound = BitsetType::New(BitsetType::Lub(*map), region); | 726 type->Set(0, BitsetType::New(BitsetType::Lub(*map), region)); |
| 640 return New(map, bound, region); | 727 type->SetValue(1, map); |
| 641 } | 728 } |
| 729 return type; | |
| 642 } | 730 } |
| 643 | 731 |
| 644 static ClassType* cast(TypeImpl* type) { | 732 static ClassType* cast(TypeImpl* type) { |
| 645 DCHECK(type->IsClass()); | 733 DCHECK(type->IsClass()); |
| 646 return static_cast<ClassType*>(type); | 734 return static_cast<ClassType*>(type); |
| 647 } | 735 } |
| 648 }; | 736 }; |
| 649 | 737 |
| 650 | 738 |
| 651 // ----------------------------------------------------------------------------- | 739 // ----------------------------------------------------------------------------- |
| 652 // Constant types. | 740 // Constant types. |
| 653 | 741 |
| 654 template<class Config> | 742 template<class Config> |
| 655 class TypeImpl<Config>::ConstantType : public StructuralType { | 743 class TypeImpl<Config>::ConstantType : public StructuralType { |
| 656 public: | 744 public: |
| 657 TypeHandle Bound() { return this->Get(0); } | 745 int BitsetLub() { return this->Get(0)->AsBitset(); } |
|
rossberg
2014/09/23 15:20:38
Same here.
neis1
2014/09/24 07:21:38
Done.
| |
| 658 i::Handle<i::Object> Value() { return this->template GetValue<i::Object>(1); } | 746 i::Handle<i::Object> Value() { return this->template GetValue<i::Object>(1); } |
| 659 | 747 |
| 660 static ConstantHandle New( | 748 static ConstantHandle New(i::Handle<i::Object> value, Region* region) { |
| 661 i::Handle<i::Object> value, TypeHandle bound, Region* region) { | |
| 662 DCHECK(BitsetType::Is(bound->AsBitset(), BitsetType::Lub(*value))); | |
| 663 ConstantHandle type = Config::template cast<ConstantType>( | 749 ConstantHandle type = Config::template cast<ConstantType>( |
| 664 StructuralType::New(StructuralType::kConstantTag, 2, region)); | 750 StructuralType::New(StructuralType::kConstantTag, 2, region)); |
| 665 type->Set(0, bound); | 751 type->Set(0, BitsetType::New(BitsetType::Lub(*value), region)); |
| 666 type->SetValue(1, value); | 752 type->SetValue(1, value); |
| 667 return type; | 753 return type; |
| 668 } | 754 } |
| 669 | 755 |
| 670 static ConstantHandle New(i::Handle<i::Object> value, Region* region) { | |
| 671 TypeHandle bound = BitsetType::New(BitsetType::Lub(*value), region); | |
| 672 return New(value, bound, region); | |
| 673 } | |
| 674 | |
| 675 static ConstantType* cast(TypeImpl* type) { | 756 static ConstantType* cast(TypeImpl* type) { |
| 676 DCHECK(type->IsConstant()); | 757 DCHECK(type->IsConstant()); |
| 677 return static_cast<ConstantType*>(type); | 758 return static_cast<ConstantType*>(type); |
| 678 } | 759 } |
| 679 }; | 760 }; |
| 761 // TODO(neis): Also cache value if numerical. | |
| 762 // TODO(neis): Allow restricting the representation. | |
| 680 | 763 |
| 681 | 764 |
| 682 // ----------------------------------------------------------------------------- | 765 // ----------------------------------------------------------------------------- |
| 683 // Range types. | 766 // Range types. |
| 684 | 767 |
| 685 template<class Config> | 768 template<class Config> |
| 686 class TypeImpl<Config>::RangeType : public StructuralType { | 769 class TypeImpl<Config>::RangeType : public StructuralType { |
| 687 public: | 770 public: |
| 688 TypeHandle Bound() { return this->Get(0); } | 771 int BitsetLub() { return this->Get(0)->AsBitset(); } |
| 689 double Min() { return this->template GetValue<i::HeapNumber>(1)->value(); } | 772 i::Handle<i::Object> Min() { return this->template GetValue<i::Object>(1); } |
| 690 double Max() { return this->template GetValue<i::HeapNumber>(2)->value(); } | 773 i::Handle<i::Object> Max() { return this->template GetValue<i::Object>(2); } |
| 691 | 774 |
| 692 static RangeHandle New( | 775 static RangeHandle New( |
| 693 double min, double max, TypeHandle bound, Region* region) { | 776 i::Handle<i::Object> min, i::Handle<i::Object> max, Region* region) { |
| 694 DCHECK(BitsetType::Is(bound->AsBitset(), BitsetType::Lub(min, max))); | 777 DCHECK(min->Number() <= max->Number()); |
| 695 RangeHandle type = Config::template cast<RangeType>( | 778 RangeHandle type = Config::template cast<RangeType>( |
| 696 StructuralType::New(StructuralType::kRangeTag, 3, region)); | 779 StructuralType::New(StructuralType::kRangeTag, 3, region)); |
| 697 type->Set(0, bound); | 780 type->Set(0, BitsetType::New(BitsetType::Lub(Limits(min, max)), region)); |
| 698 Factory* factory = Config::isolate(region)->factory(); | 781 type->SetValue(1, min); |
| 699 Handle<HeapNumber> minV = factory->NewHeapNumber(min); | 782 type->SetValue(2, max); |
| 700 Handle<HeapNumber> maxV = factory->NewHeapNumber(max); | |
| 701 type->SetValue(1, minV); | |
| 702 type->SetValue(2, maxV); | |
| 703 return type; | 783 return type; |
| 704 } | 784 } |
| 705 | 785 |
| 706 static RangeHandle New(double min, double max, Region* region) { | 786 static RangeHandle New(Limits lim, Region* region) { |
| 707 TypeHandle bound = BitsetType::New(BitsetType::Lub(min, max), region); | 787 return New(lim.min, lim.max, region); |
| 708 return New(min, max, bound, region); | |
| 709 } | 788 } |
| 710 | 789 |
| 711 static RangeType* cast(TypeImpl* type) { | 790 static RangeType* cast(TypeImpl* type) { |
| 712 DCHECK(type->IsRange()); | 791 DCHECK(type->IsRange()); |
| 713 return static_cast<RangeType*>(type); | 792 return static_cast<RangeType*>(type); |
| 714 } | 793 } |
| 715 }; | 794 }; |
| 795 // TODO(neis): Also cache min and max values. | |
| 796 // TODO(neis): Allow restricting the representation. | |
| 716 | 797 |
| 717 | 798 |
| 718 // ----------------------------------------------------------------------------- | 799 // ----------------------------------------------------------------------------- |
| 719 // Context types. | 800 // Context types. |
| 720 | 801 |
| 721 template<class Config> | 802 template<class Config> |
| 722 class TypeImpl<Config>::ContextType : public StructuralType { | 803 class TypeImpl<Config>::ContextType : public StructuralType { |
| 723 public: | 804 public: |
| 724 TypeHandle Bound() { return this->Get(0); } | 805 TypeHandle Outer() { return this->Get(0); } |
| 725 TypeHandle Outer() { return this->Get(1); } | |
| 726 | |
| 727 static ContextHandle New(TypeHandle outer, TypeHandle bound, Region* region) { | |
| 728 DCHECK(BitsetType::Is( | |
| 729 bound->AsBitset(), BitsetType::kInternal & BitsetType::kTaggedPtr)); | |
| 730 ContextHandle type = Config::template cast<ContextType>( | |
| 731 StructuralType::New(StructuralType::kContextTag, 2, region)); | |
| 732 type->Set(0, bound); | |
| 733 type->Set(1, outer); | |
| 734 return type; | |
| 735 } | |
| 736 | 806 |
| 737 static ContextHandle New(TypeHandle outer, Region* region) { | 807 static ContextHandle New(TypeHandle outer, Region* region) { |
| 738 TypeHandle bound = BitsetType::New( | 808 ContextHandle type = Config::template cast<ContextType>( |
| 739 BitsetType::kInternal & BitsetType::kTaggedPtr, region); | 809 StructuralType::New(StructuralType::kContextTag, 1, region)); |
| 740 return New(outer, bound, region); | 810 type->Set(0, outer); |
| 811 return type; | |
| 741 } | 812 } |
| 742 | 813 |
| 743 static ContextType* cast(TypeImpl* type) { | 814 static ContextType* cast(TypeImpl* type) { |
| 744 DCHECK(type->IsContext()); | 815 DCHECK(type->IsContext()); |
| 745 return static_cast<ContextType*>(type); | 816 return static_cast<ContextType*>(type); |
| 746 } | 817 } |
| 747 }; | 818 }; |
| 748 | 819 |
| 749 | 820 |
| 750 // ----------------------------------------------------------------------------- | 821 // ----------------------------------------------------------------------------- |
| 751 // Array types. | 822 // Array types. |
| 752 | 823 |
| 753 template<class Config> | 824 template<class Config> |
| 754 class TypeImpl<Config>::ArrayType : public StructuralType { | 825 class TypeImpl<Config>::ArrayType : public StructuralType { |
| 755 public: | 826 public: |
| 756 TypeHandle Bound() { return this->Get(0); } | 827 TypeHandle Element() { return this->Get(0); } |
| 757 TypeHandle Element() { return this->Get(1); } | |
| 758 | |
| 759 static ArrayHandle New(TypeHandle element, TypeHandle bound, Region* region) { | |
| 760 DCHECK(BitsetType::Is(bound->AsBitset(), BitsetType::kArray)); | |
| 761 ArrayHandle type = Config::template cast<ArrayType>( | |
| 762 StructuralType::New(StructuralType::kArrayTag, 2, region)); | |
| 763 type->Set(0, bound); | |
| 764 type->Set(1, element); | |
| 765 return type; | |
| 766 } | |
| 767 | 828 |
| 768 static ArrayHandle New(TypeHandle element, Region* region) { | 829 static ArrayHandle New(TypeHandle element, Region* region) { |
| 769 TypeHandle bound = BitsetType::New(BitsetType::kArray, region); | 830 ArrayHandle type = Config::template cast<ArrayType>( |
| 770 return New(element, bound, region); | 831 StructuralType::New(StructuralType::kArrayTag, 1, region)); |
| 832 type->Set(0, element); | |
| 833 return type; | |
| 771 } | 834 } |
| 772 | 835 |
| 773 static ArrayType* cast(TypeImpl* type) { | 836 static ArrayType* cast(TypeImpl* type) { |
| 774 DCHECK(type->IsArray()); | 837 DCHECK(type->IsArray()); |
| 775 return static_cast<ArrayType*>(type); | 838 return static_cast<ArrayType*>(type); |
| 776 } | 839 } |
| 777 }; | 840 }; |
| 778 | 841 |
| 779 | 842 |
| 780 // ----------------------------------------------------------------------------- | 843 // ----------------------------------------------------------------------------- |
| 781 // Function types. | 844 // Function types. |
| 782 | 845 |
| 783 template<class Config> | 846 template<class Config> |
| 784 class TypeImpl<Config>::FunctionType : public StructuralType { | 847 class TypeImpl<Config>::FunctionType : public StructuralType { |
| 785 public: | 848 public: |
| 786 int Arity() { return this->Length() - 3; } | 849 int Arity() { return this->Length() - 2; } |
| 787 TypeHandle Bound() { return this->Get(0); } | 850 TypeHandle Result() { return this->Get(0); } |
| 788 TypeHandle Result() { return this->Get(1); } | 851 TypeHandle Receiver() { return this->Get(1); } |
| 789 TypeHandle Receiver() { return this->Get(2); } | 852 TypeHandle Parameter(int i) { return this->Get(2 + i); } |
| 790 TypeHandle Parameter(int i) { return this->Get(3 + i); } | |
| 791 | 853 |
| 792 void InitParameter(int i, TypeHandle type) { this->Set(3 + i, type); } | 854 void InitParameter(int i, TypeHandle type) { this->Set(2 + i, type); } |
| 793 | |
| 794 static FunctionHandle New( | |
| 795 TypeHandle result, TypeHandle receiver, TypeHandle bound, | |
| 796 int arity, Region* region) { | |
| 797 DCHECK(BitsetType::Is(bound->AsBitset(), BitsetType::kFunction)); | |
| 798 FunctionHandle type = Config::template cast<FunctionType>( | |
| 799 StructuralType::New(StructuralType::kFunctionTag, 3 + arity, region)); | |
| 800 type->Set(0, bound); | |
| 801 type->Set(1, result); | |
| 802 type->Set(2, receiver); | |
| 803 return type; | |
| 804 } | |
| 805 | 855 |
| 806 static FunctionHandle New( | 856 static FunctionHandle New( |
| 807 TypeHandle result, TypeHandle receiver, int arity, Region* region) { | 857 TypeHandle result, TypeHandle receiver, int arity, Region* region) { |
| 808 TypeHandle bound = BitsetType::New(BitsetType::kFunction, region); | 858 FunctionHandle type = Config::template cast<FunctionType>( |
| 809 return New(result, receiver, bound, arity, region); | 859 StructuralType::New(StructuralType::kFunctionTag, 2 + arity, region)); |
| 860 type->Set(0, result); | |
| 861 type->Set(1, receiver); | |
| 862 return type; | |
| 810 } | 863 } |
| 811 | 864 |
| 812 static FunctionType* cast(TypeImpl* type) { | 865 static FunctionType* cast(TypeImpl* type) { |
| 813 DCHECK(type->IsFunction()); | 866 DCHECK(type->IsFunction()); |
| 814 return static_cast<FunctionType*>(type); | 867 return static_cast<FunctionType*>(type); |
| 815 } | 868 } |
| 816 }; | 869 }; |
| 817 | 870 |
| 818 | 871 |
| 819 // ----------------------------------------------------------------------------- | 872 // ----------------------------------------------------------------------------- |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 846 // Zone-allocated types; they are either (odd) integers to represent bitsets, or | 899 // Zone-allocated types; they are either (odd) integers to represent bitsets, or |
| 847 // (even) pointers to structures for everything else. | 900 // (even) pointers to structures for everything else. |
| 848 | 901 |
| 849 struct ZoneTypeConfig { | 902 struct ZoneTypeConfig { |
| 850 typedef TypeImpl<ZoneTypeConfig> Type; | 903 typedef TypeImpl<ZoneTypeConfig> Type; |
| 851 class Base {}; | 904 class Base {}; |
| 852 typedef void* Struct; | 905 typedef void* Struct; |
| 853 typedef i::Zone Region; | 906 typedef i::Zone Region; |
| 854 template<class T> struct Handle { typedef T* type; }; | 907 template<class T> struct Handle { typedef T* type; }; |
| 855 | 908 |
| 856 // TODO(neis): This will be removed again once we have struct_get_double(). | |
| 857 static inline i::Isolate* isolate(Region* region) { | |
| 858 return region->isolate(); | |
| 859 } | |
| 860 | |
| 861 template<class T> static inline T* handle(T* type); | 909 template<class T> static inline T* handle(T* type); |
| 862 template<class T> static inline T* cast(Type* type); | 910 template<class T> static inline T* cast(Type* type); |
| 863 | 911 |
| 864 static inline bool is_bitset(Type* type); | 912 static inline bool is_bitset(Type* type); |
| 865 static inline bool is_class(Type* type); | 913 static inline bool is_class(Type* type); |
| 866 static inline bool is_struct(Type* type, int tag); | 914 static inline bool is_struct(Type* type, int tag); |
| 867 | 915 |
| 868 static inline int as_bitset(Type* type); | 916 static inline int as_bitset(Type* type); |
| 869 static inline i::Handle<i::Map> as_class(Type* type); | 917 static inline i::Handle<i::Map> as_class(Type* type); |
| 870 static inline Struct* as_struct(Type* type); | 918 static inline Struct* as_struct(Type* type); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 893 // Heap-allocated types; either smis for bitsets, maps for classes, boxes for | 941 // Heap-allocated types; either smis for bitsets, maps for classes, boxes for |
| 894 // constants, or fixed arrays for unions. | 942 // constants, or fixed arrays for unions. |
| 895 | 943 |
| 896 struct HeapTypeConfig { | 944 struct HeapTypeConfig { |
| 897 typedef TypeImpl<HeapTypeConfig> Type; | 945 typedef TypeImpl<HeapTypeConfig> Type; |
| 898 typedef i::Object Base; | 946 typedef i::Object Base; |
| 899 typedef i::FixedArray Struct; | 947 typedef i::FixedArray Struct; |
| 900 typedef i::Isolate Region; | 948 typedef i::Isolate Region; |
| 901 template<class T> struct Handle { typedef i::Handle<T> type; }; | 949 template<class T> struct Handle { typedef i::Handle<T> type; }; |
| 902 | 950 |
| 903 // TODO(neis): This will be removed again once we have struct_get_double(). | |
| 904 static inline i::Isolate* isolate(Region* region) { | |
| 905 return region; | |
| 906 } | |
| 907 | |
| 908 template<class T> static inline i::Handle<T> handle(T* type); | 951 template<class T> static inline i::Handle<T> handle(T* type); |
| 909 template<class T> static inline i::Handle<T> cast(i::Handle<Type> type); | 952 template<class T> static inline i::Handle<T> cast(i::Handle<Type> type); |
| 910 | 953 |
| 911 static inline bool is_bitset(Type* type); | 954 static inline bool is_bitset(Type* type); |
| 912 static inline bool is_class(Type* type); | 955 static inline bool is_class(Type* type); |
| 913 static inline bool is_struct(Type* type, int tag); | 956 static inline bool is_struct(Type* type, int tag); |
| 914 | 957 |
| 915 static inline int as_bitset(Type* type); | 958 static inline int as_bitset(Type* type); |
| 916 static inline i::Handle<i::Map> as_class(Type* type); | 959 static inline i::Handle<i::Map> as_class(Type* type); |
| 917 static inline i::Handle<Struct> as_struct(Type* type); | 960 static inline i::Handle<Struct> as_struct(Type* type); |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 995 bool Narrows(BoundsImpl that) { | 1038 bool Narrows(BoundsImpl that) { |
| 996 return that.lower->Is(this->lower) && this->upper->Is(that.upper); | 1039 return that.lower->Is(this->lower) && this->upper->Is(that.upper); |
| 997 } | 1040 } |
| 998 }; | 1041 }; |
| 999 | 1042 |
| 1000 typedef BoundsImpl<ZoneTypeConfig> Bounds; | 1043 typedef BoundsImpl<ZoneTypeConfig> Bounds; |
| 1001 | 1044 |
| 1002 } } // namespace v8::internal | 1045 } } // namespace v8::internal |
| 1003 | 1046 |
| 1004 #endif // V8_TYPES_H_ | 1047 #endif // V8_TYPES_H_ |
| OLD | NEW |