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 #include <iomanip> | 5 #include <iomanip> |
6 | 6 |
7 #include "src/compiler/types.h" | 7 #include "src/compiler/types.h" |
8 | 8 |
9 #include "src/handles-inl.h" | 9 #include "src/handles-inl.h" |
10 #include "src/ostreams.h" | 10 #include "src/ostreams.h" |
(...skipping 44 matching lines...) Loading... | |
55 DisallowHeapAllocation no_allocation; | 55 DisallowHeapAllocation no_allocation; |
56 return lhs->Min() <= rhs->Min() && rhs->Max() <= lhs->Max(); | 56 return lhs->Min() <= rhs->Min() && rhs->Max() <= lhs->Max(); |
57 } | 57 } |
58 | 58 |
59 bool Type::Contains(RangeType* lhs, ConstantType* rhs) { | 59 bool Type::Contains(RangeType* lhs, ConstantType* rhs) { |
60 DisallowHeapAllocation no_allocation; | 60 DisallowHeapAllocation no_allocation; |
61 return IsInteger(*rhs->Value()) && lhs->Min() <= rhs->Value()->Number() && | 61 return IsInteger(*rhs->Value()) && lhs->Min() <= rhs->Value()->Number() && |
62 rhs->Value()->Number() <= lhs->Max(); | 62 rhs->Value()->Number() <= lhs->Max(); |
63 } | 63 } |
64 | 64 |
65 bool Type::Contains(RangeType* lhs, NumberConstantType* rhs) { | |
66 DisallowHeapAllocation no_allocation; | |
67 return IsInteger(rhs->Value()) && lhs->Min() <= rhs->Value() && | |
mvstanton
2016/09/28 14:47:44
Actually don't do this - a numberconstant is NEVER
mvstanton
2016/10/04 11:55:55
Done.
| |
68 rhs->Value() <= lhs->Max(); | |
69 } | |
70 | |
65 bool Type::Contains(RangeType* range, i::Object* val) { | 71 bool Type::Contains(RangeType* range, i::Object* val) { |
66 DisallowHeapAllocation no_allocation; | 72 DisallowHeapAllocation no_allocation; |
67 return IsInteger(val) && range->Min() <= val->Number() && | 73 return IsInteger(val) && range->Min() <= val->Number() && |
68 val->Number() <= range->Max(); | 74 val->Number() <= range->Max(); |
69 } | 75 } |
70 | 76 |
71 // ----------------------------------------------------------------------------- | 77 // ----------------------------------------------------------------------------- |
72 // Min and Max computation. | 78 // Min and Max computation. |
73 | 79 |
74 double Type::Min() { | 80 double Type::Min() { |
75 DCHECK(this->Is(Number())); | 81 DCHECK(this->Is(Number())); |
76 if (this->IsBitset()) return BitsetType::Min(this->AsBitset()); | 82 if (this->IsBitset()) return BitsetType::Min(this->AsBitset()); |
77 if (this->IsUnion()) { | 83 if (this->IsUnion()) { |
78 double min = +V8_INFINITY; | 84 double min = +V8_INFINITY; |
79 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { | 85 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { |
80 min = std::min(min, this->AsUnion()->Get(i)->Min()); | 86 min = std::min(min, this->AsUnion()->Get(i)->Min()); |
81 } | 87 } |
82 return min; | 88 return min; |
83 } | 89 } |
84 if (this->IsRange()) return this->AsRange()->Min(); | 90 if (this->IsRange()) return this->AsRange()->Min(); |
85 if (this->IsConstant()) return this->AsConstant()->Value()->Number(); | 91 if (this->IsConstant()) return this->AsConstant()->Value()->Number(); |
92 if (this->IsNumberConstant()) return this->AsNumberConstant()->Value(); | |
86 UNREACHABLE(); | 93 UNREACHABLE(); |
87 return 0; | 94 return 0; |
88 } | 95 } |
89 | 96 |
90 double Type::Max() { | 97 double Type::Max() { |
91 DCHECK(this->Is(Number())); | 98 DCHECK(this->Is(Number())); |
92 if (this->IsBitset()) return BitsetType::Max(this->AsBitset()); | 99 if (this->IsBitset()) return BitsetType::Max(this->AsBitset()); |
93 if (this->IsUnion()) { | 100 if (this->IsUnion()) { |
94 double max = -V8_INFINITY; | 101 double max = -V8_INFINITY; |
95 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { | 102 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { |
96 max = std::max(max, this->AsUnion()->Get(i)->Max()); | 103 max = std::max(max, this->AsUnion()->Get(i)->Max()); |
97 } | 104 } |
98 return max; | 105 return max; |
99 } | 106 } |
100 if (this->IsRange()) return this->AsRange()->Max(); | 107 if (this->IsRange()) return this->AsRange()->Max(); |
101 if (this->IsConstant()) return this->AsConstant()->Value()->Number(); | 108 if (this->IsConstant()) return this->AsConstant()->Value()->Number(); |
109 if (this->IsNumberConstant()) return this->AsNumberConstant()->Value(); | |
102 UNREACHABLE(); | 110 UNREACHABLE(); |
103 return 0; | 111 return 0; |
104 } | 112 } |
105 | 113 |
106 // ----------------------------------------------------------------------------- | 114 // ----------------------------------------------------------------------------- |
107 // Glb and lub computation. | 115 // Glb and lub computation. |
108 | 116 |
109 // The largest bitset subsumed by this type. | 117 // The largest bitset subsumed by this type. |
110 Type::bitset BitsetType::Glb(Type* type) { | 118 Type::bitset BitsetType::Glb(Type* type) { |
111 DisallowHeapAllocation no_allocation; | 119 DisallowHeapAllocation no_allocation; |
(...skipping 21 matching lines...) Loading... | |
133 // Take the representation from the first element, which is always | 141 // Take the representation from the first element, which is always |
134 // a bitset. | 142 // a bitset. |
135 int bitset = type->AsUnion()->Get(0)->BitsetLub(); | 143 int bitset = type->AsUnion()->Get(0)->BitsetLub(); |
136 for (int i = 0, n = type->AsUnion()->Length(); i < n; ++i) { | 144 for (int i = 0, n = type->AsUnion()->Length(); i < n; ++i) { |
137 // Other elements only contribute their semantic part. | 145 // Other elements only contribute their semantic part. |
138 bitset |= type->AsUnion()->Get(i)->BitsetLub(); | 146 bitset |= type->AsUnion()->Get(i)->BitsetLub(); |
139 } | 147 } |
140 return bitset; | 148 return bitset; |
141 } | 149 } |
142 if (type->IsConstant()) return type->AsConstant()->Lub(); | 150 if (type->IsConstant()) return type->AsConstant()->Lub(); |
151 if (type->IsNumberConstant()) return type->AsNumberConstant()->Lub(); | |
143 if (type->IsRange()) return type->AsRange()->Lub(); | 152 if (type->IsRange()) return type->AsRange()->Lub(); |
144 if (type->IsTuple()) return kOtherInternal; | 153 if (type->IsTuple()) return kOtherInternal; |
145 UNREACHABLE(); | 154 UNREACHABLE(); |
146 return kNone; | 155 return kNone; |
147 } | 156 } |
148 | 157 |
149 Type::bitset BitsetType::Lub(i::Map* map) { | 158 Type::bitset BitsetType::Lub(i::Map* map) { |
150 DisallowHeapAllocation no_allocation; | 159 DisallowHeapAllocation no_allocation; |
151 switch (map->instance_type()) { | 160 switch (map->instance_type()) { |
152 case STRING_TYPE: | 161 case STRING_TYPE: |
(...skipping 239 matching lines...) Loading... | |
392 | 401 |
393 // ----------------------------------------------------------------------------- | 402 // ----------------------------------------------------------------------------- |
394 // Predicates. | 403 // Predicates. |
395 | 404 |
396 bool Type::SimplyEquals(Type* that) { | 405 bool Type::SimplyEquals(Type* that) { |
397 DisallowHeapAllocation no_allocation; | 406 DisallowHeapAllocation no_allocation; |
398 if (this->IsConstant()) { | 407 if (this->IsConstant()) { |
399 return that->IsConstant() && | 408 return that->IsConstant() && |
400 *this->AsConstant()->Value() == *that->AsConstant()->Value(); | 409 *this->AsConstant()->Value() == *that->AsConstant()->Value(); |
401 } | 410 } |
411 if (this->IsNumberConstant()) { | |
412 return that->IsNumberConstant() && | |
413 this->AsNumberConstant()->Value() == | |
414 that->AsNumberConstant()->Value(); | |
415 } | |
402 if (this->IsTuple()) { | 416 if (this->IsTuple()) { |
403 if (!that->IsTuple()) return false; | 417 if (!that->IsTuple()) return false; |
404 TupleType* this_tuple = this->AsTuple(); | 418 TupleType* this_tuple = this->AsTuple(); |
405 TupleType* that_tuple = that->AsTuple(); | 419 TupleType* that_tuple = that->AsTuple(); |
406 if (this_tuple->Arity() != that_tuple->Arity()) { | 420 if (this_tuple->Arity() != that_tuple->Arity()) { |
407 return false; | 421 return false; |
408 } | 422 } |
409 for (int i = 0, n = this_tuple->Arity(); i < n; ++i) { | 423 for (int i = 0, n = this_tuple->Arity(); i < n; ++i) { |
410 if (!this_tuple->Element(i)->Equals(that_tuple->Element(i))) return false; | 424 if (!this_tuple->Element(i)->Equals(that_tuple->Element(i))) return false; |
411 } | 425 } |
(...skipping 65 matching lines...) Loading... | |
477 } | 491 } |
478 return false; | 492 return false; |
479 } | 493 } |
480 | 494 |
481 if (this->IsBitset() && that->IsBitset()) return true; | 495 if (this->IsBitset() && that->IsBitset()) return true; |
482 | 496 |
483 if (this->IsRange()) { | 497 if (this->IsRange()) { |
484 if (that->IsConstant()) { | 498 if (that->IsConstant()) { |
485 return Contains(this->AsRange(), that->AsConstant()); | 499 return Contains(this->AsRange(), that->AsConstant()); |
486 } | 500 } |
501 if (that->IsNumberConstant()) { | |
502 return Contains(this->AsRange(), that->AsNumberConstant()); | |
503 } | |
487 if (that->IsRange()) { | 504 if (that->IsRange()) { |
488 return Overlap(this->AsRange(), that->AsRange()); | 505 return Overlap(this->AsRange(), that->AsRange()); |
489 } | 506 } |
490 if (that->IsBitset()) { | 507 if (that->IsBitset()) { |
491 bitset number_bits = BitsetType::NumberBits(that->AsBitset()); | 508 bitset number_bits = BitsetType::NumberBits(that->AsBitset()); |
492 if (number_bits == BitsetType::kNone) { | 509 if (number_bits == BitsetType::kNone) { |
493 return false; | 510 return false; |
494 } | 511 } |
495 double min = std::max(BitsetType::Min(number_bits), this->Min()); | 512 double min = std::max(BitsetType::Min(number_bits), this->Min()); |
496 double max = std::min(BitsetType::Max(number_bits), this->Max()); | 513 double max = std::min(BitsetType::Max(number_bits), this->Max()); |
(...skipping 172 matching lines...) Loading... | |
669 RangeType::Limits lim = IntersectRangeAndBitset(lhs, rhs, zone); | 686 RangeType::Limits lim = IntersectRangeAndBitset(lhs, rhs, zone); |
670 | 687 |
671 if (!lim.IsEmpty()) { | 688 if (!lim.IsEmpty()) { |
672 *lims = RangeType::Limits::Union(lim, *lims); | 689 *lims = RangeType::Limits::Union(lim, *lims); |
673 } | 690 } |
674 return size; | 691 return size; |
675 } | 692 } |
676 if (rhs->IsConstant() && Contains(lhs->AsRange(), rhs->AsConstant())) { | 693 if (rhs->IsConstant() && Contains(lhs->AsRange(), rhs->AsConstant())) { |
677 return AddToUnion(rhs, result, size, zone); | 694 return AddToUnion(rhs, result, size, zone); |
678 } | 695 } |
696 if (rhs->IsNumberConstant() && | |
697 Contains(lhs->AsRange(), rhs->AsNumberConstant())) { | |
698 return AddToUnion(rhs, result, size, zone); | |
mvstanton
2016/09/28 14:47:44
leave this out, because a range cannot contain a n
mvstanton
2016/10/04 11:55:55
Done.
| |
699 } | |
679 if (rhs->IsRange()) { | 700 if (rhs->IsRange()) { |
680 RangeType::Limits lim = RangeType::Limits::Intersect( | 701 RangeType::Limits lim = RangeType::Limits::Intersect( |
681 RangeType::Limits(lhs->AsRange()), RangeType::Limits(rhs->AsRange())); | 702 RangeType::Limits(lhs->AsRange()), RangeType::Limits(rhs->AsRange())); |
682 if (!lim.IsEmpty()) { | 703 if (!lim.IsEmpty()) { |
683 *lims = RangeType::Limits::Union(lim, *lims); | 704 *lims = RangeType::Limits::Union(lim, *lims); |
684 } | 705 } |
685 } | 706 } |
686 return size; | 707 return size; |
687 } | 708 } |
688 if (rhs->IsRange()) { | 709 if (rhs->IsRange()) { |
(...skipping 47 matching lines...) Loading... | |
736 | 757 |
737 if (bitset_min < range_min) { | 758 if (bitset_min < range_min) { |
738 range_min = bitset_min; | 759 range_min = bitset_min; |
739 } | 760 } |
740 if (bitset_max > range_max) { | 761 if (bitset_max > range_max) { |
741 range_max = bitset_max; | 762 range_max = bitset_max; |
742 } | 763 } |
743 return RangeType::New(range_min, range_max, zone); | 764 return RangeType::New(range_min, range_max, zone); |
744 } | 765 } |
745 | 766 |
767 Type* Type::NewConstant(i::Handle<i::Object> value, Zone* zone) { | |
768 if (IsInteger(*value)) { | |
769 double v = value->IsSmi() ? Smi::cast(*value)->value() | |
770 : HeapNumber::cast(*value)->value(); | |
771 return Range(v, v, zone); | |
772 } else if (value->IsHeapNumber()) { | |
773 double v = HeapNumber::cast(*value)->value(); | |
774 if (NumberConstantType::IsNumberConstant(v)) { | |
775 return NumberConstant(v, zone); | |
776 } | |
777 } | |
778 return Constant(value, zone); | |
mvstanton
2016/09/28 14:47:44
drive by comment - shouldn't we canonicalize NaN a
mvstanton
2016/10/04 11:55:55
Done.
| |
779 } | |
mvstanton
2016/09/28 14:47:44
Also, a separate CL to land after would make sure
| |
780 | |
746 Type* Type::Union(Type* type1, Type* type2, Zone* zone) { | 781 Type* Type::Union(Type* type1, Type* type2, Zone* zone) { |
747 // Fast case: bit sets. | 782 // Fast case: bit sets. |
748 if (type1->IsBitset() && type2->IsBitset()) { | 783 if (type1->IsBitset() && type2->IsBitset()) { |
749 return BitsetType::New(type1->AsBitset() | type2->AsBitset()); | 784 return BitsetType::New(type1->AsBitset() | type2->AsBitset()); |
750 } | 785 } |
751 | 786 |
752 // Fast case: top or bottom types. | 787 // Fast case: top or bottom types. |
753 if (type1->IsAny() || type2->IsNone()) return type1; | 788 if (type1->IsAny() || type2->IsNone()) return type1; |
754 if (type2->IsAny() || type1->IsNone()) return type2; | 789 if (type2->IsAny() || type1->IsNone()) return type2; |
755 | 790 |
(...skipping 70 matching lines...) Loading... | |
826 if (unioned->Get(1)->IsRange()) { | 861 if (unioned->Get(1)->IsRange()) { |
827 return RangeType::New(unioned->Get(1)->AsRange()->Min(), | 862 return RangeType::New(unioned->Get(1)->AsRange()->Min(), |
828 unioned->Get(1)->AsRange()->Max(), zone); | 863 unioned->Get(1)->AsRange()->Max(), zone); |
829 } | 864 } |
830 } | 865 } |
831 unioned->Shrink(size); | 866 unioned->Shrink(size); |
832 SLOW_DCHECK(unioned->Wellformed()); | 867 SLOW_DCHECK(unioned->Wellformed()); |
833 return union_type; | 868 return union_type; |
834 } | 869 } |
835 | 870 |
836 // ----------------------------------------------------------------------------- | |
837 // Iteration. | |
838 | |
839 int Type::NumConstants() { | 871 int Type::NumConstants() { |
840 DisallowHeapAllocation no_allocation; | 872 DisallowHeapAllocation no_allocation; |
841 if (this->IsConstant()) { | 873 if (this->IsConstant() || this->IsNumberConstant()) { |
842 return 1; | 874 return 1; |
843 } else if (this->IsUnion()) { | 875 } else if (this->IsUnion()) { |
844 int result = 0; | 876 int result = 0; |
845 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { | 877 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { |
846 if (this->AsUnion()->Get(i)->IsConstant()) ++result; | 878 if (this->AsUnion()->Get(i)->IsConstant()) ++result; |
847 } | 879 } |
848 return result; | 880 return result; |
849 } else { | 881 } else { |
850 return 0; | 882 return 0; |
851 } | 883 } |
(...skipping 48 matching lines...) Loading... | |
900 DCHECK(bits == 0); | 932 DCHECK(bits == 0); |
901 os << ")"; | 933 os << ")"; |
902 } | 934 } |
903 | 935 |
904 void Type::PrintTo(std::ostream& os) { | 936 void Type::PrintTo(std::ostream& os) { |
905 DisallowHeapAllocation no_allocation; | 937 DisallowHeapAllocation no_allocation; |
906 if (this->IsBitset()) { | 938 if (this->IsBitset()) { |
907 BitsetType::Print(os, this->AsBitset()); | 939 BitsetType::Print(os, this->AsBitset()); |
908 } else if (this->IsConstant()) { | 940 } else if (this->IsConstant()) { |
909 os << "Constant(" << Brief(*this->AsConstant()->Value()) << ")"; | 941 os << "Constant(" << Brief(*this->AsConstant()->Value()) << ")"; |
942 } else if (this->IsNumberConstant()) { | |
943 os << "NumberConstant(" << this->AsNumberConstant()->Value() << ")"; | |
910 } else if (this->IsRange()) { | 944 } else if (this->IsRange()) { |
911 std::ostream::fmtflags saved_flags = os.setf(std::ios::fixed); | 945 std::ostream::fmtflags saved_flags = os.setf(std::ios::fixed); |
912 std::streamsize saved_precision = os.precision(0); | 946 std::streamsize saved_precision = os.precision(0); |
913 os << "Range(" << this->AsRange()->Min() << ", " << this->AsRange()->Max() | 947 os << "Range(" << this->AsRange()->Min() << ", " << this->AsRange()->Max() |
914 << ")"; | 948 << ")"; |
915 os.flags(saved_flags); | 949 os.flags(saved_flags); |
916 os.precision(saved_precision); | 950 os.precision(saved_precision); |
917 } else if (this->IsUnion()) { | 951 } else if (this->IsUnion()) { |
918 os << "("; | 952 os << "("; |
919 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { | 953 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { |
(...skipping 32 matching lines...) Loading... | |
952 return i::SmiValuesAre31Bits() ? kSigned31 : kSigned32; | 986 return i::SmiValuesAre31Bits() ? kSigned31 : kSigned32; |
953 } | 987 } |
954 | 988 |
955 BitsetType::bitset BitsetType::UnsignedSmall() { | 989 BitsetType::bitset BitsetType::UnsignedSmall() { |
956 return i::SmiValuesAre31Bits() ? kUnsigned30 : kUnsigned31; | 990 return i::SmiValuesAre31Bits() ? kUnsigned30 : kUnsigned31; |
957 } | 991 } |
958 | 992 |
959 } // namespace compiler | 993 } // namespace compiler |
960 } // namespace internal | 994 } // namespace internal |
961 } // namespace v8 | 995 } // namespace v8 |
OLD | NEW |