| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #include "src/arguments.h" | 7 #include "src/arguments.h" |
| 8 #include "src/conversions.h" | 8 #include "src/conversions.h" |
| 9 #include "src/elements.h" | 9 #include "src/elements.h" |
| 10 #include "src/messages.h" | 10 #include "src/messages.h" |
| (...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 541 // ... | 541 // ... |
| 542 // } | 542 // } |
| 543 // | 543 // |
| 544 // This is an example of the Curiously Recurring Template Pattern (see | 544 // This is an example of the Curiously Recurring Template Pattern (see |
| 545 // http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern). We use | 545 // http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern). We use |
| 546 // CRTP to guarantee aggressive compile time optimizations (i.e. inlining and | 546 // CRTP to guarantee aggressive compile time optimizations (i.e. inlining and |
| 547 // specialization of SomeElementsAccessor methods). | 547 // specialization of SomeElementsAccessor methods). |
| 548 template <typename ElementsAccessorSubclass, | 548 template <typename ElementsAccessorSubclass, |
| 549 typename ElementsTraitsParam> | 549 typename ElementsTraitsParam> |
| 550 class ElementsAccessorBase : public ElementsAccessor { | 550 class ElementsAccessorBase : public ElementsAccessor { |
| 551 protected: | 551 public: |
| 552 template <typename SloppyArgumentsElementsAccessorSubclass, | |
| 553 typename ArgumentsAccessor, typename KindTraits> | |
| 554 friend class SloppyArgumentsElementsAccessor; | |
| 555 explicit ElementsAccessorBase(const char* name) | 552 explicit ElementsAccessorBase(const char* name) |
| 556 : ElementsAccessor(name) { } | 553 : ElementsAccessor(name) { } |
| 557 | 554 |
| 558 typedef ElementsTraitsParam ElementsTraits; | 555 typedef ElementsTraitsParam ElementsTraits; |
| 559 typedef typename ElementsTraitsParam::BackingStore BackingStore; | 556 typedef typename ElementsTraitsParam::BackingStore BackingStore; |
| 560 | 557 |
| 561 static ElementsKind kind() { return ElementsTraits::Kind; } | 558 static ElementsKind kind() { return ElementsTraits::Kind; } |
| 562 | 559 |
| 563 static void ValidateContents(Handle<JSObject> holder, int length) { | 560 static void ValidateContents(Handle<JSObject> holder, int length) { |
| 564 } | 561 } |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 857 if (!value->IsTheHole() && !HasKey(to, value)) { | 854 if (!value->IsTheHole() && !HasKey(to, value)) { |
| 858 result->set(len0 + index, *value); | 855 result->set(len0 + index, *value); |
| 859 index++; | 856 index++; |
| 860 } | 857 } |
| 861 } | 858 } |
| 862 } | 859 } |
| 863 DCHECK(extra == index); | 860 DCHECK(extra == index); |
| 864 return result; | 861 return result; |
| 865 } | 862 } |
| 866 | 863 |
| 867 protected: | |
| 868 static uint32_t GetCapacityImpl(JSObject* holder, | 864 static uint32_t GetCapacityImpl(JSObject* holder, |
| 869 FixedArrayBase* backing_store) { | 865 FixedArrayBase* backing_store) { |
| 870 return backing_store->length(); | 866 return backing_store->length(); |
| 871 } | 867 } |
| 872 | 868 |
| 873 uint32_t GetCapacity(JSObject* holder, FixedArrayBase* backing_store) final { | 869 uint32_t GetCapacity(JSObject* holder, FixedArrayBase* backing_store) final { |
| 874 return ElementsAccessorSubclass::GetCapacityImpl(holder, backing_store); | 870 return ElementsAccessorSubclass::GetCapacityImpl(holder, backing_store); |
| 875 } | 871 } |
| 876 | 872 |
| 877 static bool HasIndexImpl(FixedArrayBase* backing_store, uint32_t index) { | 873 static bool HasIndexImpl(FixedArrayBase* backing_store, uint32_t index) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 917 virtual PropertyDetails GetDetails(FixedArrayBase* backing_store, | 913 virtual PropertyDetails GetDetails(FixedArrayBase* backing_store, |
| 918 uint32_t index) final { | 914 uint32_t index) final { |
| 919 return ElementsAccessorSubclass::GetDetailsImpl(backing_store, index); | 915 return ElementsAccessorSubclass::GetDetailsImpl(backing_store, index); |
| 920 } | 916 } |
| 921 | 917 |
| 922 private: | 918 private: |
| 923 DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase); | 919 DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase); |
| 924 }; | 920 }; |
| 925 | 921 |
| 926 | 922 |
| 927 class FastSloppyArgumentsElementsAccessor; | 923 class DictionaryElementsAccessor |
| 928 class FastHoleyObjectElementsAccessor; | 924 : public ElementsAccessorBase<DictionaryElementsAccessor, |
| 929 template <typename SloppyArgumentsElementsAccessorSubclass, | 925 ElementsKindTraits<DICTIONARY_ELEMENTS> > { |
| 930 typename ArgumentsAccessor, typename KindTraits> | 926 public: |
| 931 class SloppyArgumentsElementsAccessor; | 927 explicit DictionaryElementsAccessor(const char* name) |
| 928 : ElementsAccessorBase<DictionaryElementsAccessor, |
| 929 ElementsKindTraits<DICTIONARY_ELEMENTS> >(name) {} |
| 930 |
| 931 static void SetLengthImpl(Handle<JSArray> array, uint32_t length, |
| 932 Handle<FixedArrayBase> backing_store) { |
| 933 Handle<SeededNumberDictionary> dict = |
| 934 Handle<SeededNumberDictionary>::cast(backing_store); |
| 935 Isolate* isolate = array->GetIsolate(); |
| 936 int capacity = dict->Capacity(); |
| 937 uint32_t old_length = 0; |
| 938 CHECK(array->length()->ToArrayLength(&old_length)); |
| 939 if (length < old_length) { |
| 940 if (dict->requires_slow_elements()) { |
| 941 // Find last non-deletable element in range of elements to be |
| 942 // deleted and adjust range accordingly. |
| 943 for (int i = 0; i < capacity; i++) { |
| 944 DisallowHeapAllocation no_gc; |
| 945 Object* key = dict->KeyAt(i); |
| 946 if (key->IsNumber()) { |
| 947 uint32_t number = static_cast<uint32_t>(key->Number()); |
| 948 if (length <= number && number < old_length) { |
| 949 PropertyDetails details = dict->DetailsAt(i); |
| 950 if (!details.IsConfigurable()) length = number + 1; |
| 951 } |
| 952 } |
| 953 } |
| 954 } |
| 955 |
| 956 if (length == 0) { |
| 957 // Flush the backing store. |
| 958 JSObject::ResetElements(array); |
| 959 } else { |
| 960 DisallowHeapAllocation no_gc; |
| 961 // Remove elements that should be deleted. |
| 962 int removed_entries = 0; |
| 963 Handle<Object> the_hole_value = isolate->factory()->the_hole_value(); |
| 964 for (int i = 0; i < capacity; i++) { |
| 965 Object* key = dict->KeyAt(i); |
| 966 if (key->IsNumber()) { |
| 967 uint32_t number = static_cast<uint32_t>(key->Number()); |
| 968 if (length <= number && number < old_length) { |
| 969 dict->SetEntry(i, the_hole_value, the_hole_value); |
| 970 removed_entries++; |
| 971 } |
| 972 } |
| 973 } |
| 974 |
| 975 // Update the number of elements. |
| 976 dict->ElementsRemoved(removed_entries); |
| 977 } |
| 978 } |
| 979 |
| 980 Handle<Object> length_obj = isolate->factory()->NewNumberFromUint(length); |
| 981 array->set_length(*length_obj); |
| 982 } |
| 983 |
| 984 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, |
| 985 FixedArrayBase* to, ElementsKind from_kind, |
| 986 uint32_t to_start, int packed_size, |
| 987 int copy_size) { |
| 988 UNREACHABLE(); |
| 989 } |
| 990 |
| 991 |
| 992 static void DeleteCommon(Handle<JSObject> obj, uint32_t key, |
| 993 LanguageMode language_mode) { |
| 994 Isolate* isolate = obj->GetIsolate(); |
| 995 Handle<FixedArray> backing_store(FixedArray::cast(obj->elements()), |
| 996 isolate); |
| 997 bool is_arguments = obj->HasSloppyArgumentsElements(); |
| 998 if (is_arguments) { |
| 999 backing_store = handle(FixedArray::cast(backing_store->get(1)), isolate); |
| 1000 } |
| 1001 Handle<SeededNumberDictionary> dictionary = |
| 1002 Handle<SeededNumberDictionary>::cast(backing_store); |
| 1003 int entry = dictionary->FindEntry(key); |
| 1004 if (entry != SeededNumberDictionary::kNotFound) { |
| 1005 Handle<Object> result = |
| 1006 SeededNumberDictionary::DeleteProperty(dictionary, entry); |
| 1007 USE(result); |
| 1008 DCHECK(result->IsTrue()); |
| 1009 Handle<FixedArray> new_elements = |
| 1010 SeededNumberDictionary::Shrink(dictionary, key); |
| 1011 |
| 1012 if (is_arguments) { |
| 1013 FixedArray::cast(obj->elements())->set(1, *new_elements); |
| 1014 } else { |
| 1015 obj->set_elements(*new_elements); |
| 1016 } |
| 1017 } |
| 1018 } |
| 1019 |
| 1020 virtual void Delete(Handle<JSObject> obj, uint32_t key, |
| 1021 LanguageMode language_mode) final { |
| 1022 DeleteCommon(obj, key, language_mode); |
| 1023 } |
| 1024 |
| 1025 static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key, |
| 1026 Handle<FixedArrayBase> store) { |
| 1027 Handle<SeededNumberDictionary> backing_store = |
| 1028 Handle<SeededNumberDictionary>::cast(store); |
| 1029 Isolate* isolate = backing_store->GetIsolate(); |
| 1030 int entry = backing_store->FindEntry(key); |
| 1031 if (entry != SeededNumberDictionary::kNotFound) { |
| 1032 return handle(backing_store->ValueAt(entry), isolate); |
| 1033 } |
| 1034 return isolate->factory()->the_hole_value(); |
| 1035 } |
| 1036 |
| 1037 static void SetImpl(FixedArrayBase* store, uint32_t key, Object* value) { |
| 1038 SeededNumberDictionary* dictionary = SeededNumberDictionary::cast(store); |
| 1039 int entry = dictionary->FindEntry(key); |
| 1040 DCHECK_NE(SeededNumberDictionary::kNotFound, entry); |
| 1041 dictionary->ValueAtPut(entry, value); |
| 1042 } |
| 1043 |
| 1044 static void ReconfigureImpl(Handle<JSObject> object, |
| 1045 Handle<FixedArrayBase> store, uint32_t index, |
| 1046 Handle<Object> value, |
| 1047 PropertyAttributes attributes) { |
| 1048 SeededNumberDictionary* dictionary = SeededNumberDictionary::cast(*store); |
| 1049 if (attributes != NONE) dictionary->set_requires_slow_elements(); |
| 1050 dictionary->ValueAtPut(index, *value); |
| 1051 PropertyDetails details = dictionary->DetailsAt(index); |
| 1052 details = PropertyDetails(attributes, DATA, details.dictionary_index(), |
| 1053 PropertyCellType::kNoCell); |
| 1054 dictionary->DetailsAtPut(index, details); |
| 1055 } |
| 1056 |
| 1057 static void AddImpl(Handle<JSObject> object, uint32_t index, |
| 1058 Handle<Object> value, PropertyAttributes attributes, |
| 1059 uint32_t new_capacity) { |
| 1060 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); |
| 1061 Handle<SeededNumberDictionary> dictionary = |
| 1062 object->HasFastElements() |
| 1063 ? JSObject::NormalizeElements(object) |
| 1064 : handle(SeededNumberDictionary::cast(object->elements())); |
| 1065 Handle<SeededNumberDictionary> new_dictionary = |
| 1066 SeededNumberDictionary::AddNumberEntry(dictionary, index, value, |
| 1067 details); |
| 1068 if (attributes != NONE) new_dictionary->set_requires_slow_elements(); |
| 1069 if (dictionary.is_identical_to(new_dictionary)) return; |
| 1070 object->set_elements(*new_dictionary); |
| 1071 } |
| 1072 |
| 1073 static MaybeHandle<AccessorPair> GetAccessorPairImpl( |
| 1074 Handle<JSObject> obj, uint32_t key, Handle<FixedArrayBase> store) { |
| 1075 Handle<SeededNumberDictionary> backing_store = |
| 1076 Handle<SeededNumberDictionary>::cast(store); |
| 1077 int entry = backing_store->FindEntry(key); |
| 1078 if (entry != SeededNumberDictionary::kNotFound && |
| 1079 backing_store->DetailsAt(entry).type() == ACCESSOR_CONSTANT && |
| 1080 backing_store->ValueAt(entry)->IsAccessorPair()) { |
| 1081 return handle(AccessorPair::cast(backing_store->ValueAt(entry))); |
| 1082 } |
| 1083 return MaybeHandle<AccessorPair>(); |
| 1084 } |
| 1085 |
| 1086 static bool HasIndexImpl(FixedArrayBase* store, uint32_t index) { |
| 1087 DisallowHeapAllocation no_gc; |
| 1088 SeededNumberDictionary* dict = SeededNumberDictionary::cast(store); |
| 1089 Object* key = dict->KeyAt(index); |
| 1090 return !key->IsTheHole(); |
| 1091 } |
| 1092 |
| 1093 static uint32_t GetKeyForIndexImpl(FixedArrayBase* store, uint32_t index) { |
| 1094 DisallowHeapAllocation no_gc; |
| 1095 SeededNumberDictionary* dict = SeededNumberDictionary::cast(store); |
| 1096 uint32_t result = 0; |
| 1097 CHECK(dict->KeyAt(index)->ToArrayIndex(&result)); |
| 1098 return result; |
| 1099 } |
| 1100 |
| 1101 static uint32_t GetIndexForKeyImpl(JSObject* holder, FixedArrayBase* store, |
| 1102 uint32_t key) { |
| 1103 DisallowHeapAllocation no_gc; |
| 1104 SeededNumberDictionary* dict = SeededNumberDictionary::cast(store); |
| 1105 int entry = dict->FindEntry(key); |
| 1106 return entry == SeededNumberDictionary::kNotFound |
| 1107 ? kMaxUInt32 |
| 1108 : static_cast<uint32_t>(entry); |
| 1109 } |
| 1110 |
| 1111 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, |
| 1112 uint32_t index) { |
| 1113 return SeededNumberDictionary::cast(backing_store)->DetailsAt(index); |
| 1114 } |
| 1115 }; |
| 1116 |
| 932 | 1117 |
| 933 // Super class for all fast element arrays. | 1118 // Super class for all fast element arrays. |
| 934 template<typename FastElementsAccessorSubclass, | 1119 template<typename FastElementsAccessorSubclass, |
| 935 typename KindTraits> | 1120 typename KindTraits> |
| 936 class FastElementsAccessor | 1121 class FastElementsAccessor |
| 937 : public ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits> { | 1122 : public ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits> { |
| 938 public: | 1123 public: |
| 939 explicit FastElementsAccessor(const char* name) | 1124 explicit FastElementsAccessor(const char* name) |
| 940 : ElementsAccessorBase<FastElementsAccessorSubclass, | 1125 : ElementsAccessorBase<FastElementsAccessorSubclass, |
| 941 KindTraits>(name) {} | 1126 KindTraits>(name) {} |
| 942 | 1127 |
| 943 protected: | |
| 944 friend class ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits>; | |
| 945 friend class SloppyArgumentsElementsAccessor< | |
| 946 FastSloppyArgumentsElementsAccessor, FastHoleyObjectElementsAccessor, | |
| 947 ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >; | |
| 948 | |
| 949 typedef typename KindTraits::BackingStore BackingStore; | 1128 typedef typename KindTraits::BackingStore BackingStore; |
| 950 | 1129 |
| 951 static void DeleteCommon(Handle<JSObject> obj, uint32_t key, | 1130 static void DeleteCommon(Handle<JSObject> obj, uint32_t key, |
| 952 LanguageMode language_mode) { | 1131 LanguageMode language_mode) { |
| 953 DCHECK(obj->HasFastSmiOrObjectElements() || | 1132 DCHECK(obj->HasFastSmiOrObjectElements() || |
| 954 obj->HasFastDoubleElements() || | 1133 obj->HasFastDoubleElements() || |
| 955 obj->HasFastArgumentsElements()); | 1134 obj->HasFastArgumentsElements()); |
| 956 Isolate* isolate = obj->GetIsolate(); | 1135 Isolate* isolate = obj->GetIsolate(); |
| 957 Heap* heap = obj->GetHeap(); | 1136 Heap* heap = obj->GetHeap(); |
| 958 Handle<FixedArrayBase> elements(obj->elements()); | 1137 Handle<FixedArrayBase> elements(obj->elements()); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1004 } | 1183 } |
| 1005 } | 1184 } |
| 1006 | 1185 |
| 1007 static void ReconfigureImpl(Handle<JSObject> object, | 1186 static void ReconfigureImpl(Handle<JSObject> object, |
| 1008 Handle<FixedArrayBase> store, uint32_t index, | 1187 Handle<FixedArrayBase> store, uint32_t index, |
| 1009 Handle<Object> value, | 1188 Handle<Object> value, |
| 1010 PropertyAttributes attributes) { | 1189 PropertyAttributes attributes) { |
| 1011 Handle<SeededNumberDictionary> dictionary = | 1190 Handle<SeededNumberDictionary> dictionary = |
| 1012 JSObject::NormalizeElements(object); | 1191 JSObject::NormalizeElements(object); |
| 1013 index = dictionary->FindEntry(index); | 1192 index = dictionary->FindEntry(index); |
| 1014 object->GetElementsAccessor()->Reconfigure(object, dictionary, index, value, | 1193 DictionaryElementsAccessor::ReconfigureImpl(object, dictionary, index, |
| 1015 attributes); | 1194 value, attributes); |
| 1016 } | 1195 } |
| 1017 | 1196 |
| 1018 static void AddImpl(Handle<JSObject> object, uint32_t index, | 1197 static void AddImpl(Handle<JSObject> object, uint32_t index, |
| 1019 Handle<Object> value, PropertyAttributes attributes, | 1198 Handle<Object> value, PropertyAttributes attributes, |
| 1020 uint32_t new_capacity) { | 1199 uint32_t new_capacity) { |
| 1021 DCHECK_EQ(NONE, attributes); | 1200 DCHECK_EQ(NONE, attributes); |
| 1022 ElementsKind from_kind = object->GetElementsKind(); | 1201 ElementsKind from_kind = object->GetElementsKind(); |
| 1023 ElementsKind to_kind = FastElementsAccessorSubclass::kind(); | 1202 ElementsKind to_kind = FastElementsAccessorSubclass::kind(); |
| 1024 if (IsDictionaryElementsKind(from_kind) || | 1203 if (IsDictionaryElementsKind(from_kind) || |
| 1025 IsFastDoubleElementsKind(from_kind) != | 1204 IsFastDoubleElementsKind(from_kind) != |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1179 | 1358 |
| 1180 template<typename FastElementsAccessorSubclass, | 1359 template<typename FastElementsAccessorSubclass, |
| 1181 typename KindTraits> | 1360 typename KindTraits> |
| 1182 class FastDoubleElementsAccessor | 1361 class FastDoubleElementsAccessor |
| 1183 : public FastElementsAccessor<FastElementsAccessorSubclass, KindTraits> { | 1362 : public FastElementsAccessor<FastElementsAccessorSubclass, KindTraits> { |
| 1184 public: | 1363 public: |
| 1185 explicit FastDoubleElementsAccessor(const char* name) | 1364 explicit FastDoubleElementsAccessor(const char* name) |
| 1186 : FastElementsAccessor<FastElementsAccessorSubclass, | 1365 : FastElementsAccessor<FastElementsAccessorSubclass, |
| 1187 KindTraits>(name) {} | 1366 KindTraits>(name) {} |
| 1188 | 1367 |
| 1189 protected: | |
| 1190 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, | 1368 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, |
| 1191 FixedArrayBase* to, ElementsKind from_kind, | 1369 FixedArrayBase* to, ElementsKind from_kind, |
| 1192 uint32_t to_start, int packed_size, | 1370 uint32_t to_start, int packed_size, |
| 1193 int copy_size) { | 1371 int copy_size) { |
| 1194 DisallowHeapAllocation no_allocation; | 1372 DisallowHeapAllocation no_allocation; |
| 1195 switch (from_kind) { | 1373 switch (from_kind) { |
| 1196 case FAST_SMI_ELEMENTS: | 1374 case FAST_SMI_ELEMENTS: |
| 1197 CopyPackedSmiToDoubleElements(from, from_start, to, to_start, | 1375 CopyPackedSmiToDoubleElements(from, from_start, to, to_start, |
| 1198 packed_size, copy_size); | 1376 packed_size, copy_size); |
| 1199 break; | 1377 break; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 1225 } | 1403 } |
| 1226 } | 1404 } |
| 1227 }; | 1405 }; |
| 1228 | 1406 |
| 1229 | 1407 |
| 1230 class FastPackedDoubleElementsAccessor | 1408 class FastPackedDoubleElementsAccessor |
| 1231 : public FastDoubleElementsAccessor< | 1409 : public FastDoubleElementsAccessor< |
| 1232 FastPackedDoubleElementsAccessor, | 1410 FastPackedDoubleElementsAccessor, |
| 1233 ElementsKindTraits<FAST_DOUBLE_ELEMENTS> > { | 1411 ElementsKindTraits<FAST_DOUBLE_ELEMENTS> > { |
| 1234 public: | 1412 public: |
| 1235 friend class ElementsAccessorBase<FastPackedDoubleElementsAccessor, | |
| 1236 ElementsKindTraits<FAST_DOUBLE_ELEMENTS> >; | |
| 1237 explicit FastPackedDoubleElementsAccessor(const char* name) | 1413 explicit FastPackedDoubleElementsAccessor(const char* name) |
| 1238 : FastDoubleElementsAccessor< | 1414 : FastDoubleElementsAccessor< |
| 1239 FastPackedDoubleElementsAccessor, | 1415 FastPackedDoubleElementsAccessor, |
| 1240 ElementsKindTraits<FAST_DOUBLE_ELEMENTS> >(name) {} | 1416 ElementsKindTraits<FAST_DOUBLE_ELEMENTS> >(name) {} |
| 1241 }; | 1417 }; |
| 1242 | 1418 |
| 1243 | 1419 |
| 1244 class FastHoleyDoubleElementsAccessor | 1420 class FastHoleyDoubleElementsAccessor |
| 1245 : public FastDoubleElementsAccessor< | 1421 : public FastDoubleElementsAccessor< |
| 1246 FastHoleyDoubleElementsAccessor, | 1422 FastHoleyDoubleElementsAccessor, |
| 1247 ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> > { | 1423 ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> > { |
| 1248 public: | 1424 public: |
| 1249 friend class ElementsAccessorBase< | |
| 1250 FastHoleyDoubleElementsAccessor, | |
| 1251 ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> >; | |
| 1252 explicit FastHoleyDoubleElementsAccessor(const char* name) | 1425 explicit FastHoleyDoubleElementsAccessor(const char* name) |
| 1253 : FastDoubleElementsAccessor< | 1426 : FastDoubleElementsAccessor< |
| 1254 FastHoleyDoubleElementsAccessor, | 1427 FastHoleyDoubleElementsAccessor, |
| 1255 ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> >(name) {} | 1428 ElementsKindTraits<FAST_HOLEY_DOUBLE_ELEMENTS> >(name) {} |
| 1256 }; | 1429 }; |
| 1257 | 1430 |
| 1258 | 1431 |
| 1259 // Super class for all external element arrays. | 1432 // Super class for all external element arrays. |
| 1260 template<ElementsKind Kind> | 1433 template<ElementsKind Kind> |
| 1261 class TypedElementsAccessor | 1434 class TypedElementsAccessor |
| 1262 : public ElementsAccessorBase<TypedElementsAccessor<Kind>, | 1435 : public ElementsAccessorBase<TypedElementsAccessor<Kind>, |
| 1263 ElementsKindTraits<Kind> > { | 1436 ElementsKindTraits<Kind> > { |
| 1264 public: | 1437 public: |
| 1265 explicit TypedElementsAccessor(const char* name) | 1438 explicit TypedElementsAccessor(const char* name) |
| 1266 : ElementsAccessorBase<AccessorClass, | 1439 : ElementsAccessorBase<AccessorClass, |
| 1267 ElementsKindTraits<Kind> >(name) {} | 1440 ElementsKindTraits<Kind> >(name) {} |
| 1268 | 1441 |
| 1269 protected: | |
| 1270 typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore; | 1442 typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore; |
| 1271 typedef TypedElementsAccessor<Kind> AccessorClass; | 1443 typedef TypedElementsAccessor<Kind> AccessorClass; |
| 1272 | 1444 |
| 1273 friend class ElementsAccessorBase<AccessorClass, | |
| 1274 ElementsKindTraits<Kind> >; | |
| 1275 | |
| 1276 static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key, | 1445 static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key, |
| 1277 Handle<FixedArrayBase> backing_store) { | 1446 Handle<FixedArrayBase> backing_store) { |
| 1278 if (key < AccessorClass::GetCapacityImpl(*obj, *backing_store)) { | 1447 if (key < AccessorClass::GetCapacityImpl(*obj, *backing_store)) { |
| 1279 return BackingStore::get(Handle<BackingStore>::cast(backing_store), key); | 1448 return BackingStore::get(Handle<BackingStore>::cast(backing_store), key); |
| 1280 } else { | 1449 } else { |
| 1281 return backing_store->GetIsolate()->factory()->undefined_value(); | 1450 return backing_store->GetIsolate()->factory()->undefined_value(); |
| 1282 } | 1451 } |
| 1283 } | 1452 } |
| 1284 | 1453 |
| 1285 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, | 1454 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1324 #undef EXTERNAL_ELEMENTS_ACCESSOR | 1493 #undef EXTERNAL_ELEMENTS_ACCESSOR |
| 1325 | 1494 |
| 1326 #define FIXED_ELEMENTS_ACCESSOR(Type, type, TYPE, ctype, size) \ | 1495 #define FIXED_ELEMENTS_ACCESSOR(Type, type, TYPE, ctype, size) \ |
| 1327 typedef TypedElementsAccessor<TYPE##_ELEMENTS > \ | 1496 typedef TypedElementsAccessor<TYPE##_ELEMENTS > \ |
| 1328 Fixed##Type##ElementsAccessor; | 1497 Fixed##Type##ElementsAccessor; |
| 1329 | 1498 |
| 1330 TYPED_ARRAYS(FIXED_ELEMENTS_ACCESSOR) | 1499 TYPED_ARRAYS(FIXED_ELEMENTS_ACCESSOR) |
| 1331 #undef FIXED_ELEMENTS_ACCESSOR | 1500 #undef FIXED_ELEMENTS_ACCESSOR |
| 1332 | 1501 |
| 1333 | 1502 |
| 1334 class SlowSloppyArgumentsElementsAccessor; | |
| 1335 | |
| 1336 | |
| 1337 class DictionaryElementsAccessor | |
| 1338 : public ElementsAccessorBase<DictionaryElementsAccessor, | |
| 1339 ElementsKindTraits<DICTIONARY_ELEMENTS> > { | |
| 1340 public: | |
| 1341 explicit DictionaryElementsAccessor(const char* name) | |
| 1342 : ElementsAccessorBase<DictionaryElementsAccessor, | |
| 1343 ElementsKindTraits<DICTIONARY_ELEMENTS> >(name) {} | |
| 1344 | |
| 1345 static void SetLengthImpl(Handle<JSArray> array, uint32_t length, | |
| 1346 Handle<FixedArrayBase> backing_store) { | |
| 1347 Handle<SeededNumberDictionary> dict = | |
| 1348 Handle<SeededNumberDictionary>::cast(backing_store); | |
| 1349 Isolate* isolate = array->GetIsolate(); | |
| 1350 int capacity = dict->Capacity(); | |
| 1351 uint32_t old_length = 0; | |
| 1352 CHECK(array->length()->ToArrayLength(&old_length)); | |
| 1353 if (length < old_length) { | |
| 1354 if (dict->requires_slow_elements()) { | |
| 1355 // Find last non-deletable element in range of elements to be | |
| 1356 // deleted and adjust range accordingly. | |
| 1357 for (int i = 0; i < capacity; i++) { | |
| 1358 DisallowHeapAllocation no_gc; | |
| 1359 Object* key = dict->KeyAt(i); | |
| 1360 if (key->IsNumber()) { | |
| 1361 uint32_t number = static_cast<uint32_t>(key->Number()); | |
| 1362 if (length <= number && number < old_length) { | |
| 1363 PropertyDetails details = dict->DetailsAt(i); | |
| 1364 if (!details.IsConfigurable()) length = number + 1; | |
| 1365 } | |
| 1366 } | |
| 1367 } | |
| 1368 } | |
| 1369 | |
| 1370 if (length == 0) { | |
| 1371 // Flush the backing store. | |
| 1372 JSObject::ResetElements(array); | |
| 1373 } else { | |
| 1374 DisallowHeapAllocation no_gc; | |
| 1375 // Remove elements that should be deleted. | |
| 1376 int removed_entries = 0; | |
| 1377 Handle<Object> the_hole_value = isolate->factory()->the_hole_value(); | |
| 1378 for (int i = 0; i < capacity; i++) { | |
| 1379 Object* key = dict->KeyAt(i); | |
| 1380 if (key->IsNumber()) { | |
| 1381 uint32_t number = static_cast<uint32_t>(key->Number()); | |
| 1382 if (length <= number && number < old_length) { | |
| 1383 dict->SetEntry(i, the_hole_value, the_hole_value); | |
| 1384 removed_entries++; | |
| 1385 } | |
| 1386 } | |
| 1387 } | |
| 1388 | |
| 1389 // Update the number of elements. | |
| 1390 dict->ElementsRemoved(removed_entries); | |
| 1391 } | |
| 1392 } | |
| 1393 | |
| 1394 Handle<Object> length_obj = isolate->factory()->NewNumberFromUint(length); | |
| 1395 array->set_length(*length_obj); | |
| 1396 } | |
| 1397 | |
| 1398 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, | |
| 1399 FixedArrayBase* to, ElementsKind from_kind, | |
| 1400 uint32_t to_start, int packed_size, | |
| 1401 int copy_size) { | |
| 1402 UNREACHABLE(); | |
| 1403 } | |
| 1404 | |
| 1405 | |
| 1406 protected: | |
| 1407 friend class ElementsAccessorBase<DictionaryElementsAccessor, | |
| 1408 ElementsKindTraits<DICTIONARY_ELEMENTS> >; | |
| 1409 friend class SlowSloppyArgumentsElementsAccessor; | |
| 1410 friend class SloppyArgumentsElementsAccessor< | |
| 1411 SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor, | |
| 1412 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> >; | |
| 1413 | |
| 1414 static void DeleteCommon(Handle<JSObject> obj, uint32_t key, | |
| 1415 LanguageMode language_mode) { | |
| 1416 Isolate* isolate = obj->GetIsolate(); | |
| 1417 Handle<FixedArray> backing_store(FixedArray::cast(obj->elements()), | |
| 1418 isolate); | |
| 1419 bool is_arguments = obj->HasSloppyArgumentsElements(); | |
| 1420 if (is_arguments) { | |
| 1421 backing_store = handle(FixedArray::cast(backing_store->get(1)), isolate); | |
| 1422 } | |
| 1423 Handle<SeededNumberDictionary> dictionary = | |
| 1424 Handle<SeededNumberDictionary>::cast(backing_store); | |
| 1425 int entry = dictionary->FindEntry(key); | |
| 1426 if (entry != SeededNumberDictionary::kNotFound) { | |
| 1427 Handle<Object> result = | |
| 1428 SeededNumberDictionary::DeleteProperty(dictionary, entry); | |
| 1429 USE(result); | |
| 1430 DCHECK(result->IsTrue()); | |
| 1431 Handle<FixedArray> new_elements = | |
| 1432 SeededNumberDictionary::Shrink(dictionary, key); | |
| 1433 | |
| 1434 if (is_arguments) { | |
| 1435 FixedArray::cast(obj->elements())->set(1, *new_elements); | |
| 1436 } else { | |
| 1437 obj->set_elements(*new_elements); | |
| 1438 } | |
| 1439 } | |
| 1440 } | |
| 1441 | |
| 1442 virtual void Delete(Handle<JSObject> obj, uint32_t key, | |
| 1443 LanguageMode language_mode) final { | |
| 1444 DeleteCommon(obj, key, language_mode); | |
| 1445 } | |
| 1446 | |
| 1447 static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key, | |
| 1448 Handle<FixedArrayBase> store) { | |
| 1449 Handle<SeededNumberDictionary> backing_store = | |
| 1450 Handle<SeededNumberDictionary>::cast(store); | |
| 1451 Isolate* isolate = backing_store->GetIsolate(); | |
| 1452 int entry = backing_store->FindEntry(key); | |
| 1453 if (entry != SeededNumberDictionary::kNotFound) { | |
| 1454 return handle(backing_store->ValueAt(entry), isolate); | |
| 1455 } | |
| 1456 return isolate->factory()->the_hole_value(); | |
| 1457 } | |
| 1458 | |
| 1459 static void SetImpl(FixedArrayBase* store, uint32_t key, Object* value) { | |
| 1460 SeededNumberDictionary* dictionary = SeededNumberDictionary::cast(store); | |
| 1461 int entry = dictionary->FindEntry(key); | |
| 1462 DCHECK_NE(SeededNumberDictionary::kNotFound, entry); | |
| 1463 dictionary->ValueAtPut(entry, value); | |
| 1464 } | |
| 1465 | |
| 1466 static void ReconfigureImpl(Handle<JSObject> object, | |
| 1467 Handle<FixedArrayBase> store, uint32_t index, | |
| 1468 Handle<Object> value, | |
| 1469 PropertyAttributes attributes) { | |
| 1470 SeededNumberDictionary* dictionary = SeededNumberDictionary::cast(*store); | |
| 1471 if (attributes != NONE) dictionary->set_requires_slow_elements(); | |
| 1472 dictionary->ValueAtPut(index, *value); | |
| 1473 PropertyDetails details = dictionary->DetailsAt(index); | |
| 1474 details = PropertyDetails(attributes, DATA, details.dictionary_index(), | |
| 1475 PropertyCellType::kNoCell); | |
| 1476 dictionary->DetailsAtPut(index, details); | |
| 1477 } | |
| 1478 | |
| 1479 static void AddImpl(Handle<JSObject> object, uint32_t index, | |
| 1480 Handle<Object> value, PropertyAttributes attributes, | |
| 1481 uint32_t new_capacity) { | |
| 1482 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); | |
| 1483 Handle<SeededNumberDictionary> dictionary = | |
| 1484 object->HasFastElements() | |
| 1485 ? JSObject::NormalizeElements(object) | |
| 1486 : handle(SeededNumberDictionary::cast(object->elements())); | |
| 1487 Handle<SeededNumberDictionary> new_dictionary = | |
| 1488 SeededNumberDictionary::AddNumberEntry(dictionary, index, value, | |
| 1489 details); | |
| 1490 if (attributes != NONE) new_dictionary->set_requires_slow_elements(); | |
| 1491 if (dictionary.is_identical_to(new_dictionary)) return; | |
| 1492 object->set_elements(*new_dictionary); | |
| 1493 } | |
| 1494 | |
| 1495 static MaybeHandle<AccessorPair> GetAccessorPairImpl( | |
| 1496 Handle<JSObject> obj, uint32_t key, Handle<FixedArrayBase> store) { | |
| 1497 Handle<SeededNumberDictionary> backing_store = | |
| 1498 Handle<SeededNumberDictionary>::cast(store); | |
| 1499 int entry = backing_store->FindEntry(key); | |
| 1500 if (entry != SeededNumberDictionary::kNotFound && | |
| 1501 backing_store->DetailsAt(entry).type() == ACCESSOR_CONSTANT && | |
| 1502 backing_store->ValueAt(entry)->IsAccessorPair()) { | |
| 1503 return handle(AccessorPair::cast(backing_store->ValueAt(entry))); | |
| 1504 } | |
| 1505 return MaybeHandle<AccessorPair>(); | |
| 1506 } | |
| 1507 | |
| 1508 static bool HasIndexImpl(FixedArrayBase* store, uint32_t index) { | |
| 1509 DisallowHeapAllocation no_gc; | |
| 1510 SeededNumberDictionary* dict = SeededNumberDictionary::cast(store); | |
| 1511 Object* key = dict->KeyAt(index); | |
| 1512 return !key->IsTheHole(); | |
| 1513 } | |
| 1514 | |
| 1515 static uint32_t GetKeyForIndexImpl(FixedArrayBase* store, uint32_t index) { | |
| 1516 DisallowHeapAllocation no_gc; | |
| 1517 SeededNumberDictionary* dict = SeededNumberDictionary::cast(store); | |
| 1518 uint32_t result = 0; | |
| 1519 CHECK(dict->KeyAt(index)->ToArrayIndex(&result)); | |
| 1520 return result; | |
| 1521 } | |
| 1522 | |
| 1523 static uint32_t GetIndexForKeyImpl(JSObject* holder, FixedArrayBase* store, | |
| 1524 uint32_t key) { | |
| 1525 DisallowHeapAllocation no_gc; | |
| 1526 SeededNumberDictionary* dict = SeededNumberDictionary::cast(store); | |
| 1527 int entry = dict->FindEntry(key); | |
| 1528 return entry == SeededNumberDictionary::kNotFound | |
| 1529 ? kMaxUInt32 | |
| 1530 : static_cast<uint32_t>(entry); | |
| 1531 } | |
| 1532 | |
| 1533 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, | |
| 1534 uint32_t index) { | |
| 1535 return SeededNumberDictionary::cast(backing_store)->DetailsAt(index); | |
| 1536 } | |
| 1537 }; | |
| 1538 | |
| 1539 | |
| 1540 template <typename SloppyArgumentsElementsAccessorSubclass, | 1503 template <typename SloppyArgumentsElementsAccessorSubclass, |
| 1541 typename ArgumentsAccessor, typename KindTraits> | 1504 typename ArgumentsAccessor, typename KindTraits> |
| 1542 class SloppyArgumentsElementsAccessor | 1505 class SloppyArgumentsElementsAccessor |
| 1543 : public ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass, | 1506 : public ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass, |
| 1544 KindTraits> { | 1507 KindTraits> { |
| 1545 public: | 1508 public: |
| 1546 explicit SloppyArgumentsElementsAccessor(const char* name) | 1509 explicit SloppyArgumentsElementsAccessor(const char* name) |
| 1547 : ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass, | 1510 : ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass, |
| 1548 KindTraits>(name) {} | 1511 KindTraits>(name) {} |
| 1549 | 1512 |
| 1550 protected: | |
| 1551 friend class ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass, | |
| 1552 KindTraits>; | |
| 1553 | |
| 1554 static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key, | 1513 static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key, |
| 1555 Handle<FixedArrayBase> parameters) { | 1514 Handle<FixedArrayBase> parameters) { |
| 1556 Isolate* isolate = obj->GetIsolate(); | 1515 Isolate* isolate = obj->GetIsolate(); |
| 1557 Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters); | 1516 Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters); |
| 1558 Handle<Object> probe(GetParameterMapArg(*parameter_map, key), isolate); | 1517 Handle<Object> probe(GetParameterMapArg(*parameter_map, key), isolate); |
| 1559 if (!probe->IsTheHole()) { | 1518 if (!probe->IsTheHole()) { |
| 1560 DisallowHeapAllocation no_gc; | 1519 DisallowHeapAllocation no_gc; |
| 1561 Context* context = Context::cast(parameter_map->get(0)); | 1520 Context* context = Context::cast(parameter_map->get(0)); |
| 1562 int context_index = Handle<Smi>::cast(probe)->value(); | 1521 int context_index = Handle<Smi>::cast(probe)->value(); |
| 1563 DCHECK(!context->get(context_index)->IsTheHole()); | 1522 DCHECK(!context->get(context_index)->IsTheHole()); |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1689 | 1648 |
| 1690 static Object* GetParameterMapArg(FixedArray* parameter_map, uint32_t key) { | 1649 static Object* GetParameterMapArg(FixedArray* parameter_map, uint32_t key) { |
| 1691 uint32_t length = parameter_map->length() - 2; | 1650 uint32_t length = parameter_map->length() - 2; |
| 1692 return key < length | 1651 return key < length |
| 1693 ? parameter_map->get(key + 2) | 1652 ? parameter_map->get(key + 2) |
| 1694 : Object::cast(parameter_map->GetHeap()->the_hole_value()); | 1653 : Object::cast(parameter_map->GetHeap()->the_hole_value()); |
| 1695 } | 1654 } |
| 1696 }; | 1655 }; |
| 1697 | 1656 |
| 1698 | 1657 |
| 1658 class SlowSloppyArgumentsElementsAccessor |
| 1659 : public SloppyArgumentsElementsAccessor< |
| 1660 SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor, |
| 1661 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> > { |
| 1662 public: |
| 1663 explicit SlowSloppyArgumentsElementsAccessor(const char* name) |
| 1664 : SloppyArgumentsElementsAccessor< |
| 1665 SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor, |
| 1666 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> >(name) {} |
| 1667 |
| 1668 static void AddImpl(Handle<JSObject> object, uint32_t key, |
| 1669 Handle<Object> value, PropertyAttributes attributes, |
| 1670 uint32_t new_capacity) { |
| 1671 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements())); |
| 1672 Handle<FixedArrayBase> old_elements( |
| 1673 FixedArrayBase::cast(parameter_map->get(1))); |
| 1674 Handle<SeededNumberDictionary> dictionary = |
| 1675 old_elements->IsSeededNumberDictionary() |
| 1676 ? Handle<SeededNumberDictionary>::cast(old_elements) |
| 1677 : JSObject::NormalizeElements(object); |
| 1678 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); |
| 1679 Handle<SeededNumberDictionary> new_dictionary = |
| 1680 SeededNumberDictionary::AddNumberEntry(dictionary, key, value, details); |
| 1681 if (attributes != NONE) new_dictionary->set_requires_slow_elements(); |
| 1682 if (*dictionary != *new_dictionary) { |
| 1683 FixedArray::cast(object->elements())->set(1, *new_dictionary); |
| 1684 } |
| 1685 } |
| 1686 |
| 1687 static void ReconfigureImpl(Handle<JSObject> object, |
| 1688 Handle<FixedArrayBase> store, uint32_t index, |
| 1689 Handle<Object> value, |
| 1690 PropertyAttributes attributes) { |
| 1691 Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(store); |
| 1692 uint32_t length = parameter_map->length() - 2; |
| 1693 if (index < length) { |
| 1694 Object* probe = parameter_map->get(index + 2); |
| 1695 DCHECK(!probe->IsTheHole()); |
| 1696 Context* context = Context::cast(parameter_map->get(0)); |
| 1697 int context_index = Smi::cast(probe)->value(); |
| 1698 DCHECK(!context->get(context_index)->IsTheHole()); |
| 1699 context->set(context_index, *value); |
| 1700 |
| 1701 // Redefining attributes of an aliased element destroys fast aliasing. |
| 1702 parameter_map->set_the_hole(index + 2); |
| 1703 // For elements that are still writable we re-establish slow aliasing. |
| 1704 if ((attributes & READ_ONLY) == 0) { |
| 1705 Isolate* isolate = store->GetIsolate(); |
| 1706 value = isolate->factory()->NewAliasedArgumentsEntry(context_index); |
| 1707 } |
| 1708 |
| 1709 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); |
| 1710 Handle<SeededNumberDictionary> arguments( |
| 1711 SeededNumberDictionary::cast(parameter_map->get(1))); |
| 1712 arguments = SeededNumberDictionary::AddNumberEntry(arguments, index, |
| 1713 value, details); |
| 1714 parameter_map->set(1, *arguments); |
| 1715 } else { |
| 1716 Handle<FixedArrayBase> arguments( |
| 1717 FixedArrayBase::cast(parameter_map->get(1))); |
| 1718 DictionaryElementsAccessor::ReconfigureImpl( |
| 1719 object, arguments, index - length, value, attributes); |
| 1720 } |
| 1721 } |
| 1722 }; |
| 1723 |
| 1724 |
| 1699 class FastSloppyArgumentsElementsAccessor | 1725 class FastSloppyArgumentsElementsAccessor |
| 1700 : public SloppyArgumentsElementsAccessor< | 1726 : public SloppyArgumentsElementsAccessor< |
| 1701 FastSloppyArgumentsElementsAccessor, FastHoleyObjectElementsAccessor, | 1727 FastSloppyArgumentsElementsAccessor, FastHoleyObjectElementsAccessor, |
| 1702 ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> > { | 1728 ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> > { |
| 1703 public: | 1729 public: |
| 1704 friend class SloppyArgumentsElementsAccessor< | |
| 1705 FastSloppyArgumentsElementsAccessor, FastHoleyObjectElementsAccessor, | |
| 1706 ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >; | |
| 1707 friend class ElementsAccessorBase< | |
| 1708 FastSloppyArgumentsElementsAccessor, | |
| 1709 ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >; | |
| 1710 explicit FastSloppyArgumentsElementsAccessor(const char* name) | 1730 explicit FastSloppyArgumentsElementsAccessor(const char* name) |
| 1711 : SloppyArgumentsElementsAccessor< | 1731 : SloppyArgumentsElementsAccessor< |
| 1712 FastSloppyArgumentsElementsAccessor, | 1732 FastSloppyArgumentsElementsAccessor, |
| 1713 FastHoleyObjectElementsAccessor, | 1733 FastHoleyObjectElementsAccessor, |
| 1714 ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >(name) {} | 1734 ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >(name) {} |
| 1715 | 1735 |
| 1716 protected: | |
| 1717 static void AddImpl(Handle<JSObject> object, uint32_t key, | 1736 static void AddImpl(Handle<JSObject> object, uint32_t key, |
| 1718 Handle<Object> value, PropertyAttributes attributes, | 1737 Handle<Object> value, PropertyAttributes attributes, |
| 1719 uint32_t new_capacity) { | 1738 uint32_t new_capacity) { |
| 1720 DCHECK_EQ(NONE, attributes); | 1739 DCHECK_EQ(NONE, attributes); |
| 1721 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements())); | 1740 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements())); |
| 1722 Handle<FixedArrayBase> old_elements( | 1741 Handle<FixedArrayBase> old_elements( |
| 1723 FixedArrayBase::cast(parameter_map->get(1))); | 1742 FixedArrayBase::cast(parameter_map->get(1))); |
| 1724 if (old_elements->IsSeededNumberDictionary() || | 1743 if (old_elements->IsSeededNumberDictionary() || |
| 1725 static_cast<uint32_t>(old_elements->length()) < new_capacity) { | 1744 static_cast<uint32_t>(old_elements->length()) < new_capacity) { |
| 1726 GrowCapacityAndConvertImpl(object, new_capacity); | 1745 GrowCapacityAndConvertImpl(object, new_capacity); |
| 1727 } | 1746 } |
| 1728 SetImpl(object->elements(), key, *value); | 1747 SetImpl(object->elements(), key, *value); |
| 1729 } | 1748 } |
| 1730 | 1749 |
| 1731 static void ReconfigureImpl(Handle<JSObject> object, | 1750 static void ReconfigureImpl(Handle<JSObject> object, |
| 1732 Handle<FixedArrayBase> store, uint32_t index, | 1751 Handle<FixedArrayBase> store, uint32_t index, |
| 1733 Handle<Object> value, | 1752 Handle<Object> value, |
| 1734 PropertyAttributes attributes) { | 1753 PropertyAttributes attributes) { |
| 1735 Handle<SeededNumberDictionary> dictionary = | 1754 Handle<SeededNumberDictionary> dictionary = |
| 1736 JSObject::NormalizeElements(object); | 1755 JSObject::NormalizeElements(object); |
| 1737 FixedArray::cast(*store)->set(1, *dictionary); | 1756 FixedArray::cast(*store)->set(1, *dictionary); |
| 1738 uint32_t length = static_cast<uint32_t>(store->length()) - 2; | 1757 uint32_t length = static_cast<uint32_t>(store->length()) - 2; |
| 1739 if (index >= length) { | 1758 if (index >= length) { |
| 1740 index = dictionary->FindEntry(index - length) + length; | 1759 index = dictionary->FindEntry(index - length) + length; |
| 1741 } | 1760 } |
| 1742 object->GetElementsAccessor()->Reconfigure(object, store, index, value, | 1761 SlowSloppyArgumentsElementsAccessor::ReconfigureImpl(object, store, index, |
| 1743 attributes); | 1762 value, attributes); |
| 1744 } | 1763 } |
| 1745 | 1764 |
| 1746 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, | 1765 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, |
| 1747 FixedArrayBase* to, ElementsKind from_kind, | 1766 FixedArrayBase* to, ElementsKind from_kind, |
| 1748 uint32_t to_start, int packed_size, | 1767 uint32_t to_start, int packed_size, |
| 1749 int copy_size) { | 1768 int copy_size) { |
| 1750 DCHECK(!to->IsDictionary()); | 1769 DCHECK(!to->IsDictionary()); |
| 1751 if (from_kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS) { | 1770 if (from_kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS) { |
| 1752 CopyDictionaryToObjectElements(from, from_start, to, FAST_HOLEY_ELEMENTS, | 1771 CopyDictionaryToObjectElements(from, from_start, to, FAST_HOLEY_ELEMENTS, |
| 1753 to_start, copy_size); | 1772 to_start, copy_size); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1771 ConvertElementsWithCapacity(object, old_elements, from_kind, capacity); | 1790 ConvertElementsWithCapacity(object, old_elements, from_kind, capacity); |
| 1772 Handle<Map> new_map = JSObject::GetElementsTransitionMap( | 1791 Handle<Map> new_map = JSObject::GetElementsTransitionMap( |
| 1773 object, FAST_SLOPPY_ARGUMENTS_ELEMENTS); | 1792 object, FAST_SLOPPY_ARGUMENTS_ELEMENTS); |
| 1774 JSObject::MigrateToMap(object, new_map); | 1793 JSObject::MigrateToMap(object, new_map); |
| 1775 parameter_map->set(1, *elements); | 1794 parameter_map->set(1, *elements); |
| 1776 JSObject::ValidateElements(object); | 1795 JSObject::ValidateElements(object); |
| 1777 } | 1796 } |
| 1778 }; | 1797 }; |
| 1779 | 1798 |
| 1780 | 1799 |
| 1781 class SlowSloppyArgumentsElementsAccessor | |
| 1782 : public SloppyArgumentsElementsAccessor< | |
| 1783 SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor, | |
| 1784 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> > { | |
| 1785 public: | |
| 1786 friend class ElementsAccessorBase< | |
| 1787 SlowSloppyArgumentsElementsAccessor, | |
| 1788 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> >; | |
| 1789 friend class SloppyArgumentsElementsAccessor< | |
| 1790 SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor, | |
| 1791 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> >; | |
| 1792 explicit SlowSloppyArgumentsElementsAccessor(const char* name) | |
| 1793 : SloppyArgumentsElementsAccessor< | |
| 1794 SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor, | |
| 1795 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> >(name) {} | |
| 1796 | |
| 1797 protected: | |
| 1798 static void AddImpl(Handle<JSObject> object, uint32_t key, | |
| 1799 Handle<Object> value, PropertyAttributes attributes, | |
| 1800 uint32_t new_capacity) { | |
| 1801 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements())); | |
| 1802 Handle<FixedArrayBase> old_elements( | |
| 1803 FixedArrayBase::cast(parameter_map->get(1))); | |
| 1804 Handle<SeededNumberDictionary> dictionary = | |
| 1805 old_elements->IsSeededNumberDictionary() | |
| 1806 ? Handle<SeededNumberDictionary>::cast(old_elements) | |
| 1807 : JSObject::NormalizeElements(object); | |
| 1808 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); | |
| 1809 Handle<SeededNumberDictionary> new_dictionary = | |
| 1810 SeededNumberDictionary::AddNumberEntry(dictionary, key, value, details); | |
| 1811 if (attributes != NONE) new_dictionary->set_requires_slow_elements(); | |
| 1812 if (*dictionary != *new_dictionary) { | |
| 1813 FixedArray::cast(object->elements())->set(1, *new_dictionary); | |
| 1814 } | |
| 1815 } | |
| 1816 | |
| 1817 static void ReconfigureImpl(Handle<JSObject> object, | |
| 1818 Handle<FixedArrayBase> store, uint32_t index, | |
| 1819 Handle<Object> value, | |
| 1820 PropertyAttributes attributes) { | |
| 1821 Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(store); | |
| 1822 uint32_t length = parameter_map->length() - 2; | |
| 1823 if (index < length) { | |
| 1824 Object* probe = parameter_map->get(index + 2); | |
| 1825 DCHECK(!probe->IsTheHole()); | |
| 1826 Context* context = Context::cast(parameter_map->get(0)); | |
| 1827 int context_index = Smi::cast(probe)->value(); | |
| 1828 DCHECK(!context->get(context_index)->IsTheHole()); | |
| 1829 context->set(context_index, *value); | |
| 1830 | |
| 1831 // Redefining attributes of an aliased element destroys fast aliasing. | |
| 1832 parameter_map->set_the_hole(index + 2); | |
| 1833 // For elements that are still writable we re-establish slow aliasing. | |
| 1834 if ((attributes & READ_ONLY) == 0) { | |
| 1835 Isolate* isolate = store->GetIsolate(); | |
| 1836 value = isolate->factory()->NewAliasedArgumentsEntry(context_index); | |
| 1837 } | |
| 1838 | |
| 1839 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); | |
| 1840 Handle<SeededNumberDictionary> arguments( | |
| 1841 SeededNumberDictionary::cast(parameter_map->get(1))); | |
| 1842 arguments = SeededNumberDictionary::AddNumberEntry(arguments, index, | |
| 1843 value, details); | |
| 1844 parameter_map->set(1, *arguments); | |
| 1845 } else { | |
| 1846 Handle<FixedArrayBase> arguments( | |
| 1847 FixedArrayBase::cast(parameter_map->get(1))); | |
| 1848 DictionaryElementsAccessor::ReconfigureImpl( | |
| 1849 object, arguments, index - length, value, attributes); | |
| 1850 } | |
| 1851 } | |
| 1852 }; | |
| 1853 | |
| 1854 | |
| 1855 void ElementsAccessor::InitializeOncePerProcess() { | 1800 void ElementsAccessor::InitializeOncePerProcess() { |
| 1856 static ElementsAccessor* accessor_array[] = { | 1801 static ElementsAccessor* accessor_array[] = { |
| 1857 #define ACCESSOR_ARRAY(Class, Kind, Store) new Class(#Kind), | 1802 #define ACCESSOR_ARRAY(Class, Kind, Store) new Class(#Kind), |
| 1858 ELEMENTS_LIST(ACCESSOR_ARRAY) | 1803 ELEMENTS_LIST(ACCESSOR_ARRAY) |
| 1859 #undef ACCESSOR_ARRAY | 1804 #undef ACCESSOR_ARRAY |
| 1860 }; | 1805 }; |
| 1861 | 1806 |
| 1862 STATIC_ASSERT((sizeof(accessor_array) / sizeof(*accessor_array)) == | 1807 STATIC_ASSERT((sizeof(accessor_array) / sizeof(*accessor_array)) == |
| 1863 kElementsKindCount); | 1808 kElementsKindCount); |
| 1864 | 1809 |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2006 break; | 1951 break; |
| 2007 } | 1952 } |
| 2008 | 1953 |
| 2009 array->set_elements(*elms); | 1954 array->set_elements(*elms); |
| 2010 array->set_length(Smi::FromInt(number_of_elements)); | 1955 array->set_length(Smi::FromInt(number_of_elements)); |
| 2011 return array; | 1956 return array; |
| 2012 } | 1957 } |
| 2013 | 1958 |
| 2014 } // namespace internal | 1959 } // namespace internal |
| 2015 } // namespace v8 | 1960 } // namespace v8 |
| OLD | NEW |