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 |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 105 // existing assumptions or tests. | 106 // existing assumptions or tests. |
| 106 // Consequently, do not normally use Equals for type tests, always use Is! | 107 // Consequently, do not normally use Equals for type tests, always use Is! |
| 107 // | 108 // |
| 108 // The NowIs operator implements state-sensitive subtying, as described above. | 109 // The NowIs operator implements state-sensitive subtying, as described above. |
| 109 // Any compilation decision based on such temporary properties requires runtime | 110 // Any compilation decision based on such temporary properties requires runtime |
| 110 // guarding! | 111 // guarding! |
| 111 // | 112 // |
| 112 // PROPERTIES | 113 // PROPERTIES |
| 113 // | 114 // |
| 114 // Various formal properties hold for constructors, operators, and predicates | 115 // Various formal properties hold for constructors, operators, and predicates |
| 115 // over types. For example, constructors are injective, subtyping is a complete | 116 // over types. For example, constructors are injective and subtyping is a |
| 116 // partial order, union and intersection satisfy the usual algebraic properties. | 117 // complete partial order. |
| 117 // | 118 // |
| 118 // See test/cctest/test-types.cc for a comprehensive executable specification, | 119 // See test/cctest/test-types.cc for a comprehensive executable specification, |
| 119 // especially with respect to the properties of the more exotic 'temporal' | 120 // especially with respect to the properties of the more exotic 'temporal' |
| 120 // constructors and predicates (those prefixed 'Now'). | 121 // constructors and predicates (those prefixed 'Now'). |
| 121 // | 122 // |
| 122 // IMPLEMENTATION | 123 // IMPLEMENTATION |
| 123 // | 124 // |
| 124 // Internally, all 'primitive' types, and their unions, are represented as | 125 // 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 | 126 // 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. | 127 // unions containing Class'es or Constant's, currently require allocation. |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 201 V(Primitive, kNumber | kName | kBoolean | kNull | kUndefined) \ | 202 V(Primitive, kNumber | kName | kBoolean | kNull | kUndefined) \ |
| 202 V(DetectableObject, kArray | kFunction | kRegExp | kOtherObject) \ | 203 V(DetectableObject, kArray | kFunction | kRegExp | kOtherObject) \ |
| 203 V(DetectableReceiver, kDetectableObject | kProxy) \ | 204 V(DetectableReceiver, kDetectableObject | kProxy) \ |
| 204 V(Detectable, kDetectableReceiver | kNumber | kName) \ | 205 V(Detectable, kDetectableReceiver | kNumber | kName) \ |
| 205 V(Object, kDetectableObject | kUndetectable) \ | 206 V(Object, kDetectableObject | kUndetectable) \ |
| 206 V(Receiver, kObject | kProxy) \ | 207 V(Receiver, kObject | kProxy) \ |
| 207 V(NonNumber, kBoolean | kName | kNull | kReceiver | \ | 208 V(NonNumber, kBoolean | kName | kNull | kReceiver | \ |
| 208 kUndefined | kInternal) \ | 209 kUndefined | kInternal) \ |
| 209 V(Any, -1) | 210 V(Any, -1) |
| 210 | 211 |
| 212 /* | |
| 213 * The following diagrams show how integers (in the mathematical sense) are | |
| 214 * divided among the different atomic numerical types. | |
| 215 * | |
| 216 * If SmiValuesAre31Bits(): | |
| 217 * | |
| 218 * ON OS32 OSS US OU31 OU32 ON | |
| 219 * ______[_______[_______[_______[_______[_______[_______ | |
| 220 * -2^31 -2^30 0 2^30 2^31 2^32 | |
| 221 * | |
| 222 * Otherwise: | |
|
rossberg
2014/09/10 15:44:15
Nit: indentation off
neis1
2014/09/11 12:58:12
Done.
| |
| 223 * | |
| 224 * ON OSS US OU32 ON | |
| 225 * ______[_______________[_______________[_______[_______ | |
| 226 * -2^31 0 2^31 2^32 | |
| 227 * | |
| 228 * | |
| 229 * E.g., OtherUnsigned32 (OU32) covers all integers from 2^31 to 2^32-1. | |
| 230 * | |
| 231 */ | |
| 232 | |
| 233 #define PROPER_BITSET_TYPE_LIST(V) \ | |
| 234 REPRESENTATION_BITSET_TYPE_LIST(V) \ | |
| 235 SEMANTIC_BITSET_TYPE_LIST(V) | |
| 236 | |
| 211 #define BITSET_TYPE_LIST(V) \ | 237 #define BITSET_TYPE_LIST(V) \ |
| 212 MASK_BITSET_TYPE_LIST(V) \ | 238 MASK_BITSET_TYPE_LIST(V) \ |
| 213 REPRESENTATION_BITSET_TYPE_LIST(V) \ | 239 PROPER_BITSET_TYPE_LIST(V) |
| 214 SEMANTIC_BITSET_TYPE_LIST(V) | |
| 215 | 240 |
| 216 | 241 |
| 217 // ----------------------------------------------------------------------------- | 242 // ----------------------------------------------------------------------------- |
| 218 // The abstract Type class, parameterized over the low-level representation. | 243 // The abstract Type class, parameterized over the low-level representation. |
| 219 | 244 |
| 220 // struct Config { | 245 // struct Config { |
| 221 // typedef TypeImpl<Config> Type; | 246 // typedef TypeImpl<Config> Type; |
| 222 // typedef Base; | 247 // typedef Base; |
| 223 // typedef Struct; | 248 // typedef Struct; |
| 224 // typedef Region; | 249 // typedef Region; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 272 typedef typename Config::template Handle<UnionType>::type UnionHandle; | 297 typedef typename Config::template Handle<UnionType>::type UnionHandle; |
| 273 typedef typename Config::Region Region; | 298 typedef typename Config::Region Region; |
| 274 | 299 |
| 275 // Constructors. | 300 // Constructors. |
| 276 | 301 |
| 277 #define DEFINE_TYPE_CONSTRUCTOR(type, value) \ | 302 #define DEFINE_TYPE_CONSTRUCTOR(type, value) \ |
| 278 static TypeImpl* type() { return BitsetType::New(BitsetType::k##type); } \ | 303 static TypeImpl* type() { return BitsetType::New(BitsetType::k##type); } \ |
| 279 static TypeHandle type(Region* region) { \ | 304 static TypeHandle type(Region* region) { \ |
| 280 return BitsetType::New(BitsetType::k##type, region); \ | 305 return BitsetType::New(BitsetType::k##type, region); \ |
| 281 } | 306 } |
| 282 BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR) | 307 PROPER_BITSET_TYPE_LIST(DEFINE_TYPE_CONSTRUCTOR) |
| 283 #undef DEFINE_TYPE_CONSTRUCTOR | 308 #undef DEFINE_TYPE_CONSTRUCTOR |
| 284 | 309 |
| 285 static TypeHandle Class(i::Handle<i::Map> map, Region* region) { | 310 static TypeHandle Class(i::Handle<i::Map> map, Region* region) { |
| 286 return ClassType::New(map, region); | 311 return ClassType::New(map, region); |
| 287 } | 312 } |
| 288 static TypeHandle Constant(i::Handle<i::Object> value, Region* region) { | 313 static TypeHandle Constant(i::Handle<i::Object> value, Region* region) { |
| 289 // TODO(neis): Return RangeType for numerical values. | |
| 290 return ConstantType::New(value, region); | 314 return ConstantType::New(value, region); |
| 291 } | 315 } |
| 292 static TypeHandle Range(double min, double max, Region* region) { | 316 static TypeHandle Range( |
| 317 i::Handle<i::Object> min, i::Handle<i::Object> max, Region* region) { | |
| 293 return RangeType::New(min, max, region); | 318 return RangeType::New(min, max, region); |
| 294 } | 319 } |
| 295 static TypeHandle Context(TypeHandle outer, Region* region) { | 320 static TypeHandle Context(TypeHandle outer, Region* region) { |
| 296 return ContextType::New(outer, region); | 321 return ContextType::New(outer, region); |
| 297 } | 322 } |
| 298 static TypeHandle Array(TypeHandle element, Region* region) { | 323 static TypeHandle Array(TypeHandle element, Region* region) { |
| 299 return ArrayType::New(element, region); | 324 return ArrayType::New(element, region); |
| 300 } | 325 } |
| 301 static FunctionHandle Function( | 326 static FunctionHandle Function( |
| 302 TypeHandle result, TypeHandle receiver, int arity, Region* region) { | 327 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); } | 375 bool Is(TypeHandle that) { return this->Is(*that); } |
| 351 | 376 |
| 352 bool Maybe(TypeImpl* that); | 377 bool Maybe(TypeImpl* that); |
| 353 template<class TypeHandle> | 378 template<class TypeHandle> |
| 354 bool Maybe(TypeHandle that) { return this->Maybe(*that); } | 379 bool Maybe(TypeHandle that) { return this->Maybe(*that); } |
| 355 | 380 |
| 356 bool Equals(TypeImpl* that) { return this->Is(that) && that->Is(this); } | 381 bool Equals(TypeImpl* that) { return this->Is(that) && that->Is(this); } |
| 357 template<class TypeHandle> | 382 template<class TypeHandle> |
| 358 bool Equals(TypeHandle that) { return this->Equals(*that); } | 383 bool Equals(TypeHandle that) { return this->Equals(*that); } |
| 359 | 384 |
| 360 // Equivalent to Constant(value)->Is(this), but avoiding allocation. | 385 // Equivalent to Constant(val)->Is(this), but avoiding allocation. |
| 361 bool Contains(i::Object* val); | 386 bool Contains(i::Object* val); |
| 362 bool Contains(i::Handle<i::Object> val) { return this->Contains(*val); } | 387 bool Contains(i::Handle<i::Object> val) { return this->Contains(*val); } |
| 363 | 388 |
| 364 // State-dependent versions of the above that consider subtyping between | 389 // State-dependent versions of the above that consider subtyping between |
| 365 // a constant and its map class. | 390 // a constant and its map class. |
| 366 inline static TypeHandle NowOf(i::Object* value, Region* region); | 391 inline static TypeHandle NowOf(i::Object* value, Region* region); |
| 367 static TypeHandle NowOf(i::Handle<i::Object> value, Region* region) { | 392 static TypeHandle NowOf(i::Handle<i::Object> value, Region* region) { |
| 368 return NowOf(*value, region); | 393 return NowOf(*value, region); |
| 369 } | 394 } |
| 370 bool NowIs(TypeImpl* that); | 395 bool NowIs(TypeImpl* that); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 459 int AsBitset() { | 484 int AsBitset() { |
| 460 DCHECK(this->IsBitset()); | 485 DCHECK(this->IsBitset()); |
| 461 return static_cast<BitsetType*>(this)->Bitset(); | 486 return static_cast<BitsetType*>(this)->Bitset(); |
| 462 } | 487 } |
| 463 UnionType* AsUnion() { return UnionType::cast(this); } | 488 UnionType* AsUnion() { return UnionType::cast(this); } |
| 464 | 489 |
| 465 // Auxiliary functions. | 490 // Auxiliary functions. |
| 466 | 491 |
| 467 int BitsetGlb() { return BitsetType::Glb(this); } | 492 int BitsetGlb() { return BitsetType::Glb(this); } |
| 468 int BitsetLub() { return BitsetType::Lub(this); } | 493 int BitsetLub() { return BitsetType::Lub(this); } |
| 469 int InherentBitsetLub() { return BitsetType::InherentLub(this); } | |
| 470 | 494 |
| 471 bool SlowIs(TypeImpl* that); | 495 bool SlowIs(TypeImpl* that); |
| 472 | 496 |
| 473 TypeHandle Rebound(int bitset, Region* region); | 497 static bool IsInteger(double x) { |
| 474 int BoundBy(TypeImpl* that); | 498 return nearbyint(x) == x && !i::IsMinusZero(x); // Allows for infinities. |
| 475 int IndexInUnion(int bound, UnionHandle unioned, int current_size); | 499 } |
| 476 static int ExtendUnion( | 500 static bool IsInteger(i::Object* x) { |
| 477 UnionHandle unioned, int current_size, TypeHandle t, | 501 return x->IsNumber() && IsInteger(x->Number()); |
| 478 TypeHandle other, bool is_intersect, Region* region); | 502 } |
| 503 | |
| 504 struct Limits { | |
| 505 i::Handle<i::Object> min; | |
| 506 i::Handle<i::Object> max; | |
| 507 Limits(i::Handle<i::Object> min, i::Handle<i::Object> max) : | |
| 508 min(min), max(max) {} | |
| 509 explicit Limits(RangeType* range) : | |
| 510 min(range->MinV()), max(range->MaxV()) {} | |
| 511 }; | |
| 512 | |
| 513 static Limits intersect(Limits lhs, Limits rhs); | |
| 514 static Limits union_(Limits lhs, Limits rhs); | |
| 515 static bool overlap(RangeType* lhs, RangeType* rhs); | |
| 516 static bool contains(RangeType* lhs, RangeType* rhs); | |
| 517 static bool contains(RangeType* range, i::Object* val); | |
| 518 | |
| 519 RangeType* GetRange(); | |
| 520 static int UpdateRange( | |
| 521 RangeHandle type, UnionHandle result, int size, Region* region); | |
| 522 | |
| 523 bool SimplyEquals(TypeImpl* that); | |
| 524 static int AddToUnion( | |
| 525 TypeHandle type, UnionHandle result, int size, Region* region); | |
| 526 static int IntersectAux( | |
| 527 TypeHandle type, TypeHandle other, | |
| 528 UnionHandle result, int size, Region* region); | |
| 529 static TypeHandle NormalizeUnion(UnionHandle unioned, int size); | |
| 479 }; | 530 }; |
| 480 | 531 |
| 481 | 532 |
| 482 // ----------------------------------------------------------------------------- | 533 // ----------------------------------------------------------------------------- |
| 483 // Bitset types (internal). | 534 // Bitset types (internal). |
| 484 | 535 |
| 485 template<class Config> | 536 template<class Config> |
| 486 class TypeImpl<Config>::BitsetType : public TypeImpl<Config> { | 537 class TypeImpl<Config>::BitsetType : public TypeImpl<Config> { |
| 487 protected: | 538 protected: |
| 488 friend class TypeImpl<Config>; | 539 friend class TypeImpl<Config>; |
| 489 | 540 |
| 490 enum { | 541 enum { |
| 491 #define DECLARE_TYPE(type, value) k##type = (value), | 542 #define DECLARE_TYPE(type, value) k##type = (value), |
| 492 BITSET_TYPE_LIST(DECLARE_TYPE) | 543 BITSET_TYPE_LIST(DECLARE_TYPE) |
| 493 #undef DECLARE_TYPE | 544 #undef DECLARE_TYPE |
| 494 kUnusedEOL = 0 | 545 kUnusedEOL = 0 |
| 495 }; | 546 }; |
| 496 | 547 |
| 497 int Bitset() { return Config::as_bitset(this); } | 548 int Bitset() { return Config::as_bitset(this); } |
| 498 | 549 |
| 499 static TypeImpl* New(int bitset) { | 550 static TypeImpl* New(int bitset) { |
| 551 DCHECK(bitset == kNone || IsInhabited(bitset)); | |
| 500 return static_cast<BitsetType*>(Config::from_bitset(bitset)); | 552 return static_cast<BitsetType*>(Config::from_bitset(bitset)); |
| 501 } | 553 } |
| 502 static TypeHandle New(int bitset, Region* region) { | 554 static TypeHandle New(int bitset, Region* region) { |
| 555 DCHECK(bitset == kNone || IsInhabited(bitset)); | |
| 503 return Config::from_bitset(bitset, region); | 556 return Config::from_bitset(bitset, region); |
| 504 } | 557 } |
| 505 | 558 |
| 506 static bool IsInhabited(int bitset) { | 559 static bool IsInhabited(int bitset) { |
| 507 return (bitset & kRepresentation) && (bitset & kSemantic); | 560 return (bitset & kRepresentation) && (bitset & kSemantic); |
| 508 } | 561 } |
| 509 | 562 |
| 510 static bool Is(int bitset1, int bitset2) { | 563 static bool Is(int bitset1, int bitset2) { |
| 511 return (bitset1 | bitset2) == bitset2; | 564 return (bitset1 | bitset2) == bitset2; |
| 512 } | 565 } |
| 513 | 566 |
| 514 static int Glb(TypeImpl* type); // greatest lower bound that's a bitset | 567 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 | 568 static int Lub(TypeImpl* type); // least upper bound that's a bitset |
| 516 static int Lub(i::Object* value); | 569 static int Lub(i::Object* value); |
| 517 static int Lub(double value); | 570 static int Lub(double value); |
| 518 static int Lub(int32_t value); | 571 static int Lub(int32_t value); |
| 519 static int Lub(uint32_t value); | 572 static int Lub(uint32_t value); |
| 520 static int Lub(i::Map* map); | 573 static int Lub(i::Map* map); |
| 521 static int Lub(double min, double max); | 574 static int Lub(Limits lim); |
| 522 static int InherentLub(TypeImpl* type); | 575 static double Min(int bitset); |
| 523 | 576 |
| 524 static const char* Name(int bitset); | 577 static const char* Name(int bitset); |
| 525 static void Print(OStream& os, int bitset); // NOLINT | 578 static void Print(OStream& os, int bitset); // NOLINT |
| 526 using TypeImpl::PrintTo; | 579 #ifdef DEBUG |
| 580 static void Print(int bitset); | |
| 581 #endif | |
| 527 }; | 582 }; |
| 528 | 583 |
| 529 | 584 |
| 530 // ----------------------------------------------------------------------------- | 585 // ----------------------------------------------------------------------------- |
| 531 // Superclass for non-bitset types (internal). | 586 // Superclass for non-bitset types (internal). |
| 532 // Contains a tag and a variable number of type or value fields. | 587 // Contains a tag and a variable number of type or value fields. |
| 533 | 588 |
| 534 template<class Config> | 589 template<class Config> |
| 535 class TypeImpl<Config>::StructuralType : public TypeImpl<Config> { | 590 class TypeImpl<Config>::StructuralType : public TypeImpl<Config> { |
| 536 protected: | 591 protected: |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 602 bool Wellformed(); | 657 bool Wellformed(); |
| 603 }; | 658 }; |
| 604 | 659 |
| 605 | 660 |
| 606 // ----------------------------------------------------------------------------- | 661 // ----------------------------------------------------------------------------- |
| 607 // Class types. | 662 // Class types. |
| 608 | 663 |
| 609 template<class Config> | 664 template<class Config> |
| 610 class TypeImpl<Config>::ClassType : public StructuralType { | 665 class TypeImpl<Config>::ClassType : public StructuralType { |
| 611 public: | 666 public: |
| 612 TypeHandle Bound(Region* region) { | |
| 613 return Config::is_class(this) | |
| 614 ? BitsetType::New(BitsetType::Lub(*Config::as_class(this)), region) | |
| 615 : this->Get(0); | |
| 616 } | |
| 617 i::Handle<i::Map> Map() { | 667 i::Handle<i::Map> Map() { |
| 618 return Config::is_class(this) | 668 return Config::is_class(this) |
| 619 ? Config::as_class(this) | 669 ? Config::as_class(this) |
| 620 : this->template GetValue<i::Map>(1); | 670 : this->template GetValue<i::Map>(0); |
| 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 } | 671 } |
| 632 | 672 |
| 633 static ClassHandle New(i::Handle<i::Map> map, Region* region) { | 673 static ClassHandle New(i::Handle<i::Map> map, Region* region) { |
| 634 ClassHandle type = | 674 ClassHandle type = |
| 635 Config::template cast<ClassType>(Config::from_class(map, region)); | 675 Config::template cast<ClassType>(Config::from_class(map, region)); |
| 636 if (type->IsClass()) { | 676 if (!type->IsClass()) { |
| 637 return type; | 677 type = Config::template cast<ClassType>( |
| 638 } else { | 678 StructuralType::New(StructuralType::kClassTag, 1, region)); |
|
rossberg
2014/09/10 15:44:15
Nit: style guide wants +4 indentation for line con
neis1
2014/09/11 12:58:12
Done.
| |
| 639 TypeHandle bound = BitsetType::New(BitsetType::Lub(*map), region); | 679 type->SetValue(0, map); |
| 640 return New(map, bound, region); | |
| 641 } | 680 } |
| 681 return type; | |
| 642 } | 682 } |
| 643 | 683 |
| 644 static ClassType* cast(TypeImpl* type) { | 684 static ClassType* cast(TypeImpl* type) { |
| 645 DCHECK(type->IsClass()); | 685 DCHECK(type->IsClass()); |
| 646 return static_cast<ClassType*>(type); | 686 return static_cast<ClassType*>(type); |
| 647 } | 687 } |
| 648 }; | 688 }; |
| 649 | 689 |
| 650 | 690 |
| 651 // ----------------------------------------------------------------------------- | 691 // ----------------------------------------------------------------------------- |
| 652 // Constant types. | 692 // Constant types. |
| 653 | 693 |
| 654 template<class Config> | 694 template<class Config> |
| 655 class TypeImpl<Config>::ConstantType : public StructuralType { | 695 class TypeImpl<Config>::ConstantType : public StructuralType { |
| 656 public: | 696 public: |
| 657 TypeHandle Bound() { return this->Get(0); } | 697 i::Handle<i::Object> Value() { |
| 658 i::Handle<i::Object> Value() { return this->template GetValue<i::Object>(1); } | 698 return this->template GetValue<i::Object>(0); |
|
rossberg
2014/09/10 15:44:15
Nit: probably fits on previous line
neis1
2014/09/11 12:58:12
Done.
| |
| 699 } | |
| 659 | 700 |
| 660 static ConstantHandle New( | 701 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>( | 702 ConstantHandle type = Config::template cast<ConstantType>( |
| 664 StructuralType::New(StructuralType::kConstantTag, 2, region)); | 703 StructuralType::New(StructuralType::kConstantTag, 1, region)); |
| 665 type->Set(0, bound); | 704 type->SetValue(0, value); |
| 666 type->SetValue(1, value); | |
| 667 return type; | 705 return type; |
| 668 } | 706 } |
| 669 | 707 |
| 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) { | 708 static ConstantType* cast(TypeImpl* type) { |
| 676 DCHECK(type->IsConstant()); | 709 DCHECK(type->IsConstant()); |
| 677 return static_cast<ConstantType*>(type); | 710 return static_cast<ConstantType*>(type); |
| 678 } | 711 } |
| 679 }; | 712 }; |
| 680 | 713 |
| 681 | 714 |
| 682 // ----------------------------------------------------------------------------- | 715 // ----------------------------------------------------------------------------- |
| 683 // Range types. | 716 // Range types. |
| 717 // They represent continuous integer intervals in the form of a minimum | |
|
rossberg
2014/09/10 15:44:15
This should go to the top, along with the other ex
neis1
2014/09/11 12:58:12
Done.
| |
| 718 // and a maximum value. Either value might be an infinity. | |
| 719 // | |
| 720 // Constant(v) is considered a subtype of Range(x..y) if v happens to be an | |
| 721 // integer between x and y. | |
| 684 | 722 |
| 685 template<class Config> | 723 template<class Config> |
| 686 class TypeImpl<Config>::RangeType : public StructuralType { | 724 class TypeImpl<Config>::RangeType : public StructuralType { |
| 687 public: | 725 public: |
| 688 TypeHandle Bound() { return this->Get(0); } | 726 i::Handle<i::Object> MinV() { return this->template GetValue<i::Object>(0); } |
| 689 double Min() { return this->template GetValue<i::HeapNumber>(1)->value(); } | 727 i::Handle<i::Object> MaxV() { return this->template GetValue<i::Object>(1); } |
| 690 double Max() { return this->template GetValue<i::HeapNumber>(2)->value(); } | 728 double Min() { return MinV()->Number(); } |
| 729 double Max() { return MaxV()->Number(); } | |
|
rossberg
2014/09/10 15:44:15
Since we call the method to get a numeric value fr
neis1
2014/09/11 12:58:12
Not sure I'm following. Are you suggesting to exp
rossberg
2014/09/15 15:58:29
The latter. It's more consistent with our naming e
neis1
2014/09/16 10:03:59
But less consistent with the naming here, such as
rossberg
2014/09/16 14:04:40
OK, fair enough. Actually, I'd say, just remove th
neis1
2014/09/18 13:05:18
Done.
| |
| 691 | 730 |
| 692 static RangeHandle New( | 731 static RangeHandle New( |
| 693 double min, double max, TypeHandle bound, Region* region) { | 732 i::Handle<i::Object> min, i::Handle<i::Object> max, Region* region) { |
| 694 DCHECK(BitsetType::Is(bound->AsBitset(), BitsetType::Lub(min, max))); | 733 DCHECK(min->Number() <= max->Number()); |
| 695 RangeHandle type = Config::template cast<RangeType>( | 734 RangeHandle type = Config::template cast<RangeType>( |
| 696 StructuralType::New(StructuralType::kRangeTag, 3, region)); | 735 StructuralType::New(StructuralType::kRangeTag, 2, region)); |
| 697 type->Set(0, bound); | 736 type->SetValue(0, min); |
| 698 Factory* factory = Config::isolate(region)->factory(); | 737 type->SetValue(1, max); |
| 699 Handle<HeapNumber> minV = factory->NewHeapNumber(min); | 738 #ifdef DEBUG |
|
rossberg
2014/09/10 15:44:15
Debugging left-overs?
neis1
2014/09/11 12:58:12
Done.
| |
| 700 Handle<HeapNumber> maxV = factory->NewHeapNumber(max); | 739 type->Print(); |
| 701 type->SetValue(1, minV); | 740 #endif |
| 702 type->SetValue(2, maxV); | |
| 703 return type; | 741 return type; |
| 704 } | 742 } |
| 705 | 743 |
| 706 static RangeHandle New(double min, double max, Region* region) { | 744 static RangeHandle New(Limits lim, Region* region) { |
| 707 TypeHandle bound = BitsetType::New(BitsetType::Lub(min, max), region); | 745 return New(lim.min, lim.max, region); |
| 708 return New(min, max, bound, region); | |
| 709 } | 746 } |
| 710 | 747 |
| 711 static RangeType* cast(TypeImpl* type) { | 748 static RangeType* cast(TypeImpl* type) { |
| 712 DCHECK(type->IsRange()); | 749 DCHECK(type->IsRange()); |
| 713 return static_cast<RangeType*>(type); | 750 return static_cast<RangeType*>(type); |
| 714 } | 751 } |
| 715 }; | 752 }; |
| 716 | 753 |
| 717 | 754 |
| 718 // ----------------------------------------------------------------------------- | 755 // ----------------------------------------------------------------------------- |
| 719 // Context types. | 756 // Context types. |
| 720 | 757 |
| 721 template<class Config> | 758 template<class Config> |
| 722 class TypeImpl<Config>::ContextType : public StructuralType { | 759 class TypeImpl<Config>::ContextType : public StructuralType { |
| 723 public: | 760 public: |
| 724 TypeHandle Bound() { return this->Get(0); } | 761 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 | 762 |
| 737 static ContextHandle New(TypeHandle outer, Region* region) { | 763 static ContextHandle New(TypeHandle outer, Region* region) { |
| 738 TypeHandle bound = BitsetType::New( | 764 ContextHandle type = Config::template cast<ContextType>( |
| 739 BitsetType::kInternal & BitsetType::kTaggedPtr, region); | 765 StructuralType::New(StructuralType::kContextTag, 1, region)); |
| 740 return New(outer, bound, region); | 766 type->Set(0, outer); |
| 767 return type; | |
| 741 } | 768 } |
| 742 | 769 |
| 743 static ContextType* cast(TypeImpl* type) { | 770 static ContextType* cast(TypeImpl* type) { |
| 744 DCHECK(type->IsContext()); | 771 DCHECK(type->IsContext()); |
| 745 return static_cast<ContextType*>(type); | 772 return static_cast<ContextType*>(type); |
| 746 } | 773 } |
| 747 }; | 774 }; |
| 748 | 775 |
| 749 | 776 |
| 750 // ----------------------------------------------------------------------------- | 777 // ----------------------------------------------------------------------------- |
| 751 // Array types. | 778 // Array types. |
| 752 | 779 |
| 753 template<class Config> | 780 template<class Config> |
| 754 class TypeImpl<Config>::ArrayType : public StructuralType { | 781 class TypeImpl<Config>::ArrayType : public StructuralType { |
| 755 public: | 782 public: |
| 756 TypeHandle Bound() { return this->Get(0); } | 783 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 | 784 |
| 768 static ArrayHandle New(TypeHandle element, Region* region) { | 785 static ArrayHandle New(TypeHandle element, Region* region) { |
| 769 TypeHandle bound = BitsetType::New(BitsetType::kArray, region); | 786 ArrayHandle type = Config::template cast<ArrayType>( |
| 770 return New(element, bound, region); | 787 StructuralType::New(StructuralType::kArrayTag, 1, region)); |
| 788 type->Set(0, element); | |
| 789 return type; | |
| 771 } | 790 } |
| 772 | 791 |
| 773 static ArrayType* cast(TypeImpl* type) { | 792 static ArrayType* cast(TypeImpl* type) { |
| 774 DCHECK(type->IsArray()); | 793 DCHECK(type->IsArray()); |
| 775 return static_cast<ArrayType*>(type); | 794 return static_cast<ArrayType*>(type); |
| 776 } | 795 } |
| 777 }; | 796 }; |
| 778 | 797 |
| 779 | 798 |
| 780 // ----------------------------------------------------------------------------- | 799 // ----------------------------------------------------------------------------- |
| 781 // Function types. | 800 // Function types. |
| 782 | 801 |
| 783 template<class Config> | 802 template<class Config> |
| 784 class TypeImpl<Config>::FunctionType : public StructuralType { | 803 class TypeImpl<Config>::FunctionType : public StructuralType { |
| 785 public: | 804 public: |
| 786 int Arity() { return this->Length() - 3; } | 805 int Arity() { return this->Length() - 2; } |
| 787 TypeHandle Bound() { return this->Get(0); } | 806 TypeHandle Result() { return this->Get(0); } |
| 788 TypeHandle Result() { return this->Get(1); } | 807 TypeHandle Receiver() { return this->Get(1); } |
| 789 TypeHandle Receiver() { return this->Get(2); } | 808 TypeHandle Parameter(int i) { return this->Get(2 + i); } |
| 790 TypeHandle Parameter(int i) { return this->Get(3 + i); } | |
| 791 | 809 |
| 792 void InitParameter(int i, TypeHandle type) { this->Set(3 + i, type); } | 810 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 | 811 |
| 806 static FunctionHandle New( | 812 static FunctionHandle New( |
| 807 TypeHandle result, TypeHandle receiver, int arity, Region* region) { | 813 TypeHandle result, TypeHandle receiver, int arity, Region* region) { |
| 808 TypeHandle bound = BitsetType::New(BitsetType::kFunction, region); | 814 FunctionHandle type = Config::template cast<FunctionType>( |
| 809 return New(result, receiver, bound, arity, region); | 815 StructuralType::New(StructuralType::kFunctionTag, 2 + arity, region)); |
| 816 type->Set(0, result); | |
| 817 type->Set(1, receiver); | |
| 818 return type; | |
| 810 } | 819 } |
| 811 | 820 |
| 812 static FunctionType* cast(TypeImpl* type) { | 821 static FunctionType* cast(TypeImpl* type) { |
| 813 DCHECK(type->IsFunction()); | 822 DCHECK(type->IsFunction()); |
| 814 return static_cast<FunctionType*>(type); | 823 return static_cast<FunctionType*>(type); |
| 815 } | 824 } |
| 816 }; | 825 }; |
| 817 | 826 |
| 818 | 827 |
| 819 // ----------------------------------------------------------------------------- | 828 // ----------------------------------------------------------------------------- |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 846 // Zone-allocated types; they are either (odd) integers to represent bitsets, or | 855 // Zone-allocated types; they are either (odd) integers to represent bitsets, or |
| 847 // (even) pointers to structures for everything else. | 856 // (even) pointers to structures for everything else. |
| 848 | 857 |
| 849 struct ZoneTypeConfig { | 858 struct ZoneTypeConfig { |
| 850 typedef TypeImpl<ZoneTypeConfig> Type; | 859 typedef TypeImpl<ZoneTypeConfig> Type; |
| 851 class Base {}; | 860 class Base {}; |
| 852 typedef void* Struct; | 861 typedef void* Struct; |
| 853 typedef i::Zone Region; | 862 typedef i::Zone Region; |
| 854 template<class T> struct Handle { typedef T* type; }; | 863 template<class T> struct Handle { typedef T* type; }; |
| 855 | 864 |
| 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); | 865 template<class T> static inline T* handle(T* type); |
| 862 template<class T> static inline T* cast(Type* type); | 866 template<class T> static inline T* cast(Type* type); |
| 863 | 867 |
| 864 static inline bool is_bitset(Type* type); | 868 static inline bool is_bitset(Type* type); |
| 865 static inline bool is_class(Type* type); | 869 static inline bool is_class(Type* type); |
| 866 static inline bool is_struct(Type* type, int tag); | 870 static inline bool is_struct(Type* type, int tag); |
| 867 | 871 |
| 868 static inline int as_bitset(Type* type); | 872 static inline int as_bitset(Type* type); |
| 869 static inline i::Handle<i::Map> as_class(Type* type); | 873 static inline i::Handle<i::Map> as_class(Type* type); |
| 870 static inline Struct* as_struct(Type* type); | 874 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 | 897 // Heap-allocated types; either smis for bitsets, maps for classes, boxes for |
| 894 // constants, or fixed arrays for unions. | 898 // constants, or fixed arrays for unions. |
| 895 | 899 |
| 896 struct HeapTypeConfig { | 900 struct HeapTypeConfig { |
| 897 typedef TypeImpl<HeapTypeConfig> Type; | 901 typedef TypeImpl<HeapTypeConfig> Type; |
| 898 typedef i::Object Base; | 902 typedef i::Object Base; |
| 899 typedef i::FixedArray Struct; | 903 typedef i::FixedArray Struct; |
| 900 typedef i::Isolate Region; | 904 typedef i::Isolate Region; |
| 901 template<class T> struct Handle { typedef i::Handle<T> type; }; | 905 template<class T> struct Handle { typedef i::Handle<T> type; }; |
| 902 | 906 |
| 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); | 907 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); | 908 template<class T> static inline i::Handle<T> cast(i::Handle<Type> type); |
| 910 | 909 |
| 911 static inline bool is_bitset(Type* type); | 910 static inline bool is_bitset(Type* type); |
| 912 static inline bool is_class(Type* type); | 911 static inline bool is_class(Type* type); |
| 913 static inline bool is_struct(Type* type, int tag); | 912 static inline bool is_struct(Type* type, int tag); |
| 914 | 913 |
| 915 static inline int as_bitset(Type* type); | 914 static inline int as_bitset(Type* type); |
| 916 static inline i::Handle<i::Map> as_class(Type* type); | 915 static inline i::Handle<i::Map> as_class(Type* type); |
| 917 static inline i::Handle<Struct> as_struct(Type* type); | 916 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) { | 994 bool Narrows(BoundsImpl that) { |
| 996 return that.lower->Is(this->lower) && this->upper->Is(that.upper); | 995 return that.lower->Is(this->lower) && this->upper->Is(that.upper); |
| 997 } | 996 } |
| 998 }; | 997 }; |
| 999 | 998 |
| 1000 typedef BoundsImpl<ZoneTypeConfig> Bounds; | 999 typedef BoundsImpl<ZoneTypeConfig> Bounds; |
| 1001 | 1000 |
| 1002 } } // namespace v8::internal | 1001 } } // namespace v8::internal |
| 1003 | 1002 |
| 1004 #endif // V8_TYPES_H_ | 1003 #endif // V8_TYPES_H_ |
| OLD | NEW |