Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(167)

Side by Side Diff: src/elements.cc

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

Powered by Google App Engine
This is Rietveld 408576698