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/isolate-inl.h" | 10 #include "src/isolate-inl.h" |
(...skipping 964 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
975 convert, filter); | 975 convert, filter); |
976 } | 976 } |
977 | 977 |
978 static Handle<FixedArray> PrependElementIndicesImpl( | 978 static Handle<FixedArray> PrependElementIndicesImpl( |
979 Handle<JSObject> object, Handle<FixedArrayBase> backing_store, | 979 Handle<JSObject> object, Handle<FixedArrayBase> backing_store, |
980 Handle<FixedArray> keys, GetKeysConversion convert, | 980 Handle<FixedArray> keys, GetKeysConversion convert, |
981 PropertyFilter filter) { | 981 PropertyFilter filter) { |
982 Isolate* isolate = object->GetIsolate(); | 982 Isolate* isolate = object->GetIsolate(); |
983 uint32_t nof_property_keys = keys->length(); | 983 uint32_t nof_property_keys = keys->length(); |
984 uint32_t initial_list_length = | 984 uint32_t initial_list_length = |
985 Subclass::GetCapacityImpl(*object, *backing_store); | 985 Subclass::GetMaxNumberOfEntries(*object, *backing_store); |
986 initial_list_length += nof_property_keys; | 986 initial_list_length += nof_property_keys; |
987 | 987 |
| 988 bool needs_sorting = |
| 989 IsDictionaryElementsKind(kind()) || IsSloppyArgumentsElements(kind()); |
| 990 |
988 // Collect the element indices into a new list. | 991 // Collect the element indices into a new list. |
989 uint32_t nof_indices = 0; | 992 uint32_t nof_indices = 0; |
990 Handle<FixedArray> combined_keys = | 993 Handle<FixedArray> combined_keys = |
991 isolate->factory()->NewFixedArray(initial_list_length); | 994 isolate->factory()->NewFixedArray(initial_list_length); |
992 combined_keys = Subclass::DirectCollectElementIndicesImpl( | 995 combined_keys = Subclass::DirectCollectElementIndicesImpl( |
993 isolate, object, backing_store, convert, filter, combined_keys, | 996 isolate, object, backing_store, |
994 &nof_indices); | 997 needs_sorting ? GetKeysConversion::kKeepNumbers : convert, filter, |
| 998 combined_keys, &nof_indices); |
995 | 999 |
996 // Sort the indices list if necessary. | 1000 if (needs_sorting) { |
997 if (IsDictionaryElementsKind(kind()) || IsSloppyArgumentsElements(kind())) { | |
998 SortIndices(combined_keys, nof_indices, SKIP_WRITE_BARRIER); | 1001 SortIndices(combined_keys, nof_indices, SKIP_WRITE_BARRIER); |
999 uint32_t array_length = 0; | 1002 uint32_t array_length = 0; |
1000 // Indices from dictionary elements should only be converted after | 1003 // Indices from dictionary elements should only be converted after |
1001 // sorting. | 1004 // sorting. |
1002 if (convert == GetKeysConversion::kConvertToString) { | 1005 if (convert == GetKeysConversion::kConvertToString) { |
1003 for (uint32_t i = 0; i < nof_indices; i++) { | 1006 for (uint32_t i = 0; i < nof_indices; i++) { |
1004 Handle<Object> index_string = isolate->factory()->Uint32ToString( | 1007 Handle<Object> index_string = isolate->factory()->Uint32ToString( |
1005 combined_keys->get(i)->Number()); | 1008 combined_keys->get(i)->Number()); |
1006 combined_keys->set(i, *index_string); | 1009 combined_keys->set(i, *index_string); |
1007 } | 1010 } |
1008 } else if (!(object->IsJSArray() && | 1011 } else if (!(object->IsJSArray() && |
1009 JSArray::cast(*object)->length()->ToArrayLength( | 1012 JSArray::cast(*object)->length()->ToArrayLength( |
1010 &array_length) && | 1013 &array_length) && |
1011 array_length <= Smi::kMaxValue)) { | 1014 array_length <= Smi::kMaxValue)) { |
1012 // Since we use std::sort above, the GC will no longer know where the | 1015 // Since we use std::sort above, the GC will no longer know where the |
1013 // HeapNumbers are. For Arrays with valid Smi length, we are sure to | 1016 // HeapNumbers are. For Arrays with valid Smi length, we are sure to |
1014 // have no HeapNumber indices and thus we can skip this step. | 1017 // have no HeapNumber indices and thus we can skip this step. |
1015 FIXED_ARRAY_ELEMENTS_WRITE_BARRIER(isolate->heap(), *combined_keys, 0, | 1018 FIXED_ARRAY_ELEMENTS_WRITE_BARRIER(isolate->heap(), *combined_keys, 0, |
1016 nof_indices); | 1019 nof_indices); |
1017 } | 1020 } |
1018 } | 1021 } |
1019 | 1022 |
1020 // Copy over the passed-in property keys. | 1023 // Copy over the passed-in property keys. |
1021 CopyObjectToObjectElements(*keys, FAST_ELEMENTS, 0, *combined_keys, | 1024 CopyObjectToObjectElements(*keys, FAST_ELEMENTS, 0, *combined_keys, |
1022 FAST_ELEMENTS, nof_indices, nof_property_keys); | 1025 FAST_ELEMENTS, nof_indices, nof_property_keys); |
1023 | 1026 |
1024 if (IsHoleyElementsKind(kind())) { | 1027 // For holey elements and arguments we might have to shrink the collected |
| 1028 // keys since the estimates might be off. |
| 1029 if (IsHoleyElementsKind(kind()) || IsSloppyArgumentsElements(kind())) { |
1025 // Shrink combined_keys to the final size. | 1030 // Shrink combined_keys to the final size. |
1026 int final_size = nof_indices + nof_property_keys; | 1031 int final_size = nof_indices + nof_property_keys; |
1027 DCHECK_LE(final_size, combined_keys->length()); | 1032 DCHECK_LE(final_size, combined_keys->length()); |
1028 combined_keys->Shrink(final_size); | 1033 combined_keys->Shrink(final_size); |
1029 } | 1034 } |
1030 | 1035 |
1031 return combined_keys; | 1036 return combined_keys; |
1032 } | 1037 } |
1033 | 1038 |
1034 void AddElementsToKeyAccumulator(Handle<JSObject> receiver, | 1039 void AddElementsToKeyAccumulator(Handle<JSObject> receiver, |
(...skipping 1263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2298 } | 2303 } |
2299 | 2304 |
2300 static uint32_t GetCapacityImpl(JSObject* holder, | 2305 static uint32_t GetCapacityImpl(JSObject* holder, |
2301 FixedArrayBase* backing_store) { | 2306 FixedArrayBase* backing_store) { |
2302 FixedArray* parameter_map = FixedArray::cast(backing_store); | 2307 FixedArray* parameter_map = FixedArray::cast(backing_store); |
2303 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); | 2308 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); |
2304 return parameter_map->length() - 2 + | 2309 return parameter_map->length() - 2 + |
2305 ArgumentsAccessor::GetCapacityImpl(holder, arguments); | 2310 ArgumentsAccessor::GetCapacityImpl(holder, arguments); |
2306 } | 2311 } |
2307 | 2312 |
| 2313 static uint32_t GetMaxNumberOfEntries(JSObject* holder, |
| 2314 FixedArrayBase* backing_store) { |
| 2315 FixedArray* parameter_map = FixedArray::cast(backing_store); |
| 2316 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); |
| 2317 return parameter_map->length() - 2 + |
| 2318 ArgumentsAccessor::GetMaxNumberOfEntries(holder, arguments); |
| 2319 } |
| 2320 |
2308 static void AddElementsToKeyAccumulatorImpl(Handle<JSObject> receiver, | 2321 static void AddElementsToKeyAccumulatorImpl(Handle<JSObject> receiver, |
2309 KeyAccumulator* accumulator, | 2322 KeyAccumulator* accumulator, |
2310 AddKeyConversion convert) { | 2323 AddKeyConversion convert) { |
2311 FixedArrayBase* elements = receiver->elements(); | 2324 FixedArrayBase* elements = receiver->elements(); |
2312 uint32_t length = GetCapacityImpl(*receiver, elements); | 2325 uint32_t length = GetCapacityImpl(*receiver, elements); |
2313 for (uint32_t entry = 0; entry < length; entry++) { | 2326 for (uint32_t entry = 0; entry < length; entry++) { |
2314 if (!HasEntryImpl(elements, entry)) continue; | 2327 if (!HasEntryImpl(elements, entry)) continue; |
2315 Handle<Object> value = GetImpl(elements, entry); | 2328 Handle<Object> value = GetImpl(elements, entry); |
2316 accumulator->AddKey(value, convert); | 2329 accumulator->AddKey(value, convert); |
2317 } | 2330 } |
(...skipping 712 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3030 insertion_index += len; | 3043 insertion_index += len; |
3031 } | 3044 } |
3032 | 3045 |
3033 DCHECK_EQ(insertion_index, result_len); | 3046 DCHECK_EQ(insertion_index, result_len); |
3034 return result_array; | 3047 return result_array; |
3035 } | 3048 } |
3036 | 3049 |
3037 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; | 3050 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; |
3038 } // namespace internal | 3051 } // namespace internal |
3039 } // namespace v8 | 3052 } // namespace v8 |
OLD | NEW |