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