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 |