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 500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
511 uint32_t end) final { | 511 uint32_t end) final { |
512 return ElementsAccessorSubclass::IsPackedImpl(holder, backing_store, start, | 512 return ElementsAccessorSubclass::IsPackedImpl(holder, backing_store, start, |
513 end); | 513 end); |
514 } | 514 } |
515 | 515 |
516 static bool IsPackedImpl(Handle<JSObject> holder, | 516 static bool IsPackedImpl(Handle<JSObject> holder, |
517 Handle<FixedArrayBase> backing_store, uint32_t start, | 517 Handle<FixedArrayBase> backing_store, uint32_t start, |
518 uint32_t end) { | 518 uint32_t end) { |
519 if (IsFastPackedElementsKind(kind())) return true; | 519 if (IsFastPackedElementsKind(kind())) return true; |
520 for (uint32_t i = start; i < end; i++) { | 520 for (uint32_t i = start; i < end; i++) { |
521 if (!ElementsAccessorSubclass::HasElementImpl(holder, i, backing_store)) { | 521 if (!ElementsAccessorSubclass::HasElementImpl(holder, i, backing_store, |
| 522 NONE)) { |
522 return false; | 523 return false; |
523 } | 524 } |
524 } | 525 } |
525 return true; | 526 return true; |
526 } | 527 } |
527 | 528 |
528 static void TryTransitionResultArrayToPacked(Handle<JSArray> array) { | 529 static void TryTransitionResultArrayToPacked(Handle<JSArray> array) { |
529 if (!IsHoleyElementsKind(kind())) return; | 530 if (!IsHoleyElementsKind(kind())) return; |
530 int length = Smi::cast(array->length())->value(); | 531 int length = Smi::cast(array->length())->value(); |
531 Handle<FixedArrayBase> backing_store(array->elements()); | 532 Handle<FixedArrayBase> backing_store(array->elements()); |
532 if (!ElementsAccessorSubclass::IsPackedImpl(array, backing_store, 0, | 533 if (!ElementsAccessorSubclass::IsPackedImpl(array, backing_store, 0, |
533 length)) { | 534 length)) { |
534 return; | 535 return; |
535 } | 536 } |
536 ElementsKind packed_kind = GetPackedElementsKind(kind()); | 537 ElementsKind packed_kind = GetPackedElementsKind(kind()); |
537 Handle<Map> new_map = | 538 Handle<Map> new_map = |
538 JSObject::GetElementsTransitionMap(array, packed_kind); | 539 JSObject::GetElementsTransitionMap(array, packed_kind); |
539 JSObject::MigrateToMap(array, new_map); | 540 JSObject::MigrateToMap(array, new_map); |
540 if (FLAG_trace_elements_transitions) { | 541 if (FLAG_trace_elements_transitions) { |
541 JSObject::PrintElementsTransition(stdout, array, kind(), backing_store, | 542 JSObject::PrintElementsTransition(stdout, array, kind(), backing_store, |
542 packed_kind, backing_store); | 543 packed_kind, backing_store); |
543 } | 544 } |
544 } | 545 } |
545 | 546 |
546 virtual bool HasElement(Handle<JSObject> holder, uint32_t index, | 547 virtual bool HasElement(Handle<JSObject> holder, uint32_t index, |
547 Handle<FixedArrayBase> backing_store) final { | 548 Handle<FixedArrayBase> backing_store, |
| 549 PropertyAttributes filter) final { |
548 return ElementsAccessorSubclass::HasElementImpl(holder, index, | 550 return ElementsAccessorSubclass::HasElementImpl(holder, index, |
549 backing_store); | 551 backing_store, filter); |
550 } | 552 } |
551 | 553 |
552 static bool HasElementImpl(Handle<JSObject> holder, uint32_t index, | 554 static bool HasElementImpl(Handle<JSObject> holder, uint32_t index, |
553 Handle<FixedArrayBase> backing_store) { | 555 Handle<FixedArrayBase> backing_store, |
| 556 PropertyAttributes filter) { |
554 return ElementsAccessorSubclass::GetEntryForIndexImpl( | 557 return ElementsAccessorSubclass::GetEntryForIndexImpl( |
555 *holder, *backing_store, index) != kMaxUInt32; | 558 *holder, *backing_store, index, filter) != kMaxUInt32; |
556 } | 559 } |
557 | 560 |
558 virtual Handle<Object> Get(Handle<FixedArrayBase> backing_store, | 561 virtual Handle<Object> Get(Handle<FixedArrayBase> backing_store, |
559 uint32_t entry) final { | 562 uint32_t entry) final { |
560 return ElementsAccessorSubclass::GetImpl(backing_store, entry); | 563 return ElementsAccessorSubclass::GetImpl(backing_store, entry); |
561 } | 564 } |
562 | 565 |
563 static Handle<Object> GetImpl(Handle<FixedArrayBase> backing_store, | 566 static Handle<Object> GetImpl(Handle<FixedArrayBase> backing_store, |
564 uint32_t entry) { | 567 uint32_t entry) { |
565 uint32_t index = GetIndexForEntryImpl(*backing_store, entry); | 568 uint32_t index = GetIndexForEntryImpl(*backing_store, entry); |
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
863 // Details: The idea is that allocations actually happen only in case of | 866 // Details: The idea is that allocations actually happen only in case of |
864 // copying from object with fast double elements to object with object | 867 // copying from object with fast double elements to object with object |
865 // elements. In all the other cases there are no allocations performed and | 868 // elements. In all the other cases there are no allocations performed and |
866 // handle creation causes noticeable performance degradation of the builtin. | 869 // handle creation causes noticeable performance degradation of the builtin. |
867 ElementsAccessorSubclass::CopyElementsImpl( | 870 ElementsAccessorSubclass::CopyElementsImpl( |
868 from, from_start, *to, from_kind, to_start, packed_size, copy_size); | 871 from, from_start, *to, from_kind, to_start, packed_size, copy_size); |
869 } | 872 } |
870 | 873 |
871 virtual void AddElementsToKeyAccumulator(Handle<JSObject> receiver, | 874 virtual void AddElementsToKeyAccumulator(Handle<JSObject> receiver, |
872 KeyAccumulator* accumulator, | 875 KeyAccumulator* accumulator, |
873 KeyFilter filter) final { | 876 AddKeyConversion convert) final { |
874 Handle<FixedArrayBase> from(receiver->elements()); | 877 Handle<FixedArrayBase> from(receiver->elements()); |
875 uint32_t add_length = | 878 uint32_t add_length = |
876 ElementsAccessorSubclass::GetCapacityImpl(*receiver, *from); | 879 ElementsAccessorSubclass::GetCapacityImpl(*receiver, *from); |
877 if (add_length == 0) return; | 880 if (add_length == 0) return; |
878 accumulator->PrepareForComparisons(add_length); | 881 |
879 int prev_key_count = accumulator->GetLength(); | |
880 for (uint32_t i = 0; i < add_length; i++) { | 882 for (uint32_t i = 0; i < add_length; i++) { |
881 if (!ElementsAccessorSubclass::HasEntryImpl(*from, i)) continue; | 883 if (!ElementsAccessorSubclass::HasEntryImpl(*from, i)) continue; |
882 Handle<Object> value = ElementsAccessorSubclass::GetImpl(from, i); | 884 Handle<Object> value = ElementsAccessorSubclass::GetImpl(from, i); |
883 DCHECK(!value->IsTheHole()); | 885 DCHECK(!value->IsTheHole()); |
884 DCHECK(!value->IsAccessorPair()); | 886 DCHECK(!value->IsAccessorPair()); |
885 DCHECK(!value->IsExecutableAccessorInfo()); | 887 DCHECK(!value->IsExecutableAccessorInfo()); |
886 if (filter == SKIP_SYMBOLS && value->IsSymbol()) { | 888 accumulator->AddKey(value, convert); |
887 continue; | |
888 } | |
889 accumulator->AddKey(value, prev_key_count); | |
890 } | 889 } |
891 } | 890 } |
892 | 891 |
893 static uint32_t GetCapacityImpl(JSObject* holder, | 892 static uint32_t GetCapacityImpl(JSObject* holder, |
894 FixedArrayBase* backing_store) { | 893 FixedArrayBase* backing_store) { |
895 return backing_store->length(); | 894 return backing_store->length(); |
896 } | 895 } |
897 | 896 |
898 uint32_t GetCapacity(JSObject* holder, FixedArrayBase* backing_store) final { | 897 virtual uint32_t GetCapacity(JSObject* holder, |
| 898 FixedArrayBase* backing_store) final { |
899 return ElementsAccessorSubclass::GetCapacityImpl(holder, backing_store); | 899 return ElementsAccessorSubclass::GetCapacityImpl(holder, backing_store); |
900 } | 900 } |
901 | 901 |
902 static bool HasEntryImpl(FixedArrayBase* backing_store, uint32_t entry) { | 902 static bool HasEntryImpl(FixedArrayBase* backing_store, uint32_t entry) { |
903 return true; | 903 return true; |
904 } | 904 } |
905 | 905 |
906 static uint32_t GetIndexForEntryImpl(FixedArrayBase* backing_store, | 906 static uint32_t GetIndexForEntryImpl(FixedArrayBase* backing_store, |
907 uint32_t entry) { | 907 uint32_t entry) { |
908 return entry; | 908 return entry; |
909 } | 909 } |
910 | 910 |
911 static uint32_t GetEntryForIndexImpl(JSObject* holder, | 911 static uint32_t GetEntryForIndexImpl(JSObject* holder, |
912 FixedArrayBase* backing_store, | 912 FixedArrayBase* backing_store, |
913 uint32_t index) { | 913 uint32_t index, |
| 914 PropertyAttributes filter) { |
914 if (IsHoleyElementsKind(kind())) { | 915 if (IsHoleyElementsKind(kind())) { |
915 return index < ElementsAccessorSubclass::GetCapacityImpl(holder, | 916 return index < ElementsAccessorSubclass::GetCapacityImpl(holder, |
916 backing_store) && | 917 backing_store) && |
917 !BackingStore::cast(backing_store)->is_the_hole(index) | 918 !BackingStore::cast(backing_store)->is_the_hole(index) |
918 ? index | 919 ? index |
919 : kMaxUInt32; | 920 : kMaxUInt32; |
920 } else { | 921 } else { |
921 Smi* smi_length = Smi::cast(JSArray::cast(holder)->length()); | 922 Smi* smi_length = Smi::cast(JSArray::cast(holder)->length()); |
922 uint32_t length = static_cast<uint32_t>(smi_length->value()); | 923 uint32_t length = static_cast<uint32_t>(smi_length->value()); |
923 return index < length ? index : kMaxUInt32; | 924 return index < length ? index : kMaxUInt32; |
924 } | 925 } |
925 } | 926 } |
926 | 927 |
927 virtual uint32_t GetEntryForIndex(JSObject* holder, | 928 virtual uint32_t GetEntryForIndex(JSObject* holder, |
928 FixedArrayBase* backing_store, | 929 FixedArrayBase* backing_store, |
929 uint32_t index) final { | 930 uint32_t index) final { |
930 return ElementsAccessorSubclass::GetEntryForIndexImpl(holder, backing_store, | 931 return ElementsAccessorSubclass::GetEntryForIndexImpl(holder, backing_store, |
931 index); | 932 index, NONE); |
932 } | 933 } |
933 | 934 |
934 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, | 935 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, |
935 uint32_t entry) { | 936 uint32_t entry) { |
936 return PropertyDetails(NONE, DATA, 0, PropertyCellType::kNoCell); | 937 return PropertyDetails(NONE, DATA, 0, PropertyCellType::kNoCell); |
937 } | 938 } |
938 | 939 |
939 virtual PropertyDetails GetDetails(FixedArrayBase* backing_store, | 940 virtual PropertyDetails GetDetails(FixedArrayBase* backing_store, |
940 uint32_t entry) final { | 941 uint32_t entry) final { |
941 return ElementsAccessorSubclass::GetDetailsImpl(backing_store, entry); | 942 return ElementsAccessorSubclass::GetDetailsImpl(backing_store, entry); |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1083 | 1084 |
1084 static uint32_t GetIndexForEntryImpl(FixedArrayBase* store, uint32_t entry) { | 1085 static uint32_t GetIndexForEntryImpl(FixedArrayBase* store, uint32_t entry) { |
1085 DisallowHeapAllocation no_gc; | 1086 DisallowHeapAllocation no_gc; |
1086 SeededNumberDictionary* dict = SeededNumberDictionary::cast(store); | 1087 SeededNumberDictionary* dict = SeededNumberDictionary::cast(store); |
1087 uint32_t result = 0; | 1088 uint32_t result = 0; |
1088 CHECK(dict->KeyAt(entry)->ToArrayIndex(&result)); | 1089 CHECK(dict->KeyAt(entry)->ToArrayIndex(&result)); |
1089 return result; | 1090 return result; |
1090 } | 1091 } |
1091 | 1092 |
1092 static uint32_t GetEntryForIndexImpl(JSObject* holder, FixedArrayBase* store, | 1093 static uint32_t GetEntryForIndexImpl(JSObject* holder, FixedArrayBase* store, |
1093 uint32_t index) { | 1094 uint32_t index, |
| 1095 PropertyAttributes filter) { |
1094 DisallowHeapAllocation no_gc; | 1096 DisallowHeapAllocation no_gc; |
1095 SeededNumberDictionary* dict = SeededNumberDictionary::cast(store); | 1097 SeededNumberDictionary* dictionary = SeededNumberDictionary::cast(store); |
1096 int entry = dict->FindEntry(index); | 1098 int entry = dictionary->FindEntry(index); |
1097 return entry == SeededNumberDictionary::kNotFound | 1099 if (entry == SeededNumberDictionary::kNotFound) return kMaxUInt32; |
1098 ? kMaxUInt32 | 1100 if (filter != NONE) { |
1099 : static_cast<uint32_t>(entry); | 1101 PropertyDetails details = dictionary->DetailsAt(entry); |
| 1102 PropertyAttributes attr = details.attributes(); |
| 1103 if ((attr & filter) != 0) return kMaxUInt32; |
| 1104 } |
| 1105 return static_cast<uint32_t>(entry); |
1100 } | 1106 } |
1101 | 1107 |
1102 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, | 1108 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, |
1103 uint32_t entry) { | 1109 uint32_t entry) { |
1104 return SeededNumberDictionary::cast(backing_store)->DetailsAt(entry); | 1110 return SeededNumberDictionary::cast(backing_store)->DetailsAt(entry); |
1105 } | 1111 } |
1106 }; | 1112 }; |
1107 | 1113 |
1108 | 1114 |
1109 // Super class for all fast element arrays. | 1115 // Super class for all fast element arrays. |
(...skipping 642 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1752 UNREACHABLE(); | 1758 UNREACHABLE(); |
1753 } | 1759 } |
1754 | 1760 |
1755 static uint32_t GetIndexForEntryImpl(FixedArrayBase* backing_store, | 1761 static uint32_t GetIndexForEntryImpl(FixedArrayBase* backing_store, |
1756 uint32_t entry) { | 1762 uint32_t entry) { |
1757 return entry; | 1763 return entry; |
1758 } | 1764 } |
1759 | 1765 |
1760 static uint32_t GetEntryForIndexImpl(JSObject* holder, | 1766 static uint32_t GetEntryForIndexImpl(JSObject* holder, |
1761 FixedArrayBase* backing_store, | 1767 FixedArrayBase* backing_store, |
1762 uint32_t index) { | 1768 uint32_t index, |
| 1769 PropertyAttributes filter) { |
1763 return index < AccessorClass::GetCapacityImpl(holder, backing_store) | 1770 return index < AccessorClass::GetCapacityImpl(holder, backing_store) |
1764 ? index | 1771 ? index |
1765 : kMaxUInt32; | 1772 : kMaxUInt32; |
1766 } | 1773 } |
1767 | 1774 |
1768 static uint32_t GetCapacityImpl(JSObject* holder, | 1775 static uint32_t GetCapacityImpl(JSObject* holder, |
1769 FixedArrayBase* backing_store) { | 1776 FixedArrayBase* backing_store) { |
1770 JSArrayBufferView* view = JSArrayBufferView::cast(holder); | 1777 JSArrayBufferView* view = JSArrayBufferView::cast(holder); |
1771 if (view->WasNeutered()) return 0; | 1778 if (view->WasNeutered()) return 0; |
1772 return backing_store->length(); | 1779 return backing_store->length(); |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1886 FixedArray* parameter_map = FixedArray::cast(parameters); | 1893 FixedArray* parameter_map = FixedArray::cast(parameters); |
1887 uint32_t length = parameter_map->length() - 2; | 1894 uint32_t length = parameter_map->length() - 2; |
1888 if (entry < length) return entry; | 1895 if (entry < length) return entry; |
1889 | 1896 |
1890 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1897 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
1891 return ArgumentsAccessor::GetIndexForEntryImpl(arguments, entry - length); | 1898 return ArgumentsAccessor::GetIndexForEntryImpl(arguments, entry - length); |
1892 } | 1899 } |
1893 | 1900 |
1894 static uint32_t GetEntryForIndexImpl(JSObject* holder, | 1901 static uint32_t GetEntryForIndexImpl(JSObject* holder, |
1895 FixedArrayBase* parameters, | 1902 FixedArrayBase* parameters, |
1896 uint32_t index) { | 1903 uint32_t index, |
| 1904 PropertyAttributes filter) { |
1897 FixedArray* parameter_map = FixedArray::cast(parameters); | 1905 FixedArray* parameter_map = FixedArray::cast(parameters); |
1898 Object* probe = GetParameterMapArg(parameter_map, index); | 1906 Object* probe = GetParameterMapArg(parameter_map, index); |
1899 if (!probe->IsTheHole()) return index; | 1907 if (!probe->IsTheHole()) return index; |
1900 | 1908 |
1901 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1909 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
1902 uint32_t entry = | 1910 uint32_t entry = ArgumentsAccessor::GetEntryForIndexImpl(holder, arguments, |
1903 ArgumentsAccessor::GetEntryForIndexImpl(holder, arguments, index); | 1911 index, filter); |
1904 if (entry == kMaxUInt32) return entry; | 1912 if (entry == kMaxUInt32) return entry; |
1905 return (parameter_map->length() - 2) + entry; | 1913 return (parameter_map->length() - 2) + entry; |
1906 } | 1914 } |
1907 | 1915 |
1908 static PropertyDetails GetDetailsImpl(FixedArrayBase* parameters, | 1916 static PropertyDetails GetDetailsImpl(FixedArrayBase* parameters, |
1909 uint32_t entry) { | 1917 uint32_t entry) { |
1910 FixedArray* parameter_map = FixedArray::cast(parameters); | 1918 FixedArray* parameter_map = FixedArray::cast(parameters); |
1911 uint32_t length = parameter_map->length() - 2; | 1919 uint32_t length = parameter_map->length() - 2; |
1912 if (entry < length) { | 1920 if (entry < length) { |
1913 return PropertyDetails(NONE, DATA, 0, PropertyCellType::kNoCell); | 1921 return PropertyDetails(NONE, DATA, 0, PropertyCellType::kNoCell); |
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2326 } | 2334 } |
2327 } | 2335 } |
2328 | 2336 |
2329 DCHECK(j == result_len); | 2337 DCHECK(j == result_len); |
2330 return result_array; | 2338 return result_array; |
2331 } | 2339 } |
2332 | 2340 |
2333 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; | 2341 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; |
2334 } // namespace internal | 2342 } // namespace internal |
2335 } // namespace v8 | 2343 } // namespace v8 |
OLD | NEW |