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/elements.h" | 5 #include "src/elements.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/factory.h" | 9 #include "src/factory.h" |
10 #include "src/messages.h" | 10 #include "src/messages.h" |
(...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
421 for (int i = 0; i < copy_size; i++) { | 421 for (int i = 0; i < copy_size; i++) { |
422 int entry = from->FindEntry(i + from_start); | 422 int entry = from->FindEntry(i + from_start); |
423 if (entry != SeededNumberDictionary::kNotFound) { | 423 if (entry != SeededNumberDictionary::kNotFound) { |
424 to->set(i + to_start, from->ValueAt(entry)->Number()); | 424 to->set(i + to_start, from->ValueAt(entry)->Number()); |
425 } else { | 425 } else { |
426 to->set_the_hole(i + to_start); | 426 to->set_the_hole(i + to_start); |
427 } | 427 } |
428 } | 428 } |
429 } | 429 } |
430 | 430 |
431 Handle<FixedArray> EnsureSize(Isolate* isolate, Handle<FixedArray> array, | |
432 int size) { | |
433 int length = array->length(); | |
434 if (size < length) return array; | |
435 int new_capacity = length + length / 2; | |
436 int grow_by = new_capacity - length; | |
437 return isolate->factory()->CopyFixedArrayAndGrow(array, grow_by); | |
438 } | |
431 | 439 |
432 static void TraceTopFrame(Isolate* isolate) { | 440 static void TraceTopFrame(Isolate* isolate) { |
433 StackFrameIterator it(isolate); | 441 StackFrameIterator it(isolate); |
434 if (it.done()) { | 442 if (it.done()) { |
435 PrintF("unknown location (no JavaScript frames present)"); | 443 PrintF("unknown location (no JavaScript frames present)"); |
436 return; | 444 return; |
437 } | 445 } |
438 StackFrame* raw_frame = it.frame(); | 446 StackFrame* raw_frame = it.frame(); |
439 if (raw_frame->is_internal()) { | 447 if (raw_frame->is_internal()) { |
440 Code* apply_builtin = | 448 Code* apply_builtin = |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
720 } else { | 728 } else { |
721 // Check whether the backing store should be expanded. | 729 // Check whether the backing store should be expanded. |
722 capacity = Max(length, JSObject::NewElementsCapacity(capacity)); | 730 capacity = Max(length, JSObject::NewElementsCapacity(capacity)); |
723 ElementsAccessorSubclass::GrowCapacityAndConvertImpl(array, capacity); | 731 ElementsAccessorSubclass::GrowCapacityAndConvertImpl(array, capacity); |
724 } | 732 } |
725 | 733 |
726 array->set_length(Smi::FromInt(length)); | 734 array->set_length(Smi::FromInt(length)); |
727 JSObject::ValidateElements(array); | 735 JSObject::ValidateElements(array); |
728 } | 736 } |
729 | 737 |
738 static uint32_t GetIterationLength(JSObject* receiver, | |
739 FixedArrayBase* elements) { | |
740 if (receiver->IsJSArray()) { | |
741 return static_cast<uint32_t>( | |
742 Smi::cast(JSArray::cast(receiver)->length())->value()); | |
743 } else { | |
744 return ElementsAccessorSubclass::GetCapacityImpl(receiver, elements); | |
745 } | |
746 } | |
747 | |
730 static Handle<FixedArrayBase> ConvertElementsWithCapacity( | 748 static Handle<FixedArrayBase> ConvertElementsWithCapacity( |
731 Handle<JSObject> object, Handle<FixedArrayBase> old_elements, | 749 Handle<JSObject> object, Handle<FixedArrayBase> old_elements, |
732 ElementsKind from_kind, uint32_t capacity) { | 750 ElementsKind from_kind, uint32_t capacity) { |
733 return ConvertElementsWithCapacity( | 751 return ConvertElementsWithCapacity( |
734 object, old_elements, from_kind, capacity, 0, 0, | 752 object, old_elements, from_kind, capacity, 0, 0, |
735 ElementsAccessor::kCopyToEndAndInitializeToHole); | 753 ElementsAccessor::kCopyToEndAndInitializeToHole); |
736 } | 754 } |
737 | 755 |
738 static Handle<FixedArrayBase> ConvertElementsWithCapacity( | 756 static Handle<FixedArrayBase> ConvertElementsWithCapacity( |
739 Handle<JSObject> object, Handle<FixedArrayBase> old_elements, | 757 Handle<JSObject> object, Handle<FixedArrayBase> old_elements, |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
836 // intentionally to avoid ArrayConcat() builtin performance degradation. | 854 // intentionally to avoid ArrayConcat() builtin performance degradation. |
837 // | 855 // |
838 // Details: The idea is that allocations actually happen only in case of | 856 // Details: The idea is that allocations actually happen only in case of |
839 // copying from object with fast double elements to object with object | 857 // copying from object with fast double elements to object with object |
840 // elements. In all the other cases there are no allocations performed and | 858 // elements. In all the other cases there are no allocations performed and |
841 // handle creation causes noticeable performance degradation of the builtin. | 859 // handle creation causes noticeable performance degradation of the builtin. |
842 ElementsAccessorSubclass::CopyElementsImpl( | 860 ElementsAccessorSubclass::CopyElementsImpl( |
843 from, from_start, *to, from_kind, to_start, packed_size, copy_size); | 861 from, from_start, *to, from_kind, to_start, packed_size, copy_size); |
844 } | 862 } |
845 | 863 |
864 void CollectElementIndices(Handle<JSObject> object, | |
865 Handle<FixedArrayBase> backing_store, | |
866 KeyAccumulator* keys, uint32_t range, | |
867 PropertyFilter filter, uint32_t offset) final { | |
868 ElementsAccessorSubclass::CollectElementIndicesImpl( | |
869 object, backing_store, keys, range, filter, offset); | |
870 } | |
871 | |
846 static void CollectElementIndicesImpl(Handle<JSObject> object, | 872 static void CollectElementIndicesImpl(Handle<JSObject> object, |
847 Handle<FixedArrayBase> backing_store, | 873 Handle<FixedArrayBase> backing_store, |
848 KeyAccumulator* keys, uint32_t range, | 874 KeyAccumulator* keys, uint32_t range, |
849 PropertyFilter filter, | 875 PropertyFilter filter, |
850 uint32_t offset) { | 876 uint32_t offset) { |
851 DCHECK_NE(DICTIONARY_ELEMENTS, kind()); | 877 DCHECK_NE(DICTIONARY_ELEMENTS, kind()); |
852 if (filter & ONLY_ALL_CAN_READ) { | 878 if (filter & ONLY_ALL_CAN_READ) { |
853 // Non-dictionary elements can't have all-can-read accessors. | 879 // Non-dictionary elements can't have all-can-read accessors. |
854 return; | 880 return; |
855 } | 881 } |
856 uint32_t length = 0; | 882 uint32_t length = GetIterationLength(*object, *backing_store); |
857 if (object->IsJSArray()) { | |
858 length = Smi::cast(JSArray::cast(*object)->length())->value(); | |
859 } else { | |
860 length = | |
861 ElementsAccessorSubclass::GetCapacityImpl(*object, *backing_store); | |
862 } | |
863 if (range < length) length = range; | 883 if (range < length) length = range; |
864 for (uint32_t i = offset; i < length; i++) { | 884 for (uint32_t i = offset; i < length; i++) { |
865 if (!ElementsAccessorSubclass::HasElementImpl(object, i, backing_store, | 885 if (ElementsAccessorSubclass::HasElementImpl(object, i, backing_store, |
866 filter)) { | 886 filter)) { |
867 continue; | 887 keys->AddKey(i); |
868 } | 888 } |
869 keys->AddKey(i); | |
870 } | 889 } |
871 } | 890 } |
872 | 891 |
873 void CollectElementIndices(Handle<JSObject> object, | 892 static Handle<FixedArray> FastCollectElementIndicesImpl( |
874 Handle<FixedArrayBase> backing_store, | 893 Isolate* isolate, Handle<JSObject> object, |
875 KeyAccumulator* keys, uint32_t range, | 894 Handle<FixedArrayBase> backing_store, GetKeysConversion convert, |
876 PropertyFilter filter, uint32_t offset) final { | 895 PropertyFilter filter, Handle<FixedArray> list, int* nof_indices) { |
877 ElementsAccessorSubclass::CollectElementIndicesImpl( | 896 uint32_t length = |
878 object, backing_store, keys, range, filter, offset); | 897 ElementsAccessorSubclass::GetIterationLength(*object, *backing_store); |
879 }; | 898 int insertion_index = 0; |
899 for (uint32_t i = 0; i < length; i++) { | |
900 if (IsFastPackedElementsKind(kind())) { | |
Toon Verwaest
2016/02/24 15:07:06
HasElementImpl should just return true for packed
| |
901 if (convert == CONVERT_TO_STRING) { | |
902 list->set(insertion_index++, *isolate->factory()->Uint32ToString(i)); | |
903 } else { | |
904 list->set(insertion_index++, Smi::FromInt(i), SKIP_WRITE_BARRIER); | |
905 } | |
906 } else { | |
907 if (ElementsAccessorSubclass::HasElementImpl(object, i, backing_store, | |
908 filter)) { | |
909 list = EnsureSize(isolate, list, insertion_index); | |
910 if (convert == CONVERT_TO_STRING) { | |
911 list->set(insertion_index++, | |
912 *isolate->factory()->Uint32ToString(i)); | |
913 } else { | |
914 list->set(insertion_index++, Smi::FromInt(i), SKIP_WRITE_BARRIER); | |
915 } | |
916 } | |
917 } | |
918 } | |
919 *nof_indices = insertion_index; | |
920 return list; | |
921 } | |
922 | |
923 Handle<FixedArray> PrependElementIndices(Handle<JSObject> object, | |
924 Handle<FixedArrayBase> backing_store, | |
925 Handle<FixedArray> keys, | |
926 GetKeysConversion convert, | |
927 PropertyFilter filter) final { | |
928 return ElementsAccessorSubclass::PrependElementIndicesImpl( | |
929 object, backing_store, keys, convert, filter); | |
930 } | |
931 | |
932 Handle<FixedArray> PrependElementIndicesImpl( | |
933 Handle<JSObject> object, Handle<FixedArrayBase> backing_store, | |
934 Handle<FixedArray> keys, GetKeysConversion convert, | |
935 PropertyFilter filter) { | |
936 if (!IsDictionaryElementsKind(kind()) && filter & ONLY_ALL_CAN_READ) { | |
Toon Verwaest
2016/02/24 15:07:06
There are no ALL_CAN_READ indexed properties that
| |
937 // Non-dictionary elements can't have all-can-read accessors. | |
938 return keys; | |
939 } | |
940 | |
941 Isolate* isolate = object->GetIsolate(); | |
942 int nof_property_keys = keys->length(); | |
943 | |
944 // Calculate the initial list size depending on the object at hand. | |
945 int initial_list_length = 10; | |
Toon Verwaest
2016/02/24 15:07:06
Why not immediately use Capacity + nof_property_ke
| |
946 if (IsFastPackedElementsKind(kind())) { | |
947 initial_list_length = | |
948 ElementsAccessorSubclass::GetCapacityImpl(*object, *backing_store); | |
949 initial_list_length += nof_property_keys; | |
950 } | |
951 | |
952 // Collect the element indices into a new list. | |
953 int nof_indices = 0; | |
954 Handle<FixedArray> combined_keys = | |
955 isolate->factory()->NewFixedArray(initial_list_length); | |
956 combined_keys = ElementsAccessorSubclass::FastCollectElementIndicesImpl( | |
957 isolate, object, backing_store, convert, filter, combined_keys, | |
958 &nof_indices); | |
959 | |
960 // Sort the indices list if necessary. | |
961 if (kind() == DICTIONARY_ELEMENTS) { | |
962 struct { | |
963 bool operator()(Object* a, Object* b) { | |
Toon Verwaest
2016/02/24 15:07:06
return a->Number() < b->Number()? Seems like doub
| |
964 if (a->IsSmi()) { | |
965 if (!b->IsSmi()) return true; | |
966 return Smi::cast(a)->value() < Smi::cast(b)->value(); | |
967 } | |
968 return !b->IsSmi(); | |
969 } | |
970 } cmp; | |
971 Object** start = | |
972 reinterpret_cast<Object**>(combined_keys->GetFirstElementAddress()); | |
973 std::sort(start, start + nof_indices, cmp); | |
974 } | |
975 | |
976 // Shrink/Grow the combined_keys to the final size. | |
977 int final_size = nof_indices + nof_property_keys; | |
978 if (combined_keys->length() < final_size) { | |
979 combined_keys = isolate->factory()->CopyFixedArrayAndGrow( | |
980 combined_keys, final_size - combined_keys->length()); | |
981 } else { | |
982 combined_keys->Shrink(final_size); | |
983 } | |
984 | |
985 // Copy over the property keys. | |
986 ElementsKind kind = FAST_HOLEY_ELEMENTS; | |
Toon Verwaest
2016/02/24 15:07:06
I guess it doesn't change anything, but this shoul
| |
987 CopyObjectToObjectElements(*keys, kind, 0, *combined_keys, kind, | |
988 nof_indices, nof_property_keys); | |
989 return combined_keys; | |
990 } | |
880 | 991 |
881 void AddElementsToKeyAccumulator(Handle<JSObject> receiver, | 992 void AddElementsToKeyAccumulator(Handle<JSObject> receiver, |
882 KeyAccumulator* accumulator, | 993 KeyAccumulator* accumulator, |
883 AddKeyConversion convert) final { | 994 AddKeyConversion convert) final { |
884 ElementsAccessorSubclass::AddElementsToKeyAccumulatorImpl( | 995 ElementsAccessorSubclass::AddElementsToKeyAccumulatorImpl( |
885 receiver, accumulator, convert); | 996 receiver, accumulator, convert); |
886 } | 997 } |
887 | 998 |
888 static uint32_t GetCapacityImpl(JSObject* holder, | 999 static uint32_t GetCapacityImpl(JSObject* holder, |
889 FixedArrayBase* backing_store) { | 1000 FixedArrayBase* backing_store) { |
(...skipping 12 matching lines...) Expand all Loading... | |
902 static uint32_t GetEntryForIndexImpl(JSObject* holder, | 1013 static uint32_t GetEntryForIndexImpl(JSObject* holder, |
903 FixedArrayBase* backing_store, | 1014 FixedArrayBase* backing_store, |
904 uint32_t index, PropertyFilter filter) { | 1015 uint32_t index, PropertyFilter filter) { |
905 if (IsHoleyElementsKind(kind())) { | 1016 if (IsHoleyElementsKind(kind())) { |
906 return index < ElementsAccessorSubclass::GetCapacityImpl(holder, | 1017 return index < ElementsAccessorSubclass::GetCapacityImpl(holder, |
907 backing_store) && | 1018 backing_store) && |
908 !BackingStore::cast(backing_store)->is_the_hole(index) | 1019 !BackingStore::cast(backing_store)->is_the_hole(index) |
909 ? index | 1020 ? index |
910 : kMaxUInt32; | 1021 : kMaxUInt32; |
911 } else { | 1022 } else { |
912 uint32_t length = | 1023 uint32_t length = GetIterationLength(holder, backing_store); |
913 holder->IsJSArray() | |
914 ? static_cast<uint32_t>( | |
915 Smi::cast(JSArray::cast(holder)->length())->value()) | |
916 : ElementsAccessorSubclass::GetCapacityImpl(holder, | |
917 backing_store); | |
918 return index < length ? index : kMaxUInt32; | 1024 return index < length ? index : kMaxUInt32; |
919 } | 1025 } |
920 } | 1026 } |
921 | 1027 |
922 uint32_t GetEntryForIndex(JSObject* holder, FixedArrayBase* backing_store, | 1028 uint32_t GetEntryForIndex(JSObject* holder, FixedArrayBase* backing_store, |
923 uint32_t index) final { | 1029 uint32_t index) final { |
924 return ElementsAccessorSubclass::GetEntryForIndexImpl( | 1030 return ElementsAccessorSubclass::GetEntryForIndexImpl( |
925 holder, backing_store, index, ALL_PROPERTIES); | 1031 holder, backing_store, index, ALL_PROPERTIES); |
926 } | 1032 } |
927 | 1033 |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1109 | 1215 |
1110 static PropertyDetails GetDetailsImpl(JSObject* holder, uint32_t entry) { | 1216 static PropertyDetails GetDetailsImpl(JSObject* holder, uint32_t entry) { |
1111 return GetDetailsImpl(holder->elements(), entry); | 1217 return GetDetailsImpl(holder->elements(), entry); |
1112 } | 1218 } |
1113 | 1219 |
1114 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, | 1220 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, |
1115 uint32_t entry) { | 1221 uint32_t entry) { |
1116 return SeededNumberDictionary::cast(backing_store)->DetailsAt(entry); | 1222 return SeededNumberDictionary::cast(backing_store)->DetailsAt(entry); |
1117 } | 1223 } |
1118 | 1224 |
1225 static uint32_t GetKeyForEntryImpl(Handle<SeededNumberDictionary> dictionary, | |
1226 int entry, PropertyFilter filter) { | |
1227 Object* raw_key = dictionary->KeyAt(entry); | |
1228 if (!dictionary->IsKey(raw_key)) return kMaxUInt32; | |
1229 if (raw_key->FilterKey(filter)) return kMaxUInt32; | |
1230 if (dictionary->IsDeleted(entry)) return kMaxUInt32; | |
1231 DCHECK(raw_key->IsNumber()); | |
1232 DCHECK_LE(raw_key->Number(), kMaxUInt32); | |
1233 uint32_t key = static_cast<uint32_t>(raw_key->Number()); | |
1234 PropertyDetails details = dictionary->DetailsAt(entry); | |
1235 if (filter & ONLY_ALL_CAN_READ) { | |
1236 if (details.kind() != kAccessor) return kMaxUInt32; | |
1237 Object* accessors = dictionary->ValueAt(entry); | |
1238 if (!accessors->IsAccessorInfo()) return kMaxUInt32; | |
1239 if (!AccessorInfo::cast(accessors)->all_can_read()) return kMaxUInt32; | |
1240 } | |
1241 PropertyAttributes attr = details.attributes(); | |
1242 if ((attr & filter) != 0) return kMaxUInt32; | |
1243 return key; | |
1244 } | |
1245 | |
1119 static void CollectElementIndicesImpl(Handle<JSObject> object, | 1246 static void CollectElementIndicesImpl(Handle<JSObject> object, |
1120 Handle<FixedArrayBase> backing_store, | 1247 Handle<FixedArrayBase> backing_store, |
1121 KeyAccumulator* keys, uint32_t range, | 1248 KeyAccumulator* keys, uint32_t range, |
1122 PropertyFilter filter, | 1249 PropertyFilter filter, |
1123 uint32_t offset) { | 1250 uint32_t offset) { |
1124 Handle<SeededNumberDictionary> dictionary = | 1251 Handle<SeededNumberDictionary> dictionary = |
1125 Handle<SeededNumberDictionary>::cast(backing_store); | 1252 Handle<SeededNumberDictionary>::cast(backing_store); |
1126 int capacity = dictionary->Capacity(); | 1253 int capacity = dictionary->Capacity(); |
1127 for (int i = 0; i < capacity; i++) { | 1254 for (int i = 0; i < capacity; i++) { |
1128 Object* k = dictionary->KeyAt(i); | 1255 uint32_t key = GetKeyForEntryImpl(dictionary, i, filter); |
1129 if (!dictionary->IsKey(k)) continue; | 1256 if (key == kMaxUInt32) continue; |
1130 if (k->FilterKey(filter)) continue; | 1257 keys->AddKey(key); |
1131 if (dictionary->IsDeleted(i)) continue; | |
1132 DCHECK(k->IsNumber()); | |
1133 DCHECK_LE(k->Number(), kMaxUInt32); | |
1134 uint32_t index = static_cast<uint32_t>(k->Number()); | |
1135 if (index < offset) continue; | |
1136 PropertyDetails details = dictionary->DetailsAt(i); | |
1137 if (filter & ONLY_ALL_CAN_READ) { | |
1138 if (details.kind() != kAccessor) continue; | |
1139 Object* accessors = dictionary->ValueAt(i); | |
1140 if (!accessors->IsAccessorInfo()) continue; | |
1141 if (!AccessorInfo::cast(accessors)->all_can_read()) continue; | |
1142 } | |
1143 PropertyAttributes attr = details.attributes(); | |
1144 if ((attr & filter) != 0) continue; | |
1145 keys->AddKey(index); | |
1146 } | 1258 } |
1147 | 1259 |
1148 keys->SortCurrentElementsList(); | 1260 keys->SortCurrentElementsList(); |
1149 } | 1261 } |
1150 | 1262 |
1263 static Handle<FixedArray> FastCollectElementIndicesImpl( | |
1264 Isolate* isolate, Handle<JSObject> object, | |
1265 Handle<FixedArrayBase> backing_store, GetKeysConversion convert, | |
1266 PropertyFilter filter, Handle<FixedArray> list, int* nof_indices) { | |
1267 Handle<SeededNumberDictionary> dictionary = | |
1268 Handle<SeededNumberDictionary>::cast(backing_store); | |
1269 | |
1270 int capacity = dictionary->Capacity(); | |
1271 int insertion_index = 0; | |
1272 for (uint32_t i = 0; i < capacity; i++) { | |
1273 uint32_t key = GetKeyForEntryImpl(dictionary, i, filter); | |
1274 if (key == kMaxUInt32) continue; | |
1275 list = EnsureSize(isolate, list, insertion_index); | |
1276 if (convert == CONVERT_TO_STRING) { | |
1277 list->set(insertion_index++, *isolate->factory()->Uint32ToString(key)); | |
1278 } else { | |
1279 list->set(insertion_index++, Smi::FromInt(key), SKIP_WRITE_BARRIER); | |
1280 } | |
1281 } | |
1282 *nof_indices = insertion_index; | |
1283 return list; | |
1284 } | |
1285 | |
1151 static void AddElementsToKeyAccumulatorImpl(Handle<JSObject> receiver, | 1286 static void AddElementsToKeyAccumulatorImpl(Handle<JSObject> receiver, |
1152 KeyAccumulator* accumulator, | 1287 KeyAccumulator* accumulator, |
1153 AddKeyConversion convert) { | 1288 AddKeyConversion convert) { |
1154 SeededNumberDictionary* dictionary = | 1289 SeededNumberDictionary* dictionary = |
1155 SeededNumberDictionary::cast(receiver->elements()); | 1290 SeededNumberDictionary::cast(receiver->elements()); |
1156 int capacity = dictionary->Capacity(); | 1291 int capacity = dictionary->Capacity(); |
1157 for (int i = 0; i < capacity; i++) { | 1292 for (int i = 0; i < capacity; i++) { |
1158 Object* k = dictionary->KeyAt(i); | 1293 Object* k = dictionary->KeyAt(i); |
1159 if (!dictionary->IsKey(k)) continue; | 1294 if (!dictionary->IsKey(k)) continue; |
1160 if (dictionary->IsDeleted(i)) continue; | 1295 if (dictionary->IsDeleted(i)) continue; |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1305 DeleteCommon(obj, entry, handle(obj->elements())); | 1440 DeleteCommon(obj, entry, handle(obj->elements())); |
1306 } | 1441 } |
1307 | 1442 |
1308 static bool HasEntryImpl(FixedArrayBase* backing_store, uint32_t entry) { | 1443 static bool HasEntryImpl(FixedArrayBase* backing_store, uint32_t entry) { |
1309 return !BackingStore::cast(backing_store)->is_the_hole(entry); | 1444 return !BackingStore::cast(backing_store)->is_the_hole(entry); |
1310 } | 1445 } |
1311 | 1446 |
1312 static void AddElementsToKeyAccumulatorImpl(Handle<JSObject> receiver, | 1447 static void AddElementsToKeyAccumulatorImpl(Handle<JSObject> receiver, |
1313 KeyAccumulator* accumulator, | 1448 KeyAccumulator* accumulator, |
1314 AddKeyConversion convert) { | 1449 AddKeyConversion convert) { |
1315 uint32_t length = 0; | |
1316 Handle<FixedArrayBase> elements(receiver->elements(), | 1450 Handle<FixedArrayBase> elements(receiver->elements(), |
1317 receiver->GetIsolate()); | 1451 receiver->GetIsolate()); |
1318 if (receiver->IsJSArray()) { | 1452 uint32_t length = |
1319 length = Smi::cast(JSArray::cast(*receiver)->length())->value(); | 1453 FastElementsAccessorSubclass::GetIterationLength(*receiver, *elements); |
1320 } else { | |
1321 length = | |
1322 FastElementsAccessorSubclass::GetCapacityImpl(*receiver, *elements); | |
1323 } | |
1324 for (uint32_t i = 0; i < length; i++) { | 1454 for (uint32_t i = 0; i < length; i++) { |
1325 if (IsFastPackedElementsKind(KindTraits::Kind) || | 1455 if (IsFastPackedElementsKind(KindTraits::Kind) || |
1326 HasEntryImpl(*elements, i)) { | 1456 HasEntryImpl(*elements, i)) { |
1327 accumulator->AddKey(FastElementsAccessorSubclass::GetImpl(*elements, i), | 1457 accumulator->AddKey(FastElementsAccessorSubclass::GetImpl(*elements, i), |
1328 convert); | 1458 convert); |
1329 } | 1459 } |
1330 } | 1460 } |
1331 } | 1461 } |
1332 | 1462 |
1333 static void ValidateContents(Handle<JSObject> holder, int length) { | 1463 static void ValidateContents(Handle<JSObject> holder, int length) { |
(...skipping 1343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2677 } | 2807 } |
2678 } | 2808 } |
2679 | 2809 |
2680 DCHECK(j == result_len); | 2810 DCHECK(j == result_len); |
2681 return result_array; | 2811 return result_array; |
2682 } | 2812 } |
2683 | 2813 |
2684 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; | 2814 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; |
2685 } // namespace internal | 2815 } // namespace internal |
2686 } // namespace v8 | 2816 } // namespace v8 |
OLD | NEW |