Chromium Code Reviews| 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 |