| 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 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 499 return ElementsAccessorSubclass::IsPackedImpl(holder, backing_store, start, | 499 return ElementsAccessorSubclass::IsPackedImpl(holder, backing_store, start, |
| 500 end); | 500 end); |
| 501 } | 501 } |
| 502 | 502 |
| 503 static bool IsPackedImpl(Handle<JSObject> holder, | 503 static bool IsPackedImpl(Handle<JSObject> holder, |
| 504 Handle<FixedArrayBase> backing_store, uint32_t start, | 504 Handle<FixedArrayBase> backing_store, uint32_t start, |
| 505 uint32_t end) { | 505 uint32_t end) { |
| 506 if (IsFastPackedElementsKind(kind())) return true; | 506 if (IsFastPackedElementsKind(kind())) return true; |
| 507 for (uint32_t i = start; i < end; i++) { | 507 for (uint32_t i = start; i < end; i++) { |
| 508 if (!ElementsAccessorSubclass::HasElementImpl(holder, i, backing_store, | 508 if (!ElementsAccessorSubclass::HasElementImpl(holder, i, backing_store, |
| 509 NONE)) { | 509 ALL_PROPERTIES)) { |
| 510 return false; | 510 return false; |
| 511 } | 511 } |
| 512 } | 512 } |
| 513 return true; | 513 return true; |
| 514 } | 514 } |
| 515 | 515 |
| 516 static void TryTransitionResultArrayToPacked(Handle<JSArray> array) { | 516 static void TryTransitionResultArrayToPacked(Handle<JSArray> array) { |
| 517 if (!IsHoleyElementsKind(kind())) return; | 517 if (!IsHoleyElementsKind(kind())) return; |
| 518 int length = Smi::cast(array->length())->value(); | 518 int length = Smi::cast(array->length())->value(); |
| 519 Handle<FixedArrayBase> backing_store(array->elements()); | 519 Handle<FixedArrayBase> backing_store(array->elements()); |
| 520 if (!ElementsAccessorSubclass::IsPackedImpl(array, backing_store, 0, | 520 if (!ElementsAccessorSubclass::IsPackedImpl(array, backing_store, 0, |
| 521 length)) { | 521 length)) { |
| 522 return; | 522 return; |
| 523 } | 523 } |
| 524 ElementsKind packed_kind = GetPackedElementsKind(kind()); | 524 ElementsKind packed_kind = GetPackedElementsKind(kind()); |
| 525 Handle<Map> new_map = | 525 Handle<Map> new_map = |
| 526 JSObject::GetElementsTransitionMap(array, packed_kind); | 526 JSObject::GetElementsTransitionMap(array, packed_kind); |
| 527 JSObject::MigrateToMap(array, new_map); | 527 JSObject::MigrateToMap(array, new_map); |
| 528 if (FLAG_trace_elements_transitions) { | 528 if (FLAG_trace_elements_transitions) { |
| 529 JSObject::PrintElementsTransition(stdout, array, kind(), backing_store, | 529 JSObject::PrintElementsTransition(stdout, array, kind(), backing_store, |
| 530 packed_kind, backing_store); | 530 packed_kind, backing_store); |
| 531 } | 531 } |
| 532 } | 532 } |
| 533 | 533 |
| 534 bool HasElement(Handle<JSObject> holder, uint32_t index, | 534 bool HasElement(Handle<JSObject> holder, uint32_t index, |
| 535 Handle<FixedArrayBase> backing_store, | 535 Handle<FixedArrayBase> backing_store, |
| 536 PropertyAttributes filter) final { | 536 PropertyFilter filter) final { |
| 537 return ElementsAccessorSubclass::HasElementImpl(holder, index, | 537 return ElementsAccessorSubclass::HasElementImpl(holder, index, |
| 538 backing_store, filter); | 538 backing_store, filter); |
| 539 } | 539 } |
| 540 | 540 |
| 541 static bool HasElementImpl(Handle<JSObject> holder, uint32_t index, | 541 static bool HasElementImpl(Handle<JSObject> holder, uint32_t index, |
| 542 Handle<FixedArrayBase> backing_store, | 542 Handle<FixedArrayBase> backing_store, |
| 543 PropertyAttributes filter) { | 543 PropertyFilter filter) { |
| 544 return ElementsAccessorSubclass::GetEntryForIndexImpl( | 544 return ElementsAccessorSubclass::GetEntryForIndexImpl( |
| 545 *holder, *backing_store, index, filter) != kMaxUInt32; | 545 *holder, *backing_store, index, filter) != kMaxUInt32; |
| 546 } | 546 } |
| 547 | 547 |
| 548 Handle<Object> Get(Handle<FixedArrayBase> backing_store, | 548 Handle<Object> Get(Handle<FixedArrayBase> backing_store, |
| 549 uint32_t entry) final { | 549 uint32_t entry) final { |
| 550 return ElementsAccessorSubclass::GetImpl(backing_store, entry); | 550 return ElementsAccessorSubclass::GetImpl(backing_store, entry); |
| 551 } | 551 } |
| 552 | 552 |
| 553 static Handle<Object> GetImpl(Handle<FixedArrayBase> backing_store, | 553 static Handle<Object> GetImpl(Handle<FixedArrayBase> backing_store, |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 850 // copying from object with fast double elements to object with object | 850 // copying from object with fast double elements to object with object |
| 851 // elements. In all the other cases there are no allocations performed and | 851 // elements. In all the other cases there are no allocations performed and |
| 852 // handle creation causes noticeable performance degradation of the builtin. | 852 // handle creation causes noticeable performance degradation of the builtin. |
| 853 ElementsAccessorSubclass::CopyElementsImpl( | 853 ElementsAccessorSubclass::CopyElementsImpl( |
| 854 from, from_start, *to, from_kind, to_start, packed_size, copy_size); | 854 from, from_start, *to, from_kind, to_start, packed_size, copy_size); |
| 855 } | 855 } |
| 856 | 856 |
| 857 static void CollectElementIndicesImpl(Handle<JSObject> object, | 857 static void CollectElementIndicesImpl(Handle<JSObject> object, |
| 858 Handle<FixedArrayBase> backing_store, | 858 Handle<FixedArrayBase> backing_store, |
| 859 KeyAccumulator* keys, uint32_t range, | 859 KeyAccumulator* keys, uint32_t range, |
| 860 PropertyAttributes filter, | 860 PropertyFilter filter, |
| 861 uint32_t offset) { | 861 uint32_t offset) { |
| 862 uint32_t length = 0; | 862 uint32_t length = 0; |
| 863 if (object->IsJSArray()) { | 863 if (object->IsJSArray()) { |
| 864 length = Smi::cast(JSArray::cast(*object)->length())->value(); | 864 length = Smi::cast(JSArray::cast(*object)->length())->value(); |
| 865 } else { | 865 } else { |
| 866 length = | 866 length = |
| 867 ElementsAccessorSubclass::GetCapacityImpl(*object, *backing_store); | 867 ElementsAccessorSubclass::GetCapacityImpl(*object, *backing_store); |
| 868 } | 868 } |
| 869 if (range < length) length = range; | 869 if (range < length) length = range; |
| 870 for (uint32_t i = offset; i < length; i++) { | 870 for (uint32_t i = offset; i < length; i++) { |
| 871 if (!ElementsAccessorSubclass::HasElementImpl(object, i, backing_store, | 871 if (!ElementsAccessorSubclass::HasElementImpl(object, i, backing_store, |
| 872 filter)) | 872 filter)) |
| 873 continue; | 873 continue; |
| 874 keys->AddKey(i); | 874 keys->AddKey(i); |
| 875 } | 875 } |
| 876 } | 876 } |
| 877 | 877 |
| 878 void CollectElementIndices(Handle<JSObject> object, | 878 void CollectElementIndices(Handle<JSObject> object, |
| 879 Handle<FixedArrayBase> backing_store, | 879 Handle<FixedArrayBase> backing_store, |
| 880 KeyAccumulator* keys, uint32_t range, | 880 KeyAccumulator* keys, uint32_t range, |
| 881 PropertyAttributes filter, uint32_t offset) final { | 881 PropertyFilter filter, uint32_t offset) final { |
| 882 ElementsAccessorSubclass::CollectElementIndicesImpl( | 882 ElementsAccessorSubclass::CollectElementIndicesImpl( |
| 883 object, backing_store, keys, range, filter, offset); | 883 object, backing_store, keys, range, filter, offset); |
| 884 }; | 884 }; |
| 885 | 885 |
| 886 void AddElementsToKeyAccumulator(Handle<JSObject> receiver, | 886 void AddElementsToKeyAccumulator(Handle<JSObject> receiver, |
| 887 KeyAccumulator* accumulator, | 887 KeyAccumulator* accumulator, |
| 888 AddKeyConversion convert) final { | 888 AddKeyConversion convert) final { |
| 889 Handle<FixedArrayBase> from(receiver->elements()); | 889 Handle<FixedArrayBase> from(receiver->elements()); |
| 890 uint32_t add_length = | 890 uint32_t add_length = |
| 891 ElementsAccessorSubclass::GetCapacityImpl(*receiver, *from); | 891 ElementsAccessorSubclass::GetCapacityImpl(*receiver, *from); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 914 return true; | 914 return true; |
| 915 } | 915 } |
| 916 | 916 |
| 917 static uint32_t GetIndexForEntryImpl(FixedArrayBase* backing_store, | 917 static uint32_t GetIndexForEntryImpl(FixedArrayBase* backing_store, |
| 918 uint32_t entry) { | 918 uint32_t entry) { |
| 919 return entry; | 919 return entry; |
| 920 } | 920 } |
| 921 | 921 |
| 922 static uint32_t GetEntryForIndexImpl(JSObject* holder, | 922 static uint32_t GetEntryForIndexImpl(JSObject* holder, |
| 923 FixedArrayBase* backing_store, | 923 FixedArrayBase* backing_store, |
| 924 uint32_t index, | 924 uint32_t index, PropertyFilter filter) { |
| 925 PropertyAttributes filter) { | |
| 926 if (IsHoleyElementsKind(kind())) { | 925 if (IsHoleyElementsKind(kind())) { |
| 927 return index < ElementsAccessorSubclass::GetCapacityImpl(holder, | 926 return index < ElementsAccessorSubclass::GetCapacityImpl(holder, |
| 928 backing_store) && | 927 backing_store) && |
| 929 !BackingStore::cast(backing_store)->is_the_hole(index) | 928 !BackingStore::cast(backing_store)->is_the_hole(index) |
| 930 ? index | 929 ? index |
| 931 : kMaxUInt32; | 930 : kMaxUInt32; |
| 932 } else { | 931 } else { |
| 933 uint32_t length = | 932 uint32_t length = |
| 934 holder->IsJSArray() | 933 holder->IsJSArray() |
| 935 ? static_cast<uint32_t>( | 934 ? static_cast<uint32_t>( |
| 936 Smi::cast(JSArray::cast(holder)->length())->value()) | 935 Smi::cast(JSArray::cast(holder)->length())->value()) |
| 937 : ElementsAccessorSubclass::GetCapacityImpl(holder, | 936 : ElementsAccessorSubclass::GetCapacityImpl(holder, |
| 938 backing_store); | 937 backing_store); |
| 939 return index < length ? index : kMaxUInt32; | 938 return index < length ? index : kMaxUInt32; |
| 940 } | 939 } |
| 941 } | 940 } |
| 942 | 941 |
| 943 uint32_t GetEntryForIndex(JSObject* holder, FixedArrayBase* backing_store, | 942 uint32_t GetEntryForIndex(JSObject* holder, FixedArrayBase* backing_store, |
| 944 uint32_t index) final { | 943 uint32_t index) final { |
| 945 return ElementsAccessorSubclass::GetEntryForIndexImpl(holder, backing_store, | 944 return ElementsAccessorSubclass::GetEntryForIndexImpl( |
| 946 index, NONE); | 945 holder, backing_store, index, ALL_PROPERTIES); |
| 947 } | 946 } |
| 948 | 947 |
| 949 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, | 948 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, |
| 950 uint32_t entry) { | 949 uint32_t entry) { |
| 951 return PropertyDetails(NONE, DATA, 0, PropertyCellType::kNoCell); | 950 return PropertyDetails(NONE, DATA, 0, PropertyCellType::kNoCell); |
| 952 } | 951 } |
| 953 | 952 |
| 954 PropertyDetails GetDetails(FixedArrayBase* backing_store, | 953 PropertyDetails GetDetails(FixedArrayBase* backing_store, |
| 955 uint32_t entry) final { | 954 uint32_t entry) final { |
| 956 return ElementsAccessorSubclass::GetDetailsImpl(backing_store, entry); | 955 return ElementsAccessorSubclass::GetDetailsImpl(backing_store, entry); |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1098 | 1097 |
| 1099 static uint32_t GetIndexForEntryImpl(FixedArrayBase* store, uint32_t entry) { | 1098 static uint32_t GetIndexForEntryImpl(FixedArrayBase* store, uint32_t entry) { |
| 1100 DisallowHeapAllocation no_gc; | 1099 DisallowHeapAllocation no_gc; |
| 1101 SeededNumberDictionary* dict = SeededNumberDictionary::cast(store); | 1100 SeededNumberDictionary* dict = SeededNumberDictionary::cast(store); |
| 1102 uint32_t result = 0; | 1101 uint32_t result = 0; |
| 1103 CHECK(dict->KeyAt(entry)->ToArrayIndex(&result)); | 1102 CHECK(dict->KeyAt(entry)->ToArrayIndex(&result)); |
| 1104 return result; | 1103 return result; |
| 1105 } | 1104 } |
| 1106 | 1105 |
| 1107 static uint32_t GetEntryForIndexImpl(JSObject* holder, FixedArrayBase* store, | 1106 static uint32_t GetEntryForIndexImpl(JSObject* holder, FixedArrayBase* store, |
| 1108 uint32_t index, | 1107 uint32_t index, PropertyFilter filter) { |
| 1109 PropertyAttributes filter) { | |
| 1110 DisallowHeapAllocation no_gc; | 1108 DisallowHeapAllocation no_gc; |
| 1111 SeededNumberDictionary* dictionary = SeededNumberDictionary::cast(store); | 1109 SeededNumberDictionary* dictionary = SeededNumberDictionary::cast(store); |
| 1112 int entry = dictionary->FindEntry(index); | 1110 int entry = dictionary->FindEntry(index); |
| 1113 if (entry == SeededNumberDictionary::kNotFound) return kMaxUInt32; | 1111 if (entry == SeededNumberDictionary::kNotFound) return kMaxUInt32; |
| 1114 if (filter != NONE) { | 1112 if (filter != ALL_PROPERTIES) { |
| 1115 PropertyDetails details = dictionary->DetailsAt(entry); | 1113 PropertyDetails details = dictionary->DetailsAt(entry); |
| 1116 PropertyAttributes attr = details.attributes(); | 1114 PropertyAttributes attr = details.attributes(); |
| 1117 if ((attr & filter) != 0) return kMaxUInt32; | 1115 if ((attr & filter) != 0) return kMaxUInt32; |
| 1118 } | 1116 } |
| 1119 return static_cast<uint32_t>(entry); | 1117 return static_cast<uint32_t>(entry); |
| 1120 } | 1118 } |
| 1121 | 1119 |
| 1122 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, | 1120 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, |
| 1123 uint32_t entry) { | 1121 uint32_t entry) { |
| 1124 return SeededNumberDictionary::cast(backing_store)->DetailsAt(entry); | 1122 return SeededNumberDictionary::cast(backing_store)->DetailsAt(entry); |
| 1125 } | 1123 } |
| 1126 | 1124 |
| 1127 static void CollectElementIndicesImpl(Handle<JSObject> object, | 1125 static void CollectElementIndicesImpl(Handle<JSObject> object, |
| 1128 Handle<FixedArrayBase> backing_store, | 1126 Handle<FixedArrayBase> backing_store, |
| 1129 KeyAccumulator* keys, uint32_t range, | 1127 KeyAccumulator* keys, uint32_t range, |
| 1130 PropertyAttributes filter, | 1128 PropertyFilter filter, |
| 1131 uint32_t offset) { | 1129 uint32_t offset) { |
| 1132 Handle<SeededNumberDictionary> dictionary = | 1130 Handle<SeededNumberDictionary> dictionary = |
| 1133 Handle<SeededNumberDictionary>::cast(backing_store); | 1131 Handle<SeededNumberDictionary>::cast(backing_store); |
| 1134 int capacity = dictionary->Capacity(); | 1132 int capacity = dictionary->Capacity(); |
| 1135 for (int i = 0; i < capacity; i++) { | 1133 for (int i = 0; i < capacity; i++) { |
| 1136 Object* k = dictionary->KeyAt(i); | 1134 Object* k = dictionary->KeyAt(i); |
| 1137 if (!dictionary->IsKey(k)) continue; | 1135 if (!dictionary->IsKey(k)) continue; |
| 1138 if (k->FilterKey(filter)) continue; | 1136 if (k->FilterKey(filter)) continue; |
| 1139 if (dictionary->IsDeleted(i)) continue; | 1137 if (dictionary->IsDeleted(i)) continue; |
| 1140 DCHECK(k->IsNumber()); | 1138 DCHECK(k->IsNumber()); |
| (...skipping 662 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1803 UNREACHABLE(); | 1801 UNREACHABLE(); |
| 1804 } | 1802 } |
| 1805 | 1803 |
| 1806 static uint32_t GetIndexForEntryImpl(FixedArrayBase* backing_store, | 1804 static uint32_t GetIndexForEntryImpl(FixedArrayBase* backing_store, |
| 1807 uint32_t entry) { | 1805 uint32_t entry) { |
| 1808 return entry; | 1806 return entry; |
| 1809 } | 1807 } |
| 1810 | 1808 |
| 1811 static uint32_t GetEntryForIndexImpl(JSObject* holder, | 1809 static uint32_t GetEntryForIndexImpl(JSObject* holder, |
| 1812 FixedArrayBase* backing_store, | 1810 FixedArrayBase* backing_store, |
| 1813 uint32_t index, | 1811 uint32_t index, PropertyFilter filter) { |
| 1814 PropertyAttributes filter) { | |
| 1815 return index < AccessorClass::GetCapacityImpl(holder, backing_store) | 1812 return index < AccessorClass::GetCapacityImpl(holder, backing_store) |
| 1816 ? index | 1813 ? index |
| 1817 : kMaxUInt32; | 1814 : kMaxUInt32; |
| 1818 } | 1815 } |
| 1819 | 1816 |
| 1820 static uint32_t GetCapacityImpl(JSObject* holder, | 1817 static uint32_t GetCapacityImpl(JSObject* holder, |
| 1821 FixedArrayBase* backing_store) { | 1818 FixedArrayBase* backing_store) { |
| 1822 JSArrayBufferView* view = JSArrayBufferView::cast(holder); | 1819 JSArrayBufferView* view = JSArrayBufferView::cast(holder); |
| 1823 if (view->WasNeutered()) return 0; | 1820 if (view->WasNeutered()) return 0; |
| 1824 return backing_store->length(); | 1821 return backing_store->length(); |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1938 FixedArray* parameter_map = FixedArray::cast(parameters); | 1935 FixedArray* parameter_map = FixedArray::cast(parameters); |
| 1939 uint32_t length = parameter_map->length() - 2; | 1936 uint32_t length = parameter_map->length() - 2; |
| 1940 if (entry < length) return entry; | 1937 if (entry < length) return entry; |
| 1941 | 1938 |
| 1942 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1939 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 1943 return ArgumentsAccessor::GetIndexForEntryImpl(arguments, entry - length); | 1940 return ArgumentsAccessor::GetIndexForEntryImpl(arguments, entry - length); |
| 1944 } | 1941 } |
| 1945 | 1942 |
| 1946 static uint32_t GetEntryForIndexImpl(JSObject* holder, | 1943 static uint32_t GetEntryForIndexImpl(JSObject* holder, |
| 1947 FixedArrayBase* parameters, | 1944 FixedArrayBase* parameters, |
| 1948 uint32_t index, | 1945 uint32_t index, PropertyFilter filter) { |
| 1949 PropertyAttributes filter) { | |
| 1950 FixedArray* parameter_map = FixedArray::cast(parameters); | 1946 FixedArray* parameter_map = FixedArray::cast(parameters); |
| 1951 Object* probe = GetParameterMapArg(parameter_map, index); | 1947 Object* probe = GetParameterMapArg(parameter_map, index); |
| 1952 if (!probe->IsTheHole()) return index; | 1948 if (!probe->IsTheHole()) return index; |
| 1953 | 1949 |
| 1954 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1950 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 1955 uint32_t entry = ArgumentsAccessor::GetEntryForIndexImpl(holder, arguments, | 1951 uint32_t entry = ArgumentsAccessor::GetEntryForIndexImpl(holder, arguments, |
| 1956 index, filter); | 1952 index, filter); |
| 1957 if (entry == kMaxUInt32) return entry; | 1953 if (entry == kMaxUInt32) return entry; |
| 1958 return (parameter_map->length() - 2) + entry; | 1954 return (parameter_map->length() - 2) + entry; |
| 1959 } | 1955 } |
| (...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2379 } | 2375 } |
| 2380 } | 2376 } |
| 2381 | 2377 |
| 2382 DCHECK(j == result_len); | 2378 DCHECK(j == result_len); |
| 2383 return result_array; | 2379 return result_array; |
| 2384 } | 2380 } |
| 2385 | 2381 |
| 2386 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; | 2382 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; |
| 2387 } // namespace internal | 2383 } // namespace internal |
| 2388 } // namespace v8 | 2384 } // namespace v8 |
| OLD | NEW |