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...) 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...) 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...) 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...) 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...) 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...) 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...) 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...) 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...) 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 |