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/types.h" | 7 #include "src/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 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
137 if (type->IsUnion()) { | 137 if (type->IsUnion()) { |
138 // Take the representation from the first element, which is always | 138 // Take the representation from the first element, which is always |
139 // a bitset. | 139 // a bitset. |
140 int bitset = type->AsUnion()->Get(0)->BitsetLub(); | 140 int bitset = type->AsUnion()->Get(0)->BitsetLub(); |
141 for (int i = 0, n = type->AsUnion()->Length(); i < n; ++i) { | 141 for (int i = 0, n = type->AsUnion()->Length(); i < n; ++i) { |
142 // Other elements only contribute their semantic part. | 142 // Other elements only contribute their semantic part. |
143 bitset |= SEMANTIC(type->AsUnion()->Get(i)->BitsetLub()); | 143 bitset |= SEMANTIC(type->AsUnion()->Get(i)->BitsetLub()); |
144 } | 144 } |
145 return bitset; | 145 return bitset; |
146 } | 146 } |
147 if (type->IsClass()) return type->AsClass()->Lub(); | |
148 if (type->IsConstant()) return type->AsConstant()->Lub(); | 147 if (type->IsConstant()) return type->AsConstant()->Lub(); |
149 if (type->IsRange()) return type->AsRange()->Lub(); | 148 if (type->IsRange()) return type->AsRange()->Lub(); |
150 if (type->IsContext()) return kOtherInternal & kTaggedPointer; | 149 if (type->IsContext()) return kOtherInternal & kTaggedPointer; |
151 if (type->IsArray()) return kOtherObject; | 150 if (type->IsArray()) return kOtherObject; |
152 if (type->IsFunction()) return kFunction; | 151 if (type->IsFunction()) return kFunction; |
153 if (type->IsTuple()) return kOtherInternal; | 152 if (type->IsTuple()) return kOtherInternal; |
154 UNREACHABLE(); | 153 UNREACHABLE(); |
155 return kNone; | 154 return kNone; |
156 } | 155 } |
157 | 156 |
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
402 if (mz) return 0; | 401 if (mz) return 0; |
403 return std::numeric_limits<double>::quiet_NaN(); | 402 return std::numeric_limits<double>::quiet_NaN(); |
404 } | 403 } |
405 | 404 |
406 | 405 |
407 // ----------------------------------------------------------------------------- | 406 // ----------------------------------------------------------------------------- |
408 // Predicates. | 407 // Predicates. |
409 | 408 |
410 bool Type::SimplyEquals(Type* that) { | 409 bool Type::SimplyEquals(Type* that) { |
411 DisallowHeapAllocation no_allocation; | 410 DisallowHeapAllocation no_allocation; |
412 if (this->IsClass()) { | |
413 return that->IsClass() | |
414 && *this->AsClass()->Map() == *that->AsClass()->Map(); | |
415 } | |
416 if (this->IsConstant()) { | 411 if (this->IsConstant()) { |
417 return that->IsConstant() | 412 return that->IsConstant() |
418 && *this->AsConstant()->Value() == *that->AsConstant()->Value(); | 413 && *this->AsConstant()->Value() == *that->AsConstant()->Value(); |
419 } | 414 } |
420 if (this->IsContext()) { | 415 if (this->IsContext()) { |
421 return that->IsContext() | 416 return that->IsContext() |
422 && this->AsContext()->Outer()->Equals(that->AsContext()->Outer()); | 417 && this->AsContext()->Outer()->Equals(that->AsContext()->Outer()); |
423 } | 418 } |
424 if (this->IsArray()) { | 419 if (this->IsArray()) { |
425 return that->IsArray() | 420 return that->IsArray() |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
517 if (that->IsRange()) { | 512 if (that->IsRange()) { |
518 return (this->IsRange() && Contains(that->AsRange(), this->AsRange())) || | 513 return (this->IsRange() && Contains(that->AsRange(), this->AsRange())) || |
519 (this->IsConstant() && | 514 (this->IsConstant() && |
520 Contains(that->AsRange(), this->AsConstant())); | 515 Contains(that->AsRange(), this->AsConstant())); |
521 } | 516 } |
522 if (this->IsRange()) return false; | 517 if (this->IsRange()) return false; |
523 | 518 |
524 return this->SimplyEquals(that); | 519 return this->SimplyEquals(that); |
525 } | 520 } |
526 | 521 |
527 // Most precise _current_ type of a value (usually its class). | |
528 Type* Type::NowOf(i::Object* value, Zone* zone) { | |
529 if (value->IsSmi() || | |
530 i::HeapObject::cast(value)->map()->instance_type() == HEAP_NUMBER_TYPE) { | |
531 return Of(value, zone); | |
532 } | |
533 return Class(i::handle(i::HeapObject::cast(value)->map()), zone); | |
534 } | |
535 | |
536 bool Type::NowContains(i::Object* value) { | |
537 DisallowHeapAllocation no_allocation; | |
538 if (this->IsAny()) return true; | |
539 if (value->IsHeapObject()) { | |
540 i::Map* map = i::HeapObject::cast(value)->map(); | |
541 for (Iterator<i::Map> it = this->Classes(); !it.Done(); it.Advance()) { | |
542 if (*it.Current() == map) return true; | |
543 } | |
544 } | |
545 return this->Contains(value); | |
546 } | |
547 | |
548 bool Type::NowIs(Type* that) { | |
549 DisallowHeapAllocation no_allocation; | |
550 | |
551 // TODO(rossberg): this is incorrect for | |
552 // Union(Constant(V), T)->NowIs(Class(M)) | |
553 // but fuzzing does not cover that! | |
554 if (this->IsConstant()) { | |
555 i::Object* object = *this->AsConstant()->Value(); | |
556 if (object->IsHeapObject()) { | |
557 i::Map* map = i::HeapObject::cast(object)->map(); | |
558 for (Iterator<i::Map> it = that->Classes(); !it.Done(); it.Advance()) { | |
559 if (*it.Current() == map) return true; | |
560 } | |
561 } | |
562 } | |
563 return this->Is(that); | |
564 } | |
565 | |
566 | |
567 // Check if [this] contains only (currently) stable classes. | |
568 bool Type::NowStable() { | |
569 DisallowHeapAllocation no_allocation; | |
570 return !this->IsClass() || this->AsClass()->Map()->is_stable(); | |
571 } | |
572 | |
573 | 522 |
574 // Check if [this] and [that] overlap. | 523 // Check if [this] and [that] overlap. |
575 bool Type::Maybe(Type* that) { | 524 bool Type::Maybe(Type* that) { |
576 DisallowHeapAllocation no_allocation; | 525 DisallowHeapAllocation no_allocation; |
577 | 526 |
578 // Take care of the representation part (and also approximate | 527 // Take care of the representation part (and also approximate |
579 // the semantic part). | 528 // the semantic part). |
580 if (!BitsetType::IsInhabited(this->BitsetLub() & that->BitsetLub())) | 529 if (!BitsetType::IsInhabited(this->BitsetLub() & that->BitsetLub())) |
581 return false; | 530 return false; |
582 | 531 |
(...skipping 17 matching lines...) Expand all Loading... |
600 if (this->SemanticMaybe(that->AsUnion()->Get(i))) return true; | 549 if (this->SemanticMaybe(that->AsUnion()->Get(i))) return true; |
601 } | 550 } |
602 return false; | 551 return false; |
603 } | 552 } |
604 | 553 |
605 if (!BitsetType::SemanticIsInhabited(this->BitsetLub() & that->BitsetLub())) | 554 if (!BitsetType::SemanticIsInhabited(this->BitsetLub() & that->BitsetLub())) |
606 return false; | 555 return false; |
607 | 556 |
608 if (this->IsBitset() && that->IsBitset()) return true; | 557 if (this->IsBitset() && that->IsBitset()) return true; |
609 | 558 |
610 if (this->IsClass() != that->IsClass()) return true; | |
611 | |
612 if (this->IsRange()) { | 559 if (this->IsRange()) { |
613 if (that->IsConstant()) { | 560 if (that->IsConstant()) { |
614 return Contains(this->AsRange(), that->AsConstant()); | 561 return Contains(this->AsRange(), that->AsConstant()); |
615 } | 562 } |
616 if (that->IsRange()) { | 563 if (that->IsRange()) { |
617 return Overlap(this->AsRange(), that->AsRange()); | 564 return Overlap(this->AsRange(), that->AsRange()); |
618 } | 565 } |
619 if (that->IsBitset()) { | 566 if (that->IsBitset()) { |
620 bitset number_bits = BitsetType::NumberBits(that->AsBitset()); | 567 bitset number_bits = BitsetType::NumberBits(that->AsBitset()); |
621 if (number_bits == BitsetType::kNone) { | 568 if (number_bits == BitsetType::kNone) { |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
823 | 770 |
824 if (lhs->IsRange()) { | 771 if (lhs->IsRange()) { |
825 if (rhs->IsBitset()) { | 772 if (rhs->IsBitset()) { |
826 RangeType::Limits lim = IntersectRangeAndBitset(lhs, rhs, zone); | 773 RangeType::Limits lim = IntersectRangeAndBitset(lhs, rhs, zone); |
827 | 774 |
828 if (!lim.IsEmpty()) { | 775 if (!lim.IsEmpty()) { |
829 *lims = RangeType::Limits::Union(lim, *lims); | 776 *lims = RangeType::Limits::Union(lim, *lims); |
830 } | 777 } |
831 return size; | 778 return size; |
832 } | 779 } |
833 if (rhs->IsClass()) { | |
834 *lims = | |
835 RangeType::Limits::Union(RangeType::Limits(lhs->AsRange()), *lims); | |
836 } | |
837 if (rhs->IsConstant() && Contains(lhs->AsRange(), rhs->AsConstant())) { | 780 if (rhs->IsConstant() && Contains(lhs->AsRange(), rhs->AsConstant())) { |
838 return AddToUnion(rhs, result, size, zone); | 781 return AddToUnion(rhs, result, size, zone); |
839 } | 782 } |
840 if (rhs->IsRange()) { | 783 if (rhs->IsRange()) { |
841 RangeType::Limits lim = RangeType::Limits::Intersect( | 784 RangeType::Limits lim = RangeType::Limits::Intersect( |
842 RangeType::Limits(lhs->AsRange()), RangeType::Limits(rhs->AsRange())); | 785 RangeType::Limits(lhs->AsRange()), RangeType::Limits(rhs->AsRange())); |
843 if (!lim.IsEmpty()) { | 786 if (!lim.IsEmpty()) { |
844 *lims = RangeType::Limits::Union(lim, *lims); | 787 *lims = RangeType::Limits::Union(lim, *lims); |
845 } | 788 } |
846 } | 789 } |
847 return size; | 790 return size; |
848 } | 791 } |
849 if (rhs->IsRange()) { | 792 if (rhs->IsRange()) { |
850 // This case is handled symmetrically above. | 793 // This case is handled symmetrically above. |
851 return IntersectAux(rhs, lhs, result, size, lims, zone); | 794 return IntersectAux(rhs, lhs, result, size, lims, zone); |
852 } | 795 } |
853 if (lhs->IsBitset() || rhs->IsBitset()) { | 796 if (lhs->IsBitset() || rhs->IsBitset()) { |
854 return AddToUnion(lhs->IsBitset() ? rhs : lhs, result, size, zone); | 797 return AddToUnion(lhs->IsBitset() ? rhs : lhs, result, size, zone); |
855 } | 798 } |
856 if (lhs->IsClass() != rhs->IsClass()) { | |
857 return AddToUnion(lhs->IsClass() ? rhs : lhs, result, size, zone); | |
858 } | |
859 if (lhs->SimplyEquals(rhs)) { | 799 if (lhs->SimplyEquals(rhs)) { |
860 return AddToUnion(lhs, result, size, zone); | 800 return AddToUnion(lhs, result, size, zone); |
861 } | 801 } |
862 return size; | 802 return size; |
863 } | 803 } |
864 | 804 |
865 | 805 |
866 // Make sure that we produce a well-formed range and bitset: | 806 // Make sure that we produce a well-formed range and bitset: |
867 // If the range is non-empty, the number bits in the bitset should be | 807 // If the range is non-empty, the number bits in the bitset should be |
868 // clear. Moreover, if we have a canonical range (such as Signed32), | 808 // clear. Moreover, if we have a canonical range (such as Signed32), |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1024 | 964 |
1025 // static | 965 // static |
1026 Type* Type::Semantic(Type* t, Zone* zone) { | 966 Type* Type::Semantic(Type* t, Zone* zone) { |
1027 return Intersect(t, BitsetType::New(BitsetType::kSemantic), zone); | 967 return Intersect(t, BitsetType::New(BitsetType::kSemantic), zone); |
1028 } | 968 } |
1029 | 969 |
1030 | 970 |
1031 // ----------------------------------------------------------------------------- | 971 // ----------------------------------------------------------------------------- |
1032 // Iteration. | 972 // Iteration. |
1033 | 973 |
1034 int Type::NumClasses() { | |
1035 DisallowHeapAllocation no_allocation; | |
1036 if (this->IsClass()) { | |
1037 return 1; | |
1038 } else if (this->IsUnion()) { | |
1039 int result = 0; | |
1040 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { | |
1041 if (this->AsUnion()->Get(i)->IsClass()) ++result; | |
1042 } | |
1043 return result; | |
1044 } else { | |
1045 return 0; | |
1046 } | |
1047 } | |
1048 | |
1049 int Type::NumConstants() { | 974 int Type::NumConstants() { |
1050 DisallowHeapAllocation no_allocation; | 975 DisallowHeapAllocation no_allocation; |
1051 if (this->IsConstant()) { | 976 if (this->IsConstant()) { |
1052 return 1; | 977 return 1; |
1053 } else if (this->IsUnion()) { | 978 } else if (this->IsUnion()) { |
1054 int result = 0; | 979 int result = 0; |
1055 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { | 980 for (int i = 0, n = this->AsUnion()->Length(); i < n; ++i) { |
1056 if (this->AsUnion()->Get(i)->IsConstant()) ++result; | 981 if (this->AsUnion()->Get(i)->IsConstant()) ++result; |
1057 } | 982 } |
1058 return result; | 983 return result; |
(...skipping 11 matching lines...) Expand all Loading... |
1070 | 995 |
1071 // C++ cannot specialise nested templates, so we have to go through this | 996 // C++ cannot specialise nested templates, so we have to go through this |
1072 // contortion with an auxiliary template to simulate it. | 997 // contortion with an auxiliary template to simulate it. |
1073 template <class T> | 998 template <class T> |
1074 struct TypeImplIteratorAux { | 999 struct TypeImplIteratorAux { |
1075 static bool matches(Type* type); | 1000 static bool matches(Type* type); |
1076 static i::Handle<T> current(Type* type); | 1001 static i::Handle<T> current(Type* type); |
1077 }; | 1002 }; |
1078 | 1003 |
1079 template <> | 1004 template <> |
1080 struct TypeImplIteratorAux<i::Map> { | |
1081 static bool matches(Type* type) { return type->IsClass(); } | |
1082 static i::Handle<i::Map> current(Type* type) { | |
1083 return type->AsClass()->Map(); | |
1084 } | |
1085 }; | |
1086 | |
1087 template <> | |
1088 struct TypeImplIteratorAux<i::Object> { | 1005 struct TypeImplIteratorAux<i::Object> { |
1089 static bool matches(Type* type) { return type->IsConstant(); } | 1006 static bool matches(Type* type) { return type->IsConstant(); } |
1090 static i::Handle<i::Object> current(Type* type) { | 1007 static i::Handle<i::Object> current(Type* type) { |
1091 return type->AsConstant()->Value(); | 1008 return type->AsConstant()->Value(); |
1092 } | 1009 } |
1093 }; | 1010 }; |
1094 | 1011 |
1095 template <class T> | 1012 template <class T> |
1096 bool Type::Iterator<T>::matches(Type* type) { | 1013 bool Type::Iterator<T>::matches(Type* type) { |
1097 return TypeImplIteratorAux<T>::matches(type); | 1014 return TypeImplIteratorAux<T>::matches(type); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1174 } | 1091 } |
1175 DCHECK(bits == 0); | 1092 DCHECK(bits == 0); |
1176 os << ")"; | 1093 os << ")"; |
1177 } | 1094 } |
1178 | 1095 |
1179 void Type::PrintTo(std::ostream& os, PrintDimension dim) { | 1096 void Type::PrintTo(std::ostream& os, PrintDimension dim) { |
1180 DisallowHeapAllocation no_allocation; | 1097 DisallowHeapAllocation no_allocation; |
1181 if (dim != REPRESENTATION_DIM) { | 1098 if (dim != REPRESENTATION_DIM) { |
1182 if (this->IsBitset()) { | 1099 if (this->IsBitset()) { |
1183 BitsetType::Print(os, SEMANTIC(this->AsBitset())); | 1100 BitsetType::Print(os, SEMANTIC(this->AsBitset())); |
1184 } else if (this->IsClass()) { | |
1185 os << "Class(" << static_cast<void*>(*this->AsClass()->Map()) << " < "; | |
1186 BitsetType::New(BitsetType::Lub(this))->PrintTo(os, dim); | |
1187 os << ")"; | |
1188 } else if (this->IsConstant()) { | 1101 } else if (this->IsConstant()) { |
1189 os << "Constant(" << Brief(*this->AsConstant()->Value()) << ")"; | 1102 os << "Constant(" << Brief(*this->AsConstant()->Value()) << ")"; |
1190 } else if (this->IsRange()) { | 1103 } else if (this->IsRange()) { |
1191 std::ostream::fmtflags saved_flags = os.setf(std::ios::fixed); | 1104 std::ostream::fmtflags saved_flags = os.setf(std::ios::fixed); |
1192 std::streamsize saved_precision = os.precision(0); | 1105 std::streamsize saved_precision = os.precision(0); |
1193 os << "Range(" << this->AsRange()->Min() << ", " << this->AsRange()->Max() | 1106 os << "Range(" << this->AsRange()->Min() << ", " << this->AsRange()->Max() |
1194 << ")"; | 1107 << ")"; |
1195 os.flags(saved_flags); | 1108 os.flags(saved_flags); |
1196 os.precision(saved_precision); | 1109 os.precision(saved_precision); |
1197 } else if (this->IsContext()) { | 1110 } else if (this->IsContext()) { |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1255 #endif | 1168 #endif |
1256 | 1169 |
1257 BitsetType::bitset BitsetType::SignedSmall() { | 1170 BitsetType::bitset BitsetType::SignedSmall() { |
1258 return i::SmiValuesAre31Bits() ? kSigned31 : kSigned32; | 1171 return i::SmiValuesAre31Bits() ? kSigned31 : kSigned32; |
1259 } | 1172 } |
1260 | 1173 |
1261 BitsetType::bitset BitsetType::UnsignedSmall() { | 1174 BitsetType::bitset BitsetType::UnsignedSmall() { |
1262 return i::SmiValuesAre31Bits() ? kUnsigned30 : kUnsigned31; | 1175 return i::SmiValuesAre31Bits() ? kUnsigned30 : kUnsigned31; |
1263 } | 1176 } |
1264 | 1177 |
1265 #define CONSTRUCT_SIMD_TYPE(NAME, Name, name, lane_count, lane_type) \ | |
1266 Type* Type::Name(Isolate* isolate, Zone* zone) { \ | |
1267 return Class(i::handle(isolate->heap()->name##_map()), zone); \ | |
1268 } | |
1269 SIMD128_TYPES(CONSTRUCT_SIMD_TYPE) | |
1270 #undef CONSTRUCT_SIMD_TYPE | |
1271 | |
1272 // ----------------------------------------------------------------------------- | 1178 // ----------------------------------------------------------------------------- |
1273 // Instantiations. | 1179 // Instantiations. |
1274 | 1180 |
1275 template class Type::Iterator<i::Map>; | |
1276 template class Type::Iterator<i::Object>; | 1181 template class Type::Iterator<i::Object>; |
1277 | 1182 |
1278 } // namespace internal | 1183 } // namespace internal |
1279 } // namespace v8 | 1184 } // namespace v8 |
OLD | NEW |