| 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 |
| 431 static void TraceTopFrame(Isolate* isolate) { | 432 static void TraceTopFrame(Isolate* isolate) { |
| 432 StackFrameIterator it(isolate); | 433 StackFrameIterator it(isolate); |
| 433 if (it.done()) { | 434 if (it.done()) { |
| 434 PrintF("unknown location (no JavaScript frames present)"); | 435 PrintF("unknown location (no JavaScript frames present)"); |
| 435 return; | 436 return; |
| 436 } | 437 } |
| 437 StackFrame* raw_frame = it.frame(); | 438 StackFrame* raw_frame = it.frame(); |
| 438 if (raw_frame->is_internal()) { | 439 if (raw_frame->is_internal()) { |
| 439 Code* apply_builtin = | 440 Code* apply_builtin = |
| 440 isolate->builtins()->builtin(Builtins::kFunctionPrototypeApply); | 441 isolate->builtins()->builtin(Builtins::kFunctionPrototypeApply); |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 722 } else { | 723 } else { |
| 723 // Check whether the backing store should be expanded. | 724 // Check whether the backing store should be expanded. |
| 724 capacity = Max(length, JSObject::NewElementsCapacity(capacity)); | 725 capacity = Max(length, JSObject::NewElementsCapacity(capacity)); |
| 725 ElementsAccessorSubclass::GrowCapacityAndConvertImpl(array, capacity); | 726 ElementsAccessorSubclass::GrowCapacityAndConvertImpl(array, capacity); |
| 726 } | 727 } |
| 727 | 728 |
| 728 array->set_length(Smi::FromInt(length)); | 729 array->set_length(Smi::FromInt(length)); |
| 729 JSObject::ValidateElements(array); | 730 JSObject::ValidateElements(array); |
| 730 } | 731 } |
| 731 | 732 |
| 732 static uint32_t GetIterationLength(JSObject* receiver, | |
| 733 FixedArrayBase* elements) { | |
| 734 if (receiver->IsJSArray()) { | |
| 735 return static_cast<uint32_t>( | |
| 736 Smi::cast(JSArray::cast(receiver)->length())->value()); | |
| 737 } else { | |
| 738 return ElementsAccessorSubclass::GetCapacityImpl(receiver, elements); | |
| 739 } | |
| 740 } | |
| 741 | |
| 742 static Handle<FixedArrayBase> ConvertElementsWithCapacity( | 733 static Handle<FixedArrayBase> ConvertElementsWithCapacity( |
| 743 Handle<JSObject> object, Handle<FixedArrayBase> old_elements, | 734 Handle<JSObject> object, Handle<FixedArrayBase> old_elements, |
| 744 ElementsKind from_kind, uint32_t capacity) { | 735 ElementsKind from_kind, uint32_t capacity) { |
| 745 return ConvertElementsWithCapacity( | 736 return ConvertElementsWithCapacity( |
| 746 object, old_elements, from_kind, capacity, 0, 0, | 737 object, old_elements, from_kind, capacity, 0, 0, |
| 747 ElementsAccessor::kCopyToEndAndInitializeToHole); | 738 ElementsAccessor::kCopyToEndAndInitializeToHole); |
| 748 } | 739 } |
| 749 | 740 |
| 750 static Handle<FixedArrayBase> ConvertElementsWithCapacity( | 741 static Handle<FixedArrayBase> ConvertElementsWithCapacity( |
| 751 Handle<JSObject> object, Handle<FixedArrayBase> old_elements, | 742 Handle<JSObject> object, Handle<FixedArrayBase> old_elements, |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 848 // intentionally to avoid ArrayConcat() builtin performance degradation. | 839 // intentionally to avoid ArrayConcat() builtin performance degradation. |
| 849 // | 840 // |
| 850 // Details: The idea is that allocations actually happen only in case of | 841 // Details: The idea is that allocations actually happen only in case of |
| 851 // copying from object with fast double elements to object with object | 842 // copying from object with fast double elements to object with object |
| 852 // elements. In all the other cases there are no allocations performed and | 843 // elements. In all the other cases there are no allocations performed and |
| 853 // handle creation causes noticeable performance degradation of the builtin. | 844 // handle creation causes noticeable performance degradation of the builtin. |
| 854 ElementsAccessorSubclass::CopyElementsImpl( | 845 ElementsAccessorSubclass::CopyElementsImpl( |
| 855 from, from_start, *to, from_kind, to_start, packed_size, copy_size); | 846 from, from_start, *to, from_kind, to_start, packed_size, copy_size); |
| 856 } | 847 } |
| 857 | 848 |
| 858 void CollectElementIndices(Handle<JSObject> object, | |
| 859 Handle<FixedArrayBase> backing_store, | |
| 860 KeyAccumulator* keys, uint32_t range, | |
| 861 PropertyFilter filter, uint32_t offset) final { | |
| 862 ElementsAccessorSubclass::CollectElementIndicesImpl( | |
| 863 object, backing_store, keys, range, filter, offset); | |
| 864 } | |
| 865 | |
| 866 static void CollectElementIndicesImpl(Handle<JSObject> object, | 849 static void CollectElementIndicesImpl(Handle<JSObject> object, |
| 867 Handle<FixedArrayBase> backing_store, | 850 Handle<FixedArrayBase> backing_store, |
| 868 KeyAccumulator* keys, uint32_t range, | 851 KeyAccumulator* keys, uint32_t range, |
| 869 PropertyFilter filter, | 852 PropertyFilter filter, |
| 870 uint32_t offset) { | 853 uint32_t offset) { |
| 871 DCHECK_NE(DICTIONARY_ELEMENTS, kind()); | 854 DCHECK_NE(DICTIONARY_ELEMENTS, kind()); |
| 872 if (filter & ONLY_ALL_CAN_READ) { | 855 if (filter & ONLY_ALL_CAN_READ) { |
| 873 // Non-dictionary elements can't have all-can-read accessors. | 856 // Non-dictionary elements can't have all-can-read accessors. |
| 874 return; | 857 return; |
| 875 } | 858 } |
| 876 uint32_t length = GetIterationLength(*object, *backing_store); | 859 uint32_t length = 0; |
| 860 if (object->IsJSArray()) { |
| 861 length = Smi::cast(JSArray::cast(*object)->length())->value(); |
| 862 } else { |
| 863 length = |
| 864 ElementsAccessorSubclass::GetCapacityImpl(*object, *backing_store); |
| 865 } |
| 877 if (range < length) length = range; | 866 if (range < length) length = range; |
| 878 for (uint32_t i = offset; i < length; i++) { | 867 for (uint32_t i = offset; i < length; i++) { |
| 879 if (ElementsAccessorSubclass::HasElementImpl(object, i, backing_store, | 868 if (!ElementsAccessorSubclass::HasElementImpl(object, i, backing_store, |
| 880 filter)) { | 869 filter)) { |
| 881 keys->AddKey(i); | 870 continue; |
| 882 } | 871 } |
| 872 keys->AddKey(i); |
| 883 } | 873 } |
| 884 } | 874 } |
| 885 | 875 |
| 886 static Handle<FixedArray> DirectCollectElementIndicesImpl( | 876 void CollectElementIndices(Handle<JSObject> object, |
| 887 Isolate* isolate, Handle<JSObject> object, | 877 Handle<FixedArrayBase> backing_store, |
| 888 Handle<FixedArrayBase> backing_store, GetKeysConversion convert, | 878 KeyAccumulator* keys, uint32_t range, |
| 889 PropertyFilter filter, Handle<FixedArray> list, uint32_t* nof_indices) { | 879 PropertyFilter filter, uint32_t offset) final { |
| 890 uint32_t length = | 880 ElementsAccessorSubclass::CollectElementIndicesImpl( |
| 891 ElementsAccessorSubclass::GetIterationLength(*object, *backing_store); | 881 object, backing_store, keys, range, filter, offset); |
| 892 uint32_t insertion_index = 0; | 882 }; |
| 893 for (uint32_t i = 0; i < length; i++) { | |
| 894 if (ElementsAccessorSubclass::HasElementImpl(object, i, backing_store, | |
| 895 filter)) { | |
| 896 if (convert == CONVERT_TO_STRING) { | |
| 897 list->set(insertion_index, *isolate->factory()->Uint32ToString(i)); | |
| 898 } else { | |
| 899 list->set(insertion_index, Smi::FromInt(i), SKIP_WRITE_BARRIER); | |
| 900 } | |
| 901 insertion_index++; | |
| 902 } | |
| 903 } | |
| 904 *nof_indices = insertion_index; | |
| 905 return list; | |
| 906 } | |
| 907 | |
| 908 Handle<FixedArray> PrependElementIndices(Handle<JSObject> object, | |
| 909 Handle<FixedArrayBase> backing_store, | |
| 910 Handle<FixedArray> keys, | |
| 911 GetKeysConversion convert, | |
| 912 PropertyFilter filter) final { | |
| 913 return ElementsAccessorSubclass::PrependElementIndicesImpl( | |
| 914 object, backing_store, keys, convert, filter); | |
| 915 } | |
| 916 | |
| 917 static Handle<FixedArray> PrependElementIndicesImpl( | |
| 918 Handle<JSObject> object, Handle<FixedArrayBase> backing_store, | |
| 919 Handle<FixedArray> keys, GetKeysConversion convert, | |
| 920 PropertyFilter filter) { | |
| 921 Isolate* isolate = object->GetIsolate(); | |
| 922 uint32_t nof_property_keys = keys->length(); | |
| 923 uint32_t initial_list_length = | |
| 924 ElementsAccessorSubclass::GetCapacityImpl(*object, *backing_store); | |
| 925 initial_list_length += nof_property_keys; | |
| 926 | |
| 927 // Collect the element indices into a new list. | |
| 928 uint32_t nof_indices = 0; | |
| 929 Handle<FixedArray> combined_keys = | |
| 930 isolate->factory()->NewFixedArray(initial_list_length); | |
| 931 combined_keys = ElementsAccessorSubclass::DirectCollectElementIndicesImpl( | |
| 932 isolate, object, backing_store, convert, filter, combined_keys, | |
| 933 &nof_indices); | |
| 934 | |
| 935 // Sort the indices list if necessary. | |
| 936 if (IsDictionaryElementsKind(kind())) { | |
| 937 struct { | |
| 938 bool operator()(Object* a, Object* b) { | |
| 939 if (!a->IsUndefined()) { | |
| 940 if (b->IsUndefined()) return true; | |
| 941 return a->Number() < b->Number(); | |
| 942 } | |
| 943 return !b->IsUndefined(); | |
| 944 } | |
| 945 } cmp; | |
| 946 Object** start = | |
| 947 reinterpret_cast<Object**>(combined_keys->GetFirstElementAddress()); | |
| 948 std::sort(start, start + nof_indices, cmp); | |
| 949 // Indices from dictionary elements should only be converted after | |
| 950 // sorting. | |
| 951 if (convert == CONVERT_TO_STRING) { | |
| 952 for (uint32_t i = 0; i < nof_indices; i++) { | |
| 953 combined_keys->set(i, *isolate->factory()->Uint32ToString( | |
| 954 combined_keys->get(i)->Number())); | |
| 955 } | |
| 956 } | |
| 957 } | |
| 958 | |
| 959 // Copy over the passed-in property keys. | |
| 960 CopyObjectToObjectElements(*keys, FAST_ELEMENTS, 0, *combined_keys, | |
| 961 FAST_ELEMENTS, nof_indices, nof_property_keys); | |
| 962 | |
| 963 if (IsHoleyElementsKind(kind())) { | |
| 964 // Shrink combined_keys to the final size. | |
| 965 int final_size = nof_indices + nof_property_keys; | |
| 966 DCHECK_LE(final_size, combined_keys->length()); | |
| 967 combined_keys->Shrink(final_size); | |
| 968 } | |
| 969 | |
| 970 return combined_keys; | |
| 971 } | |
| 972 | 883 |
| 973 void AddElementsToKeyAccumulator(Handle<JSObject> receiver, | 884 void AddElementsToKeyAccumulator(Handle<JSObject> receiver, |
| 974 KeyAccumulator* accumulator, | 885 KeyAccumulator* accumulator, |
| 975 AddKeyConversion convert) final { | 886 AddKeyConversion convert) final { |
| 976 ElementsAccessorSubclass::AddElementsToKeyAccumulatorImpl( | 887 ElementsAccessorSubclass::AddElementsToKeyAccumulatorImpl( |
| 977 receiver, accumulator, convert); | 888 receiver, accumulator, convert); |
| 978 } | 889 } |
| 979 | 890 |
| 980 static uint32_t GetCapacityImpl(JSObject* holder, | 891 static uint32_t GetCapacityImpl(JSObject* holder, |
| 981 FixedArrayBase* backing_store) { | 892 FixedArrayBase* backing_store) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 994 static uint32_t GetEntryForIndexImpl(JSObject* holder, | 905 static uint32_t GetEntryForIndexImpl(JSObject* holder, |
| 995 FixedArrayBase* backing_store, | 906 FixedArrayBase* backing_store, |
| 996 uint32_t index, PropertyFilter filter) { | 907 uint32_t index, PropertyFilter filter) { |
| 997 if (IsHoleyElementsKind(kind())) { | 908 if (IsHoleyElementsKind(kind())) { |
| 998 return index < ElementsAccessorSubclass::GetCapacityImpl(holder, | 909 return index < ElementsAccessorSubclass::GetCapacityImpl(holder, |
| 999 backing_store) && | 910 backing_store) && |
| 1000 !BackingStore::cast(backing_store)->is_the_hole(index) | 911 !BackingStore::cast(backing_store)->is_the_hole(index) |
| 1001 ? index | 912 ? index |
| 1002 : kMaxUInt32; | 913 : kMaxUInt32; |
| 1003 } else { | 914 } else { |
| 1004 uint32_t length = GetIterationLength(holder, backing_store); | 915 uint32_t length = |
| 916 holder->IsJSArray() |
| 917 ? static_cast<uint32_t>( |
| 918 Smi::cast(JSArray::cast(holder)->length())->value()) |
| 919 : ElementsAccessorSubclass::GetCapacityImpl(holder, |
| 920 backing_store); |
| 1005 return index < length ? index : kMaxUInt32; | 921 return index < length ? index : kMaxUInt32; |
| 1006 } | 922 } |
| 1007 } | 923 } |
| 1008 | 924 |
| 1009 uint32_t GetEntryForIndex(JSObject* holder, FixedArrayBase* backing_store, | 925 uint32_t GetEntryForIndex(JSObject* holder, FixedArrayBase* backing_store, |
| 1010 uint32_t index) final { | 926 uint32_t index) final { |
| 1011 return ElementsAccessorSubclass::GetEntryForIndexImpl( | 927 return ElementsAccessorSubclass::GetEntryForIndexImpl( |
| 1012 holder, backing_store, index, ALL_PROPERTIES); | 928 holder, backing_store, index, ALL_PROPERTIES); |
| 1013 } | 929 } |
| 1014 | 930 |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1196 | 1112 |
| 1197 static PropertyDetails GetDetailsImpl(JSObject* holder, uint32_t entry) { | 1113 static PropertyDetails GetDetailsImpl(JSObject* holder, uint32_t entry) { |
| 1198 return GetDetailsImpl(holder->elements(), entry); | 1114 return GetDetailsImpl(holder->elements(), entry); |
| 1199 } | 1115 } |
| 1200 | 1116 |
| 1201 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, | 1117 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, |
| 1202 uint32_t entry) { | 1118 uint32_t entry) { |
| 1203 return SeededNumberDictionary::cast(backing_store)->DetailsAt(entry); | 1119 return SeededNumberDictionary::cast(backing_store)->DetailsAt(entry); |
| 1204 } | 1120 } |
| 1205 | 1121 |
| 1206 static uint32_t GetKeyForEntryImpl(Handle<SeededNumberDictionary> dictionary, | |
| 1207 int entry, PropertyFilter filter) { | |
| 1208 DisallowHeapAllocation no_gc; | |
| 1209 Object* raw_key = dictionary->KeyAt(entry); | |
| 1210 if (!dictionary->IsKey(raw_key)) return kMaxUInt32; | |
| 1211 if (raw_key->FilterKey(filter)) return kMaxUInt32; | |
| 1212 if (dictionary->IsDeleted(entry)) return kMaxUInt32; | |
| 1213 DCHECK(raw_key->IsNumber()); | |
| 1214 DCHECK_LE(raw_key->Number(), kMaxUInt32); | |
| 1215 uint32_t key = static_cast<uint32_t>(raw_key->Number()); | |
| 1216 PropertyDetails details = dictionary->DetailsAt(entry); | |
| 1217 if (filter & ONLY_ALL_CAN_READ) { | |
| 1218 if (details.kind() != kAccessor) return kMaxUInt32; | |
| 1219 Object* accessors = dictionary->ValueAt(entry); | |
| 1220 if (!accessors->IsAccessorInfo()) return kMaxUInt32; | |
| 1221 if (!AccessorInfo::cast(accessors)->all_can_read()) return kMaxUInt32; | |
| 1222 } | |
| 1223 PropertyAttributes attr = details.attributes(); | |
| 1224 if ((attr & filter) != 0) return kMaxUInt32; | |
| 1225 return key; | |
| 1226 } | |
| 1227 | |
| 1228 static void CollectElementIndicesImpl(Handle<JSObject> object, | 1122 static void CollectElementIndicesImpl(Handle<JSObject> object, |
| 1229 Handle<FixedArrayBase> backing_store, | 1123 Handle<FixedArrayBase> backing_store, |
| 1230 KeyAccumulator* keys, uint32_t range, | 1124 KeyAccumulator* keys, uint32_t range, |
| 1231 PropertyFilter filter, | 1125 PropertyFilter filter, |
| 1232 uint32_t offset) { | 1126 uint32_t offset) { |
| 1233 Handle<SeededNumberDictionary> dictionary = | 1127 Handle<SeededNumberDictionary> dictionary = |
| 1234 Handle<SeededNumberDictionary>::cast(backing_store); | 1128 Handle<SeededNumberDictionary>::cast(backing_store); |
| 1235 int capacity = dictionary->Capacity(); | 1129 int capacity = dictionary->Capacity(); |
| 1236 for (int i = 0; i < capacity; i++) { | 1130 for (int i = 0; i < capacity; i++) { |
| 1237 uint32_t key = GetKeyForEntryImpl(dictionary, i, filter); | 1131 Object* k = dictionary->KeyAt(i); |
| 1238 if (key == kMaxUInt32) continue; | 1132 if (!dictionary->IsKey(k)) continue; |
| 1239 keys->AddKey(key); | 1133 if (k->FilterKey(filter)) continue; |
| 1134 if (dictionary->IsDeleted(i)) continue; |
| 1135 DCHECK(k->IsNumber()); |
| 1136 DCHECK_LE(k->Number(), kMaxUInt32); |
| 1137 uint32_t index = static_cast<uint32_t>(k->Number()); |
| 1138 if (index < offset) continue; |
| 1139 PropertyDetails details = dictionary->DetailsAt(i); |
| 1140 if (filter & ONLY_ALL_CAN_READ) { |
| 1141 if (details.kind() != kAccessor) continue; |
| 1142 Object* accessors = dictionary->ValueAt(i); |
| 1143 if (!accessors->IsAccessorInfo()) continue; |
| 1144 if (!AccessorInfo::cast(accessors)->all_can_read()) continue; |
| 1145 } |
| 1146 PropertyAttributes attr = details.attributes(); |
| 1147 if ((attr & filter) != 0) continue; |
| 1148 keys->AddKey(index); |
| 1240 } | 1149 } |
| 1241 | 1150 |
| 1242 keys->SortCurrentElementsList(); | 1151 keys->SortCurrentElementsList(); |
| 1243 } | 1152 } |
| 1244 | 1153 |
| 1245 static Handle<FixedArray> DirectCollectElementIndicesImpl( | |
| 1246 Isolate* isolate, Handle<JSObject> object, | |
| 1247 Handle<FixedArrayBase> backing_store, GetKeysConversion convert, | |
| 1248 PropertyFilter filter, Handle<FixedArray> list, uint32_t* nof_indices) { | |
| 1249 Handle<SeededNumberDictionary> dictionary = | |
| 1250 Handle<SeededNumberDictionary>::cast(backing_store); | |
| 1251 uint32_t capacity = dictionary->Capacity(); | |
| 1252 uint32_t insertion_index = 0; | |
| 1253 for (uint32_t i = 0; i < capacity; i++) { | |
| 1254 uint32_t key = GetKeyForEntryImpl(dictionary, i, filter); | |
| 1255 if (key == kMaxUInt32) continue; | |
| 1256 list->set(insertion_index, *isolate->factory()->NewNumberFromUint(key)); | |
| 1257 insertion_index++; | |
| 1258 } | |
| 1259 *nof_indices = insertion_index; | |
| 1260 return list; | |
| 1261 } | |
| 1262 | |
| 1263 static void AddElementsToKeyAccumulatorImpl(Handle<JSObject> receiver, | 1154 static void AddElementsToKeyAccumulatorImpl(Handle<JSObject> receiver, |
| 1264 KeyAccumulator* accumulator, | 1155 KeyAccumulator* accumulator, |
| 1265 AddKeyConversion convert) { | 1156 AddKeyConversion convert) { |
| 1266 SeededNumberDictionary* dictionary = | 1157 SeededNumberDictionary* dictionary = |
| 1267 SeededNumberDictionary::cast(receiver->elements()); | 1158 SeededNumberDictionary::cast(receiver->elements()); |
| 1268 int capacity = dictionary->Capacity(); | 1159 int capacity = dictionary->Capacity(); |
| 1269 for (int i = 0; i < capacity; i++) { | 1160 for (int i = 0; i < capacity; i++) { |
| 1270 Object* k = dictionary->KeyAt(i); | 1161 Object* k = dictionary->KeyAt(i); |
| 1271 if (!dictionary->IsKey(k)) continue; | 1162 if (!dictionary->IsKey(k)) continue; |
| 1272 if (dictionary->IsDeleted(i)) continue; | 1163 if (dictionary->IsDeleted(i)) continue; |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1417 DeleteCommon(obj, entry, handle(obj->elements())); | 1308 DeleteCommon(obj, entry, handle(obj->elements())); |
| 1418 } | 1309 } |
| 1419 | 1310 |
| 1420 static bool HasEntryImpl(FixedArrayBase* backing_store, uint32_t entry) { | 1311 static bool HasEntryImpl(FixedArrayBase* backing_store, uint32_t entry) { |
| 1421 return !BackingStore::cast(backing_store)->is_the_hole(entry); | 1312 return !BackingStore::cast(backing_store)->is_the_hole(entry); |
| 1422 } | 1313 } |
| 1423 | 1314 |
| 1424 static void AddElementsToKeyAccumulatorImpl(Handle<JSObject> receiver, | 1315 static void AddElementsToKeyAccumulatorImpl(Handle<JSObject> receiver, |
| 1425 KeyAccumulator* accumulator, | 1316 KeyAccumulator* accumulator, |
| 1426 AddKeyConversion convert) { | 1317 AddKeyConversion convert) { |
| 1318 uint32_t length = 0; |
| 1427 Handle<FixedArrayBase> elements(receiver->elements(), | 1319 Handle<FixedArrayBase> elements(receiver->elements(), |
| 1428 receiver->GetIsolate()); | 1320 receiver->GetIsolate()); |
| 1429 uint32_t length = | 1321 if (receiver->IsJSArray()) { |
| 1430 FastElementsAccessorSubclass::GetIterationLength(*receiver, *elements); | 1322 length = Smi::cast(JSArray::cast(*receiver)->length())->value(); |
| 1323 } else { |
| 1324 length = |
| 1325 FastElementsAccessorSubclass::GetCapacityImpl(*receiver, *elements); |
| 1326 } |
| 1431 for (uint32_t i = 0; i < length; i++) { | 1327 for (uint32_t i = 0; i < length; i++) { |
| 1432 if (IsFastPackedElementsKind(KindTraits::Kind) || | 1328 if (IsFastPackedElementsKind(KindTraits::Kind) || |
| 1433 HasEntryImpl(*elements, i)) { | 1329 HasEntryImpl(*elements, i)) { |
| 1434 accumulator->AddKey(FastElementsAccessorSubclass::GetImpl(*elements, i), | 1330 accumulator->AddKey(FastElementsAccessorSubclass::GetImpl(*elements, i), |
| 1435 convert); | 1331 convert); |
| 1436 } | 1332 } |
| 1437 } | 1333 } |
| 1438 } | 1334 } |
| 1439 | 1335 |
| 1440 static void ValidateContents(Handle<JSObject> holder, int length) { | 1336 static void ValidateContents(Handle<JSObject> holder, int length) { |
| (...skipping 1343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2784 } | 2680 } |
| 2785 } | 2681 } |
| 2786 | 2682 |
| 2787 DCHECK(j == result_len); | 2683 DCHECK(j == result_len); |
| 2788 return result_array; | 2684 return result_array; |
| 2789 } | 2685 } |
| 2790 | 2686 |
| 2791 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; | 2687 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; |
| 2792 } // namespace internal | 2688 } // namespace internal |
| 2793 } // namespace v8 | 2689 } // namespace v8 |
| OLD | NEW |