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 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
438 isolate->builtins()->builtin(Builtins::kFunctionPrototypeApply); | 438 isolate->builtins()->builtin(Builtins::kFunctionPrototypeApply); |
439 if (raw_frame->unchecked_code() == apply_builtin) { | 439 if (raw_frame->unchecked_code() == apply_builtin) { |
440 PrintF("apply from "); | 440 PrintF("apply from "); |
441 it.Advance(); | 441 it.Advance(); |
442 raw_frame = it.frame(); | 442 raw_frame = it.frame(); |
443 } | 443 } |
444 } | 444 } |
445 JavaScriptFrame::PrintTop(isolate, stdout, false, true); | 445 JavaScriptFrame::PrintTop(isolate, stdout, false, true); |
446 } | 446 } |
447 | 447 |
448 static void SortIndices(Handle<FixedArray> indices, uint32_t sort_size, | |
449 bool emit_write_barrier = true) { | |
Jakob Kummerow
2016/05/23 16:25:21
Consider using the existing enum WriteBarrierMode
Camillo Bruni
2016/05/23 19:10:13
updated.
| |
450 struct { | |
451 bool operator()(Object* a, Object* b) { | |
452 if (!a->IsUndefined()) { | |
453 if (b->IsUndefined()) return true; | |
454 return a->Number() < b->Number(); | |
455 } | |
456 return !b->IsUndefined(); | |
Jakob Kummerow
2016/05/23 16:25:21
I'm pretty sure this condition is inverted, i.e. y
Camillo Bruni
2016/05/23 19:10:13
good catch!
you're right, if b is smaller than a r
| |
457 } | |
458 } cmp; | |
459 Object** start = | |
460 reinterpret_cast<Object**>(indices->GetFirstElementAddress()); | |
461 std::sort(start, start + sort_size, cmp); | |
462 if (emit_write_barrier) { | |
463 FIXED_ARRAY_ELEMENTS_WRITE_BARRIER(indices->GetIsolate()->heap(), *indices, | |
464 0, sort_size); | |
465 } | |
466 } | |
448 | 467 |
449 // Base class for element handler implementations. Contains the | 468 // Base class for element handler implementations. Contains the |
450 // the common logic for objects with different ElementsKinds. | 469 // the common logic for objects with different ElementsKinds. |
451 // Subclasses must specialize method for which the element | 470 // Subclasses must specialize method for which the element |
452 // implementation differs from the base class implementation. | 471 // implementation differs from the base class implementation. |
453 // | 472 // |
454 // This class is intended to be used in the following way: | 473 // This class is intended to be used in the following way: |
455 // | 474 // |
456 // class SomeElementsAccessor : | 475 // class SomeElementsAccessor : |
457 // public ElementsAccessorBase<SomeElementsAccessor, | 476 // public ElementsAccessorBase<SomeElementsAccessor, |
(...skipping 398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
856 return Subclass::CollectValuesOrEntriesImpl( | 875 return Subclass::CollectValuesOrEntriesImpl( |
857 isolate, object, values_or_entries, get_entries, nof_items, filter); | 876 isolate, object, values_or_entries, get_entries, nof_items, filter); |
858 } | 877 } |
859 | 878 |
860 static Maybe<bool> CollectValuesOrEntriesImpl( | 879 static Maybe<bool> CollectValuesOrEntriesImpl( |
861 Isolate* isolate, Handle<JSObject> object, | 880 Isolate* isolate, Handle<JSObject> object, |
862 Handle<FixedArray> values_or_entries, bool get_entries, int* nof_items, | 881 Handle<FixedArray> values_or_entries, bool get_entries, int* nof_items, |
863 PropertyFilter filter) { | 882 PropertyFilter filter) { |
864 int count = 0; | 883 int count = 0; |
865 KeyAccumulator accumulator(isolate, OWN_ONLY, ALL_PROPERTIES); | 884 KeyAccumulator accumulator(isolate, OWN_ONLY, ALL_PROPERTIES); |
866 accumulator.NextPrototype(); | |
867 Subclass::CollectElementIndicesImpl( | 885 Subclass::CollectElementIndicesImpl( |
868 object, handle(object->elements(), isolate), &accumulator); | 886 object, handle(object->elements(), isolate), &accumulator); |
869 Handle<FixedArray> keys = accumulator.GetKeys(); | 887 Handle<FixedArray> keys = accumulator.GetKeys(); |
870 | 888 |
871 for (int i = 0; i < keys->length(); ++i) { | 889 for (int i = 0; i < keys->length(); ++i) { |
872 Handle<Object> key(keys->get(i), isolate); | 890 Handle<Object> key(keys->get(i), isolate); |
873 Handle<Object> value; | 891 Handle<Object> value; |
874 uint32_t index; | 892 uint32_t index; |
875 if (!key->ToUint32(&index)) continue; | 893 if (!key->ToUint32(&index)) continue; |
876 | 894 |
(...skipping 27 matching lines...) Expand all Loading... | |
904 Subclass::CollectElementIndicesImpl(object, backing_store, keys); | 922 Subclass::CollectElementIndicesImpl(object, backing_store, keys); |
905 } | 923 } |
906 | 924 |
907 static void CollectElementIndicesImpl(Handle<JSObject> object, | 925 static void CollectElementIndicesImpl(Handle<JSObject> object, |
908 Handle<FixedArrayBase> backing_store, | 926 Handle<FixedArrayBase> backing_store, |
909 KeyAccumulator* keys) { | 927 KeyAccumulator* keys) { |
910 DCHECK_NE(DICTIONARY_ELEMENTS, kind()); | 928 DCHECK_NE(DICTIONARY_ELEMENTS, kind()); |
911 // Non-dictionary elements can't have all-can-read accessors. | 929 // Non-dictionary elements can't have all-can-read accessors. |
912 uint32_t length = GetIterationLength(*object, *backing_store); | 930 uint32_t length = GetIterationLength(*object, *backing_store); |
913 PropertyFilter filter = keys->filter(); | 931 PropertyFilter filter = keys->filter(); |
932 Factory* factory = keys->isolate()->factory(); | |
914 for (uint32_t i = 0; i < length; i++) { | 933 for (uint32_t i = 0; i < length; i++) { |
915 if (Subclass::HasElementImpl(object, i, backing_store, filter)) { | 934 if (Subclass::HasElementImpl(object, i, backing_store, filter)) { |
916 keys->AddKey(i); | 935 keys->AddKey(factory->NewNumberFromUint(i)); |
917 } | 936 } |
918 } | 937 } |
919 } | 938 } |
920 | 939 |
921 static Handle<FixedArray> DirectCollectElementIndicesImpl( | 940 static Handle<FixedArray> DirectCollectElementIndicesImpl( |
922 Isolate* isolate, Handle<JSObject> object, | 941 Isolate* isolate, Handle<JSObject> object, |
923 Handle<FixedArrayBase> backing_store, GetKeysConversion convert, | 942 Handle<FixedArrayBase> backing_store, GetKeysConversion convert, |
924 PropertyFilter filter, Handle<FixedArray> list, uint32_t* nof_indices, | 943 PropertyFilter filter, Handle<FixedArray> list, uint32_t* nof_indices, |
925 uint32_t insertion_index = 0) { | 944 uint32_t insertion_index = 0) { |
926 uint32_t length = Subclass::GetIterationLength(*object, *backing_store); | 945 uint32_t length = Subclass::GetIterationLength(*object, *backing_store); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
961 // Collect the element indices into a new list. | 980 // Collect the element indices into a new list. |
962 uint32_t nof_indices = 0; | 981 uint32_t nof_indices = 0; |
963 Handle<FixedArray> combined_keys = | 982 Handle<FixedArray> combined_keys = |
964 isolate->factory()->NewFixedArray(initial_list_length); | 983 isolate->factory()->NewFixedArray(initial_list_length); |
965 combined_keys = Subclass::DirectCollectElementIndicesImpl( | 984 combined_keys = Subclass::DirectCollectElementIndicesImpl( |
966 isolate, object, backing_store, convert, filter, combined_keys, | 985 isolate, object, backing_store, convert, filter, combined_keys, |
967 &nof_indices); | 986 &nof_indices); |
968 | 987 |
969 // Sort the indices list if necessary. | 988 // Sort the indices list if necessary. |
970 if (IsDictionaryElementsKind(kind()) || IsSloppyArgumentsElements(kind())) { | 989 if (IsDictionaryElementsKind(kind()) || IsSloppyArgumentsElements(kind())) { |
971 struct { | 990 SortIndices(combined_keys, nof_indices, false); |
972 bool operator()(Object* a, Object* b) { | |
973 if (!a->IsUndefined()) { | |
974 if (b->IsUndefined()) return true; | |
975 return a->Number() < b->Number(); | |
976 } | |
977 return !b->IsUndefined(); | |
978 } | |
979 } cmp; | |
980 Object** start = | |
981 reinterpret_cast<Object**>(combined_keys->GetFirstElementAddress()); | |
982 std::sort(start, start + nof_indices, cmp); | |
983 uint32_t array_length = 0; | 991 uint32_t array_length = 0; |
984 // Indices from dictionary elements should only be converted after | 992 // Indices from dictionary elements should only be converted after |
985 // sorting. | 993 // sorting. |
986 if (convert == CONVERT_TO_STRING) { | 994 if (convert == CONVERT_TO_STRING) { |
987 for (uint32_t i = 0; i < nof_indices; i++) { | 995 for (uint32_t i = 0; i < nof_indices; i++) { |
988 Handle<Object> index_string = isolate->factory()->Uint32ToString( | 996 Handle<Object> index_string = isolate->factory()->Uint32ToString( |
989 combined_keys->get(i)->Number()); | 997 combined_keys->get(i)->Number()); |
990 combined_keys->set(i, *index_string); | 998 combined_keys->set(i, *index_string); |
991 } | 999 } |
992 } else if (!(object->IsJSArray() && | 1000 } else if (!(object->IsJSArray() && |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1075 | 1083 |
1076 class DictionaryElementsAccessor | 1084 class DictionaryElementsAccessor |
1077 : public ElementsAccessorBase<DictionaryElementsAccessor, | 1085 : public ElementsAccessorBase<DictionaryElementsAccessor, |
1078 ElementsKindTraits<DICTIONARY_ELEMENTS> > { | 1086 ElementsKindTraits<DICTIONARY_ELEMENTS> > { |
1079 public: | 1087 public: |
1080 explicit DictionaryElementsAccessor(const char* name) | 1088 explicit DictionaryElementsAccessor(const char* name) |
1081 : ElementsAccessorBase<DictionaryElementsAccessor, | 1089 : ElementsAccessorBase<DictionaryElementsAccessor, |
1082 ElementsKindTraits<DICTIONARY_ELEMENTS> >(name) {} | 1090 ElementsKindTraits<DICTIONARY_ELEMENTS> >(name) {} |
1083 | 1091 |
1084 static uint32_t GetIterationLength(JSObject* receiver, | 1092 static uint32_t GetIterationLength(JSObject* receiver, |
1085 FixedArrayBase* elements) { | 1093 FixedArrayBase* backing_store) { |
1086 uint32_t length; | 1094 SeededNumberDictionary* dict = SeededNumberDictionary::cast(backing_store); |
1087 if (receiver->IsJSArray()) { | 1095 return dict->NumberOfElements(); |
Jakob Kummerow
2016/05/23 16:25:21
In existing code, GetIterationLength is clearly ex
Camillo Bruni
2016/05/23 19:10:13
Renamed to GetMaxNumberOfElements, though the rest
| |
1088 // Special-case GetIterationLength for dictionary elements since the | |
1089 // length of the array might be a HeapNumber. | |
1090 JSArray::cast(receiver)->length()->ToArrayLength(&length); | |
1091 } else { | |
1092 length = GetCapacityImpl(receiver, elements); | |
1093 } | |
1094 return length; | |
1095 } | 1096 } |
1096 | 1097 |
1097 static void SetLengthImpl(Isolate* isolate, Handle<JSArray> array, | 1098 static void SetLengthImpl(Isolate* isolate, Handle<JSArray> array, |
1098 uint32_t length, | 1099 uint32_t length, |
1099 Handle<FixedArrayBase> backing_store) { | 1100 Handle<FixedArrayBase> backing_store) { |
1100 Handle<SeededNumberDictionary> dict = | 1101 Handle<SeededNumberDictionary> dict = |
1101 Handle<SeededNumberDictionary>::cast(backing_store); | 1102 Handle<SeededNumberDictionary>::cast(backing_store); |
1102 int capacity = dict->Capacity(); | 1103 int capacity = dict->Capacity(); |
1103 uint32_t old_length = 0; | 1104 uint32_t old_length = 0; |
1104 CHECK(array->length()->ToArrayLength(&old_length)); | 1105 CHECK(array->length()->ToArrayLength(&old_length)); |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1306 if (raw_key == undefined || raw_key == the_hole) { | 1307 if (raw_key == undefined || raw_key == the_hole) { |
1307 return kMaxUInt32; | 1308 return kMaxUInt32; |
1308 } | 1309 } |
1309 return FilterKey(dictionary, entry, raw_key, filter); | 1310 return FilterKey(dictionary, entry, raw_key, filter); |
1310 } | 1311 } |
1311 | 1312 |
1312 static void CollectElementIndicesImpl(Handle<JSObject> object, | 1313 static void CollectElementIndicesImpl(Handle<JSObject> object, |
1313 Handle<FixedArrayBase> backing_store, | 1314 Handle<FixedArrayBase> backing_store, |
1314 KeyAccumulator* keys) { | 1315 KeyAccumulator* keys) { |
1315 if (keys->filter() & SKIP_STRINGS) return; | 1316 if (keys->filter() & SKIP_STRINGS) return; |
1316 Isolate* isolate = keys->isolate(); | 1317 Factory* factory = keys->isolate()->factory(); |
1317 Handle<Object> undefined = isolate->factory()->undefined_value(); | 1318 Handle<Object> undefined = factory->undefined_value(); |
1318 Handle<Object> the_hole = isolate->factory()->the_hole_value(); | 1319 Handle<Object> the_hole = factory->the_hole_value(); |
1319 Handle<SeededNumberDictionary> dictionary = | 1320 Handle<SeededNumberDictionary> dictionary = |
1320 Handle<SeededNumberDictionary>::cast(backing_store); | 1321 Handle<SeededNumberDictionary>::cast(backing_store); |
1321 int capacity = dictionary->Capacity(); | 1322 int capacity = dictionary->Capacity(); |
1323 Handle<FixedArray> elements = | |
1324 factory->NewFixedArray(GetIterationLength(*object, *backing_store)); | |
1325 int insertion_index = 0; | |
1322 PropertyFilter filter = keys->filter(); | 1326 PropertyFilter filter = keys->filter(); |
1323 for (int i = 0; i < capacity; i++) { | 1327 for (int i = 0; i < capacity; i++) { |
1324 uint32_t key = | 1328 uint32_t key = |
1325 GetKeyForEntryImpl(dictionary, i, filter, *undefined, *the_hole); | 1329 GetKeyForEntryImpl(dictionary, i, filter, *undefined, *the_hole); |
1326 if (key == kMaxUInt32) continue; | 1330 if (key == kMaxUInt32) continue; |
1327 keys->AddKey(key); | 1331 elements->set(insertion_index, *factory->NewNumberFromUint(key)); |
1332 insertion_index++; | |
1328 } | 1333 } |
1329 | 1334 SortIndices(elements, insertion_index); |
1330 keys->SortCurrentElementsList(); | 1335 for (int i = 0; i < insertion_index; i++) { |
1336 keys->AddKey(elements->get(i)); | |
1337 } | |
1331 } | 1338 } |
1332 | 1339 |
1333 static Handle<FixedArray> DirectCollectElementIndicesImpl( | 1340 static Handle<FixedArray> DirectCollectElementIndicesImpl( |
1334 Isolate* isolate, Handle<JSObject> object, | 1341 Isolate* isolate, Handle<JSObject> object, |
1335 Handle<FixedArrayBase> backing_store, GetKeysConversion convert, | 1342 Handle<FixedArrayBase> backing_store, GetKeysConversion convert, |
1336 PropertyFilter filter, Handle<FixedArray> list, uint32_t* nof_indices, | 1343 PropertyFilter filter, Handle<FixedArray> list, uint32_t* nof_indices, |
1337 uint32_t insertion_index = 0) { | 1344 uint32_t insertion_index = 0) { |
1338 if (filter & SKIP_STRINGS) return list; | 1345 if (filter & SKIP_STRINGS) return list; |
1339 if (filter & ONLY_ALL_CAN_READ) return list; | 1346 if (filter & ONLY_ALL_CAN_READ) return list; |
1340 | 1347 |
(...skipping 1038 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2379 // would enable GC of the context. | 2386 // would enable GC of the context. |
2380 parameter_map->set_the_hole(entry + 2); | 2387 parameter_map->set_the_hole(entry + 2); |
2381 } else { | 2388 } else { |
2382 Subclass::DeleteFromArguments(obj, entry - length); | 2389 Subclass::DeleteFromArguments(obj, entry - length); |
2383 } | 2390 } |
2384 } | 2391 } |
2385 | 2392 |
2386 static void CollectElementIndicesImpl(Handle<JSObject> object, | 2393 static void CollectElementIndicesImpl(Handle<JSObject> object, |
2387 Handle<FixedArrayBase> backing_store, | 2394 Handle<FixedArrayBase> backing_store, |
2388 KeyAccumulator* keys) { | 2395 KeyAccumulator* keys) { |
2389 FixedArray* parameter_map = FixedArray::cast(*backing_store); | 2396 Isolate* isolate = keys->isolate(); |
2390 uint32_t length = parameter_map->length() - 2; | 2397 uint32_t nof_indices = 0; |
2391 for (uint32_t i = 0; i < length; ++i) { | 2398 Handle<FixedArray> indices = isolate->factory()->NewFixedArray( |
2392 if (!parameter_map->get(i + 2)->IsTheHole()) { | 2399 GetCapacityImpl(*object, *backing_store)); |
2393 keys->AddKey(i); | 2400 DirectCollectElementIndicesImpl(isolate, object, backing_store, |
2394 } | 2401 KEEP_NUMBERS, ENUMERABLE_STRINGS, indices, |
2395 } | 2402 &nof_indices); |
2396 | 2403 SortIndices(indices, nof_indices); |
2397 Handle<FixedArrayBase> store(FixedArrayBase::cast(parameter_map->get(1))); | 2404 for (uint32_t i = 0; i < nof_indices; i++) { |
2398 ArgumentsAccessor::CollectElementIndicesImpl(object, store, keys); | 2405 keys->AddKey(indices->get(i)); |
2399 if (Subclass::kind() == FAST_SLOPPY_ARGUMENTS_ELEMENTS) { | |
2400 keys->SortCurrentElementsList(); | |
2401 } | 2406 } |
2402 } | 2407 } |
2403 | 2408 |
2404 static Handle<FixedArray> DirectCollectElementIndicesImpl( | 2409 static Handle<FixedArray> DirectCollectElementIndicesImpl( |
2405 Isolate* isolate, Handle<JSObject> object, | 2410 Isolate* isolate, Handle<JSObject> object, |
2406 Handle<FixedArrayBase> backing_store, GetKeysConversion convert, | 2411 Handle<FixedArrayBase> backing_store, GetKeysConversion convert, |
2407 PropertyFilter filter, Handle<FixedArray> list, uint32_t* nof_indices, | 2412 PropertyFilter filter, Handle<FixedArray> list, uint32_t* nof_indices, |
2408 uint32_t insertion_index = 0) { | 2413 uint32_t insertion_index = 0) { |
2409 FixedArray* parameter_map = FixedArray::cast(*backing_store); | 2414 FixedArray* parameter_map = FixedArray::cast(*backing_store); |
2410 uint32_t length = parameter_map->length() - 2; | 2415 uint32_t length = parameter_map->length() - 2; |
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2738 convert); | 2743 convert); |
2739 } | 2744 } |
2740 BackingStoreAccessor::AddElementsToKeyAccumulatorImpl(receiver, accumulator, | 2745 BackingStoreAccessor::AddElementsToKeyAccumulatorImpl(receiver, accumulator, |
2741 convert); | 2746 convert); |
2742 } | 2747 } |
2743 | 2748 |
2744 static void CollectElementIndicesImpl(Handle<JSObject> object, | 2749 static void CollectElementIndicesImpl(Handle<JSObject> object, |
2745 Handle<FixedArrayBase> backing_store, | 2750 Handle<FixedArrayBase> backing_store, |
2746 KeyAccumulator* keys) { | 2751 KeyAccumulator* keys) { |
2747 uint32_t length = GetString(*object)->length(); | 2752 uint32_t length = GetString(*object)->length(); |
2753 Factory* factory = keys->isolate()->factory(); | |
2748 for (uint32_t i = 0; i < length; i++) { | 2754 for (uint32_t i = 0; i < length; i++) { |
2749 keys->AddKey(i); | 2755 keys->AddKey(factory->NewNumberFromUint(i)); |
2750 } | 2756 } |
2751 BackingStoreAccessor::CollectElementIndicesImpl(object, backing_store, | 2757 BackingStoreAccessor::CollectElementIndicesImpl(object, backing_store, |
2752 keys); | 2758 keys); |
2753 } | 2759 } |
2754 | 2760 |
2755 static void GrowCapacityAndConvertImpl(Handle<JSObject> object, | 2761 static void GrowCapacityAndConvertImpl(Handle<JSObject> object, |
2756 uint32_t capacity) { | 2762 uint32_t capacity) { |
2757 Handle<FixedArrayBase> old_elements(object->elements()); | 2763 Handle<FixedArrayBase> old_elements(object->elements()); |
2758 ElementsKind from_kind = object->GetElementsKind(); | 2764 ElementsKind from_kind = object->GetElementsKind(); |
2759 // This method should only be called if there's a reason to update the | 2765 // This method should only be called if there's a reason to update the |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3024 insertion_index += len; | 3030 insertion_index += len; |
3025 } | 3031 } |
3026 | 3032 |
3027 DCHECK_EQ(insertion_index, result_len); | 3033 DCHECK_EQ(insertion_index, result_len); |
3028 return result_array; | 3034 return result_array; |
3029 } | 3035 } |
3030 | 3036 |
3031 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; | 3037 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; |
3032 } // namespace internal | 3038 } // namespace internal |
3033 } // namespace v8 | 3039 } // namespace v8 |
OLD | NEW |