Chromium Code Reviews| 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/v8.h" | 5 #include "src/v8.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/elements.h" | 9 #include "src/elements.h" |
| 10 #include "src/messages.h" | 10 #include "src/messages.h" |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 116 #define ELEMENTS_TRAITS(Class, KindParam, Store) \ | 116 #define ELEMENTS_TRAITS(Class, KindParam, Store) \ |
| 117 template<> class ElementsKindTraits<KindParam> { \ | 117 template<> class ElementsKindTraits<KindParam> { \ |
| 118 public: /* NOLINT */ \ | 118 public: /* NOLINT */ \ |
| 119 static const ElementsKind Kind = KindParam; \ | 119 static const ElementsKind Kind = KindParam; \ |
| 120 typedef Store BackingStore; \ | 120 typedef Store BackingStore; \ |
| 121 }; | 121 }; |
| 122 ELEMENTS_LIST(ELEMENTS_TRAITS) | 122 ELEMENTS_LIST(ELEMENTS_TRAITS) |
| 123 #undef ELEMENTS_TRAITS | 123 #undef ELEMENTS_TRAITS |
| 124 | 124 |
| 125 | 125 |
| 126 static bool HasKey(Handle<FixedArray> array, Handle<Object> key_handle) { | 126 static bool HasIndex(Handle<FixedArray> array, Handle<Object> index_handle) { |
| 127 DisallowHeapAllocation no_gc; | 127 DisallowHeapAllocation no_gc; |
| 128 Object* key = *key_handle; | 128 Object* index = *index_handle; |
| 129 int len0 = array->length(); | 129 int len0 = array->length(); |
| 130 for (int i = 0; i < len0; i++) { | 130 for (int i = 0; i < len0; i++) { |
| 131 Object* element = array->get(i); | 131 Object* element = array->get(i); |
| 132 if (key->KeyEquals(element)) return true; | 132 if (index->KeyEquals(element)) return true; |
| 133 } | 133 } |
| 134 return false; | 134 return false; |
| 135 } | 135 } |
| 136 | 136 |
| 137 | 137 |
| 138 MUST_USE_RESULT | 138 MUST_USE_RESULT |
| 139 static MaybeHandle<Object> ThrowArrayLengthRangeError(Isolate* isolate) { | 139 static MaybeHandle<Object> ThrowArrayLengthRangeError(Isolate* isolate) { |
| 140 THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kInvalidArrayLength), | 140 THROW_NEW_ERROR(isolate, NewRangeError(MessageTemplate::kInvalidArrayLength), |
| 141 Object); | 141 Object); |
| 142 } | 142 } |
| (...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 535 length = fixed_array_base->length(); | 535 length = fixed_array_base->length(); |
| 536 } | 536 } |
| 537 ElementsAccessorSubclass::ValidateContents(holder, length); | 537 ElementsAccessorSubclass::ValidateContents(holder, length); |
| 538 } | 538 } |
| 539 | 539 |
| 540 void Validate(Handle<JSObject> holder) final { | 540 void Validate(Handle<JSObject> holder) final { |
| 541 DisallowHeapAllocation no_gc; | 541 DisallowHeapAllocation no_gc; |
| 542 ElementsAccessorSubclass::ValidateImpl(holder); | 542 ElementsAccessorSubclass::ValidateImpl(holder); |
| 543 } | 543 } |
| 544 | 544 |
| 545 virtual bool HasElement(Handle<JSObject> holder, uint32_t key, | 545 virtual bool HasElement(Handle<JSObject> holder, uint32_t index, |
| 546 Handle<FixedArrayBase> backing_store) final { | 546 Handle<FixedArrayBase> backing_store) final { |
| 547 return ElementsAccessorSubclass::GetIndexForKeyImpl(*holder, *backing_store, | 547 return ElementsAccessorSubclass::GetEntryForIndexImpl( |
| 548 key) != kMaxUInt32; | 548 *holder, *backing_store, index) != kMaxUInt32; |
| 549 } | 549 } |
| 550 | 550 |
| 551 virtual Handle<Object> Get(Handle<JSObject> holder, uint32_t key, | 551 virtual Handle<Object> Get(Handle<JSObject> holder, uint32_t index, |
| 552 Handle<FixedArrayBase> backing_store) final { | 552 Handle<FixedArrayBase> backing_store) final { |
| 553 if (!IsExternalArrayElementsKind(ElementsTraits::Kind) && | 553 if (!IsExternalArrayElementsKind(ElementsTraits::Kind) && |
| 554 FLAG_trace_js_array_abuse) { | 554 FLAG_trace_js_array_abuse) { |
| 555 CheckArrayAbuse(holder, "elements read", key); | 555 CheckArrayAbuse(holder, "elements read", index); |
| 556 } | 556 } |
| 557 | 557 |
| 558 if (IsExternalArrayElementsKind(ElementsTraits::Kind) && | 558 if (IsExternalArrayElementsKind(ElementsTraits::Kind) && |
| 559 FLAG_trace_external_array_abuse) { | 559 FLAG_trace_external_array_abuse) { |
| 560 CheckArrayAbuse(holder, "external elements read", key); | 560 CheckArrayAbuse(holder, "external elements read", index); |
| 561 } | 561 } |
| 562 | 562 |
| 563 return ElementsAccessorSubclass::GetImpl(holder, key, backing_store); | 563 return ElementsAccessorSubclass::GetImpl(holder, index, backing_store); |
| 564 } | 564 } |
| 565 | 565 |
| 566 static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key, | 566 static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t index, |
| 567 Handle<FixedArrayBase> backing_store) { | 567 Handle<FixedArrayBase> backing_store) { |
| 568 if (key < ElementsAccessorSubclass::GetCapacityImpl(*obj, *backing_store)) { | 568 if (index < |
| 569 return BackingStore::get(Handle<BackingStore>::cast(backing_store), key); | 569 ElementsAccessorSubclass::GetCapacityImpl(*obj, *backing_store)) { |
| 570 return BackingStore::get(Handle<BackingStore>::cast(backing_store), | |
| 571 index); | |
| 570 } else { | 572 } else { |
| 571 return backing_store->GetIsolate()->factory()->the_hole_value(); | 573 return backing_store->GetIsolate()->factory()->the_hole_value(); |
| 572 } | 574 } |
| 573 } | 575 } |
| 574 | 576 |
| 575 virtual void Set(FixedArrayBase* backing_store, uint32_t key, | 577 virtual void Set(FixedArrayBase* backing_store, uint32_t index, |
| 576 Object* value) final { | 578 Object* value) final { |
| 577 ElementsAccessorSubclass::SetImpl(backing_store, key, value); | 579 ElementsAccessorSubclass::SetImpl(backing_store, index, value); |
| 578 } | 580 } |
| 579 | 581 |
| 580 static void SetImpl(FixedArrayBase* backing_store, uint32_t key, | 582 static void SetImpl(FixedArrayBase* backing_store, uint32_t index, |
| 581 Object* value) { | 583 Object* value) { |
| 582 BackingStore::cast(backing_store)->SetValue(key, value); | 584 BackingStore::cast(backing_store)->SetValue(index, value); |
| 583 } | 585 } |
| 584 | 586 |
| 585 virtual void Reconfigure(Handle<JSObject> object, | 587 virtual void Reconfigure(Handle<JSObject> object, |
| 586 Handle<FixedArrayBase> store, uint32_t index, | 588 Handle<FixedArrayBase> store, uint32_t entry, |
| 587 Handle<Object> value, | 589 Handle<Object> value, |
| 588 PropertyAttributes attributes) final { | 590 PropertyAttributes attributes) final { |
| 589 ElementsAccessorSubclass::ReconfigureImpl(object, store, index, value, | 591 ElementsAccessorSubclass::ReconfigureImpl(object, store, entry, value, |
| 590 attributes); | 592 attributes); |
| 591 } | 593 } |
| 592 | 594 |
| 593 static void ReconfigureImpl(Handle<JSObject> object, | 595 static void ReconfigureImpl(Handle<JSObject> object, |
| 594 Handle<FixedArrayBase> store, uint32_t index, | 596 Handle<FixedArrayBase> store, uint32_t entry, |
| 595 Handle<Object> value, | 597 Handle<Object> value, |
| 596 PropertyAttributes attributes) { | 598 PropertyAttributes attributes) { |
| 597 UNREACHABLE(); | 599 UNREACHABLE(); |
| 598 } | 600 } |
| 599 | 601 |
| 600 virtual void Add(Handle<JSObject> object, uint32_t index, | 602 virtual void Add(Handle<JSObject> object, uint32_t entry, |
| 601 Handle<Object> value, PropertyAttributes attributes, | 603 Handle<Object> value, PropertyAttributes attributes, |
| 602 uint32_t new_capacity) final { | 604 uint32_t new_capacity) final { |
| 603 ElementsAccessorSubclass::AddImpl(object, index, value, attributes, | 605 ElementsAccessorSubclass::AddImpl(object, entry, value, attributes, |
| 604 new_capacity); | 606 new_capacity); |
| 605 } | 607 } |
| 606 | 608 |
| 607 static void AddImpl(Handle<JSObject> object, uint32_t index, | 609 static void AddImpl(Handle<JSObject> object, uint32_t entry, |
| 608 Handle<Object> value, PropertyAttributes attributes, | 610 Handle<Object> value, PropertyAttributes attributes, |
| 609 uint32_t new_capacity) { | 611 uint32_t new_capacity) { |
| 610 UNREACHABLE(); | 612 UNREACHABLE(); |
| 611 } | 613 } |
| 612 | 614 |
| 613 virtual void SetLength(Handle<JSArray> array, uint32_t length) final { | 615 virtual void SetLength(Handle<JSArray> array, uint32_t length) final { |
| 614 ElementsAccessorSubclass::SetLengthImpl(array, length, | 616 ElementsAccessorSubclass::SetLengthImpl(array, length, |
| 615 handle(array->elements())); | 617 handle(array->elements())); |
| 616 } | 618 } |
| 617 | 619 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 671 JSObject::PrintElementsTransition(stdout, object, from_kind, old_elements, | 673 JSObject::PrintElementsTransition(stdout, object, from_kind, old_elements, |
| 672 to_kind, elements); | 674 to_kind, elements); |
| 673 } | 675 } |
| 674 } | 676 } |
| 675 | 677 |
| 676 virtual void GrowCapacityAndConvert(Handle<JSObject> object, | 678 virtual void GrowCapacityAndConvert(Handle<JSObject> object, |
| 677 uint32_t capacity) final { | 679 uint32_t capacity) final { |
| 678 ElementsAccessorSubclass::GrowCapacityAndConvertImpl(object, capacity); | 680 ElementsAccessorSubclass::GrowCapacityAndConvertImpl(object, capacity); |
| 679 } | 681 } |
| 680 | 682 |
| 681 virtual void Delete(Handle<JSObject> obj, uint32_t index) final { | 683 virtual void Delete(Handle<JSObject> obj, uint32_t entry) final { |
| 682 ElementsAccessorSubclass::DeleteImpl(obj, index); | 684 ElementsAccessorSubclass::DeleteImpl(obj, entry); |
| 683 } | 685 } |
| 684 | 686 |
| 685 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, | 687 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, |
| 686 FixedArrayBase* to, ElementsKind from_kind, | 688 FixedArrayBase* to, ElementsKind from_kind, |
| 687 uint32_t to_start, int packed_size, | 689 uint32_t to_start, int packed_size, |
| 688 int copy_size) { | 690 int copy_size) { |
| 689 UNREACHABLE(); | 691 UNREACHABLE(); |
| 690 } | 692 } |
| 691 | 693 |
| 692 virtual void CopyElements(Handle<FixedArrayBase> from, uint32_t from_start, | 694 virtual void CopyElements(Handle<FixedArrayBase> from, uint32_t from_start, |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 748 // Optimize if 'other' is empty. | 750 // Optimize if 'other' is empty. |
| 749 // We cannot optimize if 'this' is empty, as other may have holes. | 751 // We cannot optimize if 'this' is empty, as other may have holes. |
| 750 uint32_t len1 = ElementsAccessorSubclass::GetCapacityImpl(*receiver, *from); | 752 uint32_t len1 = ElementsAccessorSubclass::GetCapacityImpl(*receiver, *from); |
| 751 if (len1 == 0) return to; | 753 if (len1 == 0) return to; |
| 752 | 754 |
| 753 Isolate* isolate = from->GetIsolate(); | 755 Isolate* isolate = from->GetIsolate(); |
| 754 | 756 |
| 755 // Compute how many elements are not in other. | 757 // Compute how many elements are not in other. |
| 756 uint32_t extra = 0; | 758 uint32_t extra = 0; |
| 757 for (uint32_t y = 0; y < len1; y++) { | 759 for (uint32_t y = 0; y < len1; y++) { |
| 758 if (ElementsAccessorSubclass::HasIndexImpl(*from, y)) { | 760 if (ElementsAccessorSubclass::HasEntryImpl(*from, y)) { |
| 759 uint32_t key = ElementsAccessorSubclass::GetKeyForIndexImpl(*from, y); | 761 uint32_t index = |
| 762 ElementsAccessorSubclass::GetIndexForEntryImpl(*from, y); | |
| 760 Handle<Object> value = | 763 Handle<Object> value = |
| 761 ElementsAccessorSubclass::GetImpl(receiver, key, from); | 764 ElementsAccessorSubclass::GetImpl(receiver, index, from); |
| 762 | 765 |
| 763 DCHECK(!value->IsTheHole()); | 766 DCHECK(!value->IsTheHole()); |
| 764 DCHECK(!value->IsAccessorPair()); | 767 DCHECK(!value->IsAccessorPair()); |
| 765 DCHECK(!value->IsExecutableAccessorInfo()); | 768 DCHECK(!value->IsExecutableAccessorInfo()); |
| 766 if (filter == FixedArray::NON_SYMBOL_KEYS && value->IsSymbol()) { | 769 if (filter == FixedArray::NON_SYMBOL_KEYS && value->IsSymbol()) { |
| 767 continue; | 770 continue; |
| 768 } | 771 } |
| 769 if (!HasKey(to, value)) { | 772 if (!HasIndex(to, value)) { |
| 770 extra++; | 773 extra++; |
| 771 } | 774 } |
| 772 } | 775 } |
| 773 } | 776 } |
| 774 | 777 |
| 775 if (extra == 0) return to; | 778 if (extra == 0) return to; |
| 776 | 779 |
| 777 // Allocate the result | 780 // Allocate the result |
| 778 Handle<FixedArray> result = isolate->factory()->NewFixedArray(len0 + extra); | 781 Handle<FixedArray> result = isolate->factory()->NewFixedArray(len0 + extra); |
| 779 | 782 |
| 780 // Fill in the content | 783 // Fill in the content |
| 781 { | 784 { |
| 782 DisallowHeapAllocation no_gc; | 785 DisallowHeapAllocation no_gc; |
| 783 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); | 786 WriteBarrierMode mode = result->GetWriteBarrierMode(no_gc); |
| 784 for (int i = 0; i < len0; i++) { | 787 for (int i = 0; i < len0; i++) { |
| 785 Object* e = to->get(i); | 788 Object* e = to->get(i); |
| 786 DCHECK(e->IsString() || e->IsNumber()); | 789 DCHECK(e->IsString() || e->IsNumber()); |
| 787 result->set(i, e, mode); | 790 result->set(i, e, mode); |
| 788 } | 791 } |
| 789 } | 792 } |
| 790 // Fill in the extra values. | 793 // Fill in the extra values. |
| 791 uint32_t index = 0; | 794 uint32_t entry = 0; |
| 792 for (uint32_t y = 0; y < len1; y++) { | 795 for (uint32_t y = 0; y < len1; y++) { |
| 793 if (ElementsAccessorSubclass::HasIndexImpl(*from, y)) { | 796 if (ElementsAccessorSubclass::HasEntryImpl(*from, y)) { |
| 794 uint32_t key = ElementsAccessorSubclass::GetKeyForIndexImpl(*from, y); | 797 uint32_t index = |
| 798 ElementsAccessorSubclass::GetIndexForEntryImpl(*from, y); | |
| 795 Handle<Object> value = | 799 Handle<Object> value = |
| 796 ElementsAccessorSubclass::GetImpl(receiver, key, from); | 800 ElementsAccessorSubclass::GetImpl(receiver, index, from); |
| 797 DCHECK(!value->IsAccessorPair()); | 801 DCHECK(!value->IsAccessorPair()); |
| 798 DCHECK(!value->IsExecutableAccessorInfo()); | 802 DCHECK(!value->IsExecutableAccessorInfo()); |
| 799 if (filter == FixedArray::NON_SYMBOL_KEYS && value->IsSymbol()) { | 803 if (filter == FixedArray::NON_SYMBOL_KEYS && value->IsSymbol()) { |
| 800 continue; | 804 continue; |
| 801 } | 805 } |
| 802 if (!value->IsTheHole() && !HasKey(to, value)) { | 806 if (!value->IsTheHole() && !HasIndex(to, value)) { |
| 803 result->set(len0 + index, *value); | 807 result->set(len0 + entry, *value); |
| 804 index++; | 808 entry++; |
| 805 } | 809 } |
| 806 } | 810 } |
| 807 } | 811 } |
| 808 DCHECK(extra == index); | 812 DCHECK(extra == entry); |
| 809 return result; | 813 return result; |
| 810 } | 814 } |
| 811 | 815 |
| 812 static uint32_t GetCapacityImpl(JSObject* holder, | 816 static uint32_t GetCapacityImpl(JSObject* holder, |
| 813 FixedArrayBase* backing_store) { | 817 FixedArrayBase* backing_store) { |
| 814 return backing_store->length(); | 818 return backing_store->length(); |
| 815 } | 819 } |
| 816 | 820 |
| 817 uint32_t GetCapacity(JSObject* holder, FixedArrayBase* backing_store) final { | 821 uint32_t GetCapacity(JSObject* holder, FixedArrayBase* backing_store) final { |
| 818 return ElementsAccessorSubclass::GetCapacityImpl(holder, backing_store); | 822 return ElementsAccessorSubclass::GetCapacityImpl(holder, backing_store); |
| 819 } | 823 } |
| 820 | 824 |
| 821 static bool HasIndexImpl(FixedArrayBase* backing_store, uint32_t index) { | 825 static bool HasEntryImpl(FixedArrayBase* backing_store, uint32_t entry) { |
| 822 return true; | 826 return true; |
| 823 } | 827 } |
| 824 | 828 |
| 825 virtual bool HasIndex(FixedArrayBase* backing_store, uint32_t index) final { | 829 virtual bool HasEntry(FixedArrayBase* backing_store, uint32_t entry) final { |
| 826 return ElementsAccessorSubclass::HasIndexImpl(backing_store, index); | 830 return ElementsAccessorSubclass::HasEntryImpl(backing_store, entry); |
| 827 } | 831 } |
| 828 | 832 |
| 829 static uint32_t GetKeyForIndexImpl(FixedArrayBase* backing_store, | 833 static uint32_t GetIndexForEntryImpl(FixedArrayBase* backing_store, |
| 830 uint32_t index) { | 834 uint32_t entry) { |
| 831 return index; | 835 return entry; |
| 832 } | 836 } |
| 833 | 837 |
| 834 virtual uint32_t GetKeyForIndex(FixedArrayBase* backing_store, | 838 static uint32_t GetEntryForIndexImpl(JSObject* holder, |
| 835 uint32_t index) final { | 839 FixedArrayBase* backing_store, |
| 836 return ElementsAccessorSubclass::GetKeyForIndexImpl(backing_store, index); | 840 uint32_t index) { |
| 837 } | 841 return index < ElementsAccessorSubclass::GetCapacityImpl(holder, |
| 838 | 842 backing_store) && |
| 839 static uint32_t GetIndexForKeyImpl(JSObject* holder, | 843 !BackingStore::cast(backing_store)->is_the_hole(index) |
| 840 FixedArrayBase* backing_store, | 844 ? index |
| 841 uint32_t key) { | |
| 842 return key < ElementsAccessorSubclass::GetCapacityImpl(holder, | |
| 843 backing_store) && | |
| 844 !BackingStore::cast(backing_store)->is_the_hole(key) | |
| 845 ? key | |
| 846 : kMaxUInt32; | 845 : kMaxUInt32; |
| 847 } | 846 } |
| 848 | 847 |
| 849 virtual uint32_t GetIndexForKey(JSObject* holder, | 848 virtual uint32_t GetEntryForIndex(JSObject* holder, |
| 850 FixedArrayBase* backing_store, | 849 FixedArrayBase* backing_store, |
| 851 uint32_t key) final { | 850 uint32_t index) final { |
| 852 return ElementsAccessorSubclass::GetIndexForKeyImpl(holder, backing_store, | 851 return ElementsAccessorSubclass::GetEntryForIndexImpl(holder, backing_store, |
| 853 key); | 852 index); |
| 854 } | 853 } |
| 855 | 854 |
| 856 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, | 855 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, |
| 857 uint32_t index) { | 856 uint32_t entry) { |
| 858 return PropertyDetails(NONE, DATA, 0, PropertyCellType::kNoCell); | 857 return PropertyDetails(NONE, DATA, 0, PropertyCellType::kNoCell); |
| 859 } | 858 } |
| 860 | 859 |
| 861 virtual PropertyDetails GetDetails(FixedArrayBase* backing_store, | 860 virtual PropertyDetails GetDetails(FixedArrayBase* backing_store, |
| 862 uint32_t index) final { | 861 uint32_t entry) final { |
| 863 return ElementsAccessorSubclass::GetDetailsImpl(backing_store, index); | 862 return ElementsAccessorSubclass::GetDetailsImpl(backing_store, entry); |
| 864 } | 863 } |
| 865 | 864 |
| 866 private: | 865 private: |
| 867 DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase); | 866 DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase); |
| 868 }; | 867 }; |
| 869 | 868 |
| 870 | 869 |
| 871 class DictionaryElementsAccessor | 870 class DictionaryElementsAccessor |
| 872 : public ElementsAccessorBase<DictionaryElementsAccessor, | 871 : public ElementsAccessorBase<DictionaryElementsAccessor, |
| 873 ElementsKindTraits<DICTIONARY_ELEMENTS> > { | 872 ElementsKindTraits<DICTIONARY_ELEMENTS> > { |
| 874 public: | 873 public: |
| 875 explicit DictionaryElementsAccessor(const char* name) | 874 explicit DictionaryElementsAccessor(const char* name) |
| 876 : ElementsAccessorBase<DictionaryElementsAccessor, | 875 : ElementsAccessorBase<DictionaryElementsAccessor, |
| 877 ElementsKindTraits<DICTIONARY_ELEMENTS> >(name) {} | 876 ElementsKindTraits<DICTIONARY_ELEMENTS> >(name) {} |
| 878 | 877 |
| 879 static void SetLengthImpl(Handle<JSArray> array, uint32_t length, | 878 static void SetLengthImpl(Handle<JSArray> array, uint32_t length, |
| 880 Handle<FixedArrayBase> backing_store) { | 879 Handle<FixedArrayBase> backing_store) { |
| 881 Handle<SeededNumberDictionary> dict = | 880 Handle<SeededNumberDictionary> dict = |
| 882 Handle<SeededNumberDictionary>::cast(backing_store); | 881 Handle<SeededNumberDictionary>::cast(backing_store); |
| 883 Isolate* isolate = array->GetIsolate(); | 882 Isolate* isolate = array->GetIsolate(); |
| 884 int capacity = dict->Capacity(); | 883 int capacity = dict->Capacity(); |
| 885 uint32_t old_length = 0; | 884 uint32_t old_length = 0; |
| 886 CHECK(array->length()->ToArrayLength(&old_length)); | 885 CHECK(array->length()->ToArrayLength(&old_length)); |
| 887 if (length < old_length) { | 886 if (length < old_length) { |
| 888 if (dict->requires_slow_elements()) { | 887 if (dict->requires_slow_elements()) { |
| 889 // Find last non-deletable element in range of elements to be | 888 // Find last non-deletable element in range of elements to be |
| 890 // deleted and adjust range accordingly. | 889 // deleted and adjust range accordingly. |
| 891 for (int i = 0; i < capacity; i++) { | 890 for (int i = 0; i < capacity; i++) { |
|
Igor Sheludko
2015/07/07 11:01:42
i -> entry?
| |
| 892 DisallowHeapAllocation no_gc; | 891 DisallowHeapAllocation no_gc; |
| 893 Object* key = dict->KeyAt(i); | 892 Object* index = dict->KeyAt(i); |
| 894 if (key->IsNumber()) { | 893 if (index->IsNumber()) { |
| 895 uint32_t number = static_cast<uint32_t>(key->Number()); | 894 uint32_t number = static_cast<uint32_t>(index->Number()); |
| 896 if (length <= number && number < old_length) { | 895 if (length <= number && number < old_length) { |
| 897 PropertyDetails details = dict->DetailsAt(i); | 896 PropertyDetails details = dict->DetailsAt(i); |
| 898 if (!details.IsConfigurable()) length = number + 1; | 897 if (!details.IsConfigurable()) length = number + 1; |
| 899 } | 898 } |
| 900 } | 899 } |
| 901 } | 900 } |
| 902 } | 901 } |
| 903 | 902 |
| 904 if (length == 0) { | 903 if (length == 0) { |
| 905 // Flush the backing store. | 904 // Flush the backing store. |
| 906 JSObject::ResetElements(array); | 905 JSObject::ResetElements(array); |
| 907 } else { | 906 } else { |
| 908 DisallowHeapAllocation no_gc; | 907 DisallowHeapAllocation no_gc; |
| 909 // Remove elements that should be deleted. | 908 // Remove elements that should be deleted. |
| 910 int removed_entries = 0; | 909 int removed_entries = 0; |
| 911 Handle<Object> the_hole_value = isolate->factory()->the_hole_value(); | 910 Handle<Object> the_hole_value = isolate->factory()->the_hole_value(); |
| 912 for (int i = 0; i < capacity; i++) { | 911 for (int i = 0; i < capacity; i++) { |
|
Igor Sheludko
2015/07/07 11:01:42
i -> entry?
| |
| 913 Object* key = dict->KeyAt(i); | 912 Object* index = dict->KeyAt(i); |
| 914 if (key->IsNumber()) { | 913 if (index->IsNumber()) { |
| 915 uint32_t number = static_cast<uint32_t>(key->Number()); | 914 uint32_t number = static_cast<uint32_t>(index->Number()); |
| 916 if (length <= number && number < old_length) { | 915 if (length <= number && number < old_length) { |
| 917 dict->SetEntry(i, the_hole_value, the_hole_value); | 916 dict->SetEntry(i, the_hole_value, the_hole_value); |
| 918 removed_entries++; | 917 removed_entries++; |
| 919 } | 918 } |
| 920 } | 919 } |
| 921 } | 920 } |
| 922 | 921 |
| 923 // Update the number of elements. | 922 // Update the number of elements. |
| 924 dict->ElementsRemoved(removed_entries); | 923 dict->ElementsRemoved(removed_entries); |
| 925 } | 924 } |
| 926 } | 925 } |
| 927 | 926 |
| 928 Handle<Object> length_obj = isolate->factory()->NewNumberFromUint(length); | 927 Handle<Object> length_obj = isolate->factory()->NewNumberFromUint(length); |
| 929 array->set_length(*length_obj); | 928 array->set_length(*length_obj); |
| 930 } | 929 } |
| 931 | 930 |
| 932 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, | 931 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, |
| 933 FixedArrayBase* to, ElementsKind from_kind, | 932 FixedArrayBase* to, ElementsKind from_kind, |
| 934 uint32_t to_start, int packed_size, | 933 uint32_t to_start, int packed_size, |
| 935 int copy_size) { | 934 int copy_size) { |
| 936 UNREACHABLE(); | 935 UNREACHABLE(); |
| 937 } | 936 } |
| 938 | 937 |
| 939 | 938 |
| 940 static void DeleteImpl(Handle<JSObject> obj, uint32_t index) { | 939 static void DeleteImpl(Handle<JSObject> obj, uint32_t entry) { |
| 941 // TODO(verwaest): Remove reliance on key in Shrink. | 940 // TODO(verwaest): Remove reliance on index in Shrink. |
| 942 Handle<SeededNumberDictionary> dict( | 941 Handle<SeededNumberDictionary> dict( |
| 943 SeededNumberDictionary::cast(obj->elements())); | 942 SeededNumberDictionary::cast(obj->elements())); |
| 944 uint32_t key = GetKeyForIndexImpl(*dict, index); | 943 uint32_t index = GetIndexForEntryImpl(*dict, entry); |
| 945 Handle<Object> result = SeededNumberDictionary::DeleteProperty(dict, index); | 944 Handle<Object> result = SeededNumberDictionary::DeleteProperty(dict, entry); |
| 946 USE(result); | 945 USE(result); |
| 947 DCHECK(result->IsTrue()); | 946 DCHECK(result->IsTrue()); |
| 948 Handle<FixedArray> new_elements = SeededNumberDictionary::Shrink(dict, key); | 947 Handle<FixedArray> new_elements = |
| 948 SeededNumberDictionary::Shrink(dict, index); | |
| 949 obj->set_elements(*new_elements); | 949 obj->set_elements(*new_elements); |
| 950 } | 950 } |
| 951 | 951 |
| 952 static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key, | 952 static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t index, |
| 953 Handle<FixedArrayBase> store) { | 953 Handle<FixedArrayBase> store) { |
| 954 Handle<SeededNumberDictionary> backing_store = | 954 Handle<SeededNumberDictionary> backing_store = |
| 955 Handle<SeededNumberDictionary>::cast(store); | 955 Handle<SeededNumberDictionary>::cast(store); |
| 956 Isolate* isolate = backing_store->GetIsolate(); | 956 Isolate* isolate = backing_store->GetIsolate(); |
| 957 int entry = backing_store->FindEntry(key); | 957 int entry = backing_store->FindEntry(index); |
| 958 if (entry != SeededNumberDictionary::kNotFound) { | 958 if (entry != SeededNumberDictionary::kNotFound) { |
| 959 return handle(backing_store->ValueAt(entry), isolate); | 959 return handle(backing_store->ValueAt(entry), isolate); |
| 960 } | 960 } |
| 961 return isolate->factory()->the_hole_value(); | 961 return isolate->factory()->the_hole_value(); |
| 962 } | 962 } |
| 963 | 963 |
| 964 static void SetImpl(FixedArrayBase* store, uint32_t key, Object* value) { | 964 static void SetImpl(FixedArrayBase* store, uint32_t index, Object* value) { |
| 965 SeededNumberDictionary* dictionary = SeededNumberDictionary::cast(store); | 965 SeededNumberDictionary* dictionary = SeededNumberDictionary::cast(store); |
| 966 int entry = dictionary->FindEntry(key); | 966 int entry = dictionary->FindEntry(index); |
| 967 DCHECK_NE(SeededNumberDictionary::kNotFound, entry); | 967 DCHECK_NE(SeededNumberDictionary::kNotFound, entry); |
| 968 dictionary->ValueAtPut(entry, value); | 968 dictionary->ValueAtPut(entry, value); |
| 969 } | 969 } |
| 970 | 970 |
| 971 static void ReconfigureImpl(Handle<JSObject> object, | 971 static void ReconfigureImpl(Handle<JSObject> object, |
| 972 Handle<FixedArrayBase> store, uint32_t index, | 972 Handle<FixedArrayBase> store, uint32_t entry, |
| 973 Handle<Object> value, | 973 Handle<Object> value, |
| 974 PropertyAttributes attributes) { | 974 PropertyAttributes attributes) { |
| 975 SeededNumberDictionary* dictionary = SeededNumberDictionary::cast(*store); | 975 SeededNumberDictionary* dictionary = SeededNumberDictionary::cast(*store); |
| 976 if (attributes != NONE) dictionary->set_requires_slow_elements(); | 976 if (attributes != NONE) dictionary->set_requires_slow_elements(); |
| 977 dictionary->ValueAtPut(index, *value); | 977 dictionary->ValueAtPut(entry, *value); |
| 978 PropertyDetails details = dictionary->DetailsAt(index); | 978 PropertyDetails details = dictionary->DetailsAt(entry); |
| 979 details = PropertyDetails(attributes, DATA, details.dictionary_index(), | 979 details = PropertyDetails(attributes, DATA, details.dictionary_index(), |
| 980 PropertyCellType::kNoCell); | 980 PropertyCellType::kNoCell); |
| 981 dictionary->DetailsAtPut(index, details); | 981 dictionary->DetailsAtPut(entry, details); |
| 982 } | 982 } |
| 983 | 983 |
| 984 static void AddImpl(Handle<JSObject> object, uint32_t index, | 984 static void AddImpl(Handle<JSObject> object, uint32_t entry, |
| 985 Handle<Object> value, PropertyAttributes attributes, | 985 Handle<Object> value, PropertyAttributes attributes, |
| 986 uint32_t new_capacity) { | 986 uint32_t new_capacity) { |
| 987 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); | 987 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); |
| 988 Handle<SeededNumberDictionary> dictionary = | 988 Handle<SeededNumberDictionary> dictionary = |
| 989 object->HasFastElements() | 989 object->HasFastElements() |
| 990 ? JSObject::NormalizeElements(object) | 990 ? JSObject::NormalizeElements(object) |
| 991 : handle(SeededNumberDictionary::cast(object->elements())); | 991 : handle(SeededNumberDictionary::cast(object->elements())); |
| 992 Handle<SeededNumberDictionary> new_dictionary = | 992 Handle<SeededNumberDictionary> new_dictionary = |
| 993 SeededNumberDictionary::AddNumberEntry(dictionary, index, value, | 993 SeededNumberDictionary::AddNumberEntry(dictionary, entry, value, |
| 994 details); | 994 details); |
| 995 if (attributes != NONE) new_dictionary->set_requires_slow_elements(); | 995 if (attributes != NONE) new_dictionary->set_requires_slow_elements(); |
| 996 if (dictionary.is_identical_to(new_dictionary)) return; | 996 if (dictionary.is_identical_to(new_dictionary)) return; |
| 997 object->set_elements(*new_dictionary); | 997 object->set_elements(*new_dictionary); |
| 998 } | 998 } |
| 999 | 999 |
| 1000 static bool HasIndexImpl(FixedArrayBase* store, uint32_t index) { | 1000 static bool HasEntryImpl(FixedArrayBase* store, uint32_t entry) { |
| 1001 DisallowHeapAllocation no_gc; | 1001 DisallowHeapAllocation no_gc; |
| 1002 SeededNumberDictionary* dict = SeededNumberDictionary::cast(store); | 1002 SeededNumberDictionary* dict = SeededNumberDictionary::cast(store); |
| 1003 Object* key = dict->KeyAt(index); | 1003 Object* index = dict->KeyAt(entry); |
| 1004 return !key->IsTheHole(); | 1004 return !index->IsTheHole(); |
| 1005 } | 1005 } |
| 1006 | 1006 |
| 1007 static uint32_t GetKeyForIndexImpl(FixedArrayBase* store, uint32_t index) { | 1007 static uint32_t GetIndexForEntryImpl(FixedArrayBase* store, uint32_t entry) { |
| 1008 DisallowHeapAllocation no_gc; | 1008 DisallowHeapAllocation no_gc; |
| 1009 SeededNumberDictionary* dict = SeededNumberDictionary::cast(store); | 1009 SeededNumberDictionary* dict = SeededNumberDictionary::cast(store); |
| 1010 uint32_t result = 0; | 1010 uint32_t result = 0; |
| 1011 CHECK(dict->KeyAt(index)->ToArrayIndex(&result)); | 1011 CHECK(dict->KeyAt(entry)->ToArrayIndex(&result)); |
| 1012 return result; | 1012 return result; |
| 1013 } | 1013 } |
| 1014 | 1014 |
| 1015 static uint32_t GetIndexForKeyImpl(JSObject* holder, FixedArrayBase* store, | 1015 static uint32_t GetEntryForIndexImpl(JSObject* holder, FixedArrayBase* store, |
| 1016 uint32_t key) { | 1016 uint32_t index) { |
| 1017 DisallowHeapAllocation no_gc; | 1017 DisallowHeapAllocation no_gc; |
| 1018 SeededNumberDictionary* dict = SeededNumberDictionary::cast(store); | 1018 SeededNumberDictionary* dict = SeededNumberDictionary::cast(store); |
| 1019 int entry = dict->FindEntry(key); | 1019 int entry = dict->FindEntry(index); |
| 1020 return entry == SeededNumberDictionary::kNotFound | 1020 return entry == SeededNumberDictionary::kNotFound |
| 1021 ? kMaxUInt32 | 1021 ? kMaxUInt32 |
| 1022 : static_cast<uint32_t>(entry); | 1022 : static_cast<uint32_t>(entry); |
| 1023 } | 1023 } |
| 1024 | 1024 |
| 1025 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, | 1025 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, |
| 1026 uint32_t index) { | 1026 uint32_t entry) { |
| 1027 return SeededNumberDictionary::cast(backing_store)->DetailsAt(index); | 1027 return SeededNumberDictionary::cast(backing_store)->DetailsAt(entry); |
| 1028 } | 1028 } |
| 1029 }; | 1029 }; |
| 1030 | 1030 |
| 1031 | 1031 |
| 1032 // Super class for all fast element arrays. | 1032 // Super class for all fast element arrays. |
| 1033 template<typename FastElementsAccessorSubclass, | 1033 template<typename FastElementsAccessorSubclass, |
| 1034 typename KindTraits> | 1034 typename KindTraits> |
| 1035 class FastElementsAccessor | 1035 class FastElementsAccessor |
| 1036 : public ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits> { | 1036 : public ElementsAccessorBase<FastElementsAccessorSubclass, KindTraits> { |
| 1037 public: | 1037 public: |
| 1038 explicit FastElementsAccessor(const char* name) | 1038 explicit FastElementsAccessor(const char* name) |
| 1039 : ElementsAccessorBase<FastElementsAccessorSubclass, | 1039 : ElementsAccessorBase<FastElementsAccessorSubclass, |
| 1040 KindTraits>(name) {} | 1040 KindTraits>(name) {} |
| 1041 | 1041 |
| 1042 typedef typename KindTraits::BackingStore BackingStore; | 1042 typedef typename KindTraits::BackingStore BackingStore; |
| 1043 | 1043 |
| 1044 static void DeleteCommon(Handle<JSObject> obj, uint32_t index, | 1044 static void DeleteCommon(Handle<JSObject> obj, uint32_t entry, |
| 1045 Handle<FixedArrayBase> store) { | 1045 Handle<FixedArrayBase> store) { |
| 1046 DCHECK(obj->HasFastSmiOrObjectElements() || | 1046 DCHECK(obj->HasFastSmiOrObjectElements() || |
| 1047 obj->HasFastDoubleElements() || | 1047 obj->HasFastDoubleElements() || |
| 1048 obj->HasFastArgumentsElements()); | 1048 obj->HasFastArgumentsElements()); |
| 1049 Handle<BackingStore> backing_store = Handle<BackingStore>::cast(store); | 1049 Handle<BackingStore> backing_store = Handle<BackingStore>::cast(store); |
| 1050 backing_store->set_the_hole(index); | 1050 backing_store->set_the_hole(entry); |
| 1051 | 1051 |
| 1052 // TODO(verwaest): Move this out of elements.cc. | 1052 // TODO(verwaest): Move this out of elements.cc. |
| 1053 // If an old space backing store is larger than a certain size and | 1053 // If an old space backing store is larger than a certain size and |
| 1054 // has too few used values, normalize it. | 1054 // has too few used values, normalize it. |
| 1055 // To avoid doing the check on every delete we require at least | 1055 // To avoid doing the check on every delete we require at least |
| 1056 // one adjacent hole to the value being deleted. | 1056 // one adjacent hole to the value being deleted. |
| 1057 const int kMinLengthForSparsenessCheck = 64; | 1057 const int kMinLengthForSparsenessCheck = 64; |
| 1058 if (backing_store->length() < kMinLengthForSparsenessCheck) return; | 1058 if (backing_store->length() < kMinLengthForSparsenessCheck) return; |
| 1059 if (backing_store->GetHeap()->InNewSpace(*backing_store)) return; | 1059 if (backing_store->GetHeap()->InNewSpace(*backing_store)) return; |
| 1060 uint32_t length = 0; | 1060 uint32_t length = 0; |
| 1061 if (obj->IsJSArray()) { | 1061 if (obj->IsJSArray()) { |
| 1062 JSArray::cast(*obj)->length()->ToArrayLength(&length); | 1062 JSArray::cast(*obj)->length()->ToArrayLength(&length); |
| 1063 } else { | 1063 } else { |
| 1064 length = static_cast<uint32_t>(store->length()); | 1064 length = static_cast<uint32_t>(store->length()); |
| 1065 } | 1065 } |
| 1066 if ((index > 0 && backing_store->is_the_hole(index - 1)) || | 1066 if ((entry > 0 && backing_store->is_the_hole(entry - 1)) || |
| 1067 (index + 1 < length && backing_store->is_the_hole(index + 1))) { | 1067 (entry + 1 < length && backing_store->is_the_hole(entry + 1))) { |
| 1068 int num_used = 0; | 1068 int num_used = 0; |
| 1069 for (int i = 0; i < backing_store->length(); ++i) { | 1069 for (int i = 0; i < backing_store->length(); ++i) { |
| 1070 if (!backing_store->is_the_hole(i)) ++num_used; | 1070 if (!backing_store->is_the_hole(i)) ++num_used; |
| 1071 // Bail out early if more than 1/4 is used. | 1071 // Bail out early if more than 1/4 is used. |
| 1072 if (4 * num_used > backing_store->length()) break; | 1072 if (4 * num_used > backing_store->length()) break; |
| 1073 } | 1073 } |
| 1074 if (4 * num_used <= backing_store->length()) { | 1074 if (4 * num_used <= backing_store->length()) { |
| 1075 JSObject::NormalizeElements(obj); | 1075 JSObject::NormalizeElements(obj); |
| 1076 } | 1076 } |
| 1077 } | 1077 } |
| 1078 } | 1078 } |
| 1079 | 1079 |
| 1080 static void ReconfigureImpl(Handle<JSObject> object, | 1080 static void ReconfigureImpl(Handle<JSObject> object, |
| 1081 Handle<FixedArrayBase> store, uint32_t index, | 1081 Handle<FixedArrayBase> store, uint32_t entry, |
| 1082 Handle<Object> value, | 1082 Handle<Object> value, |
| 1083 PropertyAttributes attributes) { | 1083 PropertyAttributes attributes) { |
| 1084 Handle<SeededNumberDictionary> dictionary = | 1084 Handle<SeededNumberDictionary> dictionary = |
| 1085 JSObject::NormalizeElements(object); | 1085 JSObject::NormalizeElements(object); |
| 1086 index = dictionary->FindEntry(index); | 1086 entry = dictionary->FindEntry(entry); |
| 1087 DictionaryElementsAccessor::ReconfigureImpl(object, dictionary, index, | 1087 DictionaryElementsAccessor::ReconfigureImpl(object, dictionary, entry, |
| 1088 value, attributes); | 1088 value, attributes); |
| 1089 } | 1089 } |
| 1090 | 1090 |
| 1091 static void AddImpl(Handle<JSObject> object, uint32_t index, | 1091 static void AddImpl(Handle<JSObject> object, uint32_t entry, |
| 1092 Handle<Object> value, PropertyAttributes attributes, | 1092 Handle<Object> value, PropertyAttributes attributes, |
| 1093 uint32_t new_capacity) { | 1093 uint32_t new_capacity) { |
| 1094 DCHECK_EQ(NONE, attributes); | 1094 DCHECK_EQ(NONE, attributes); |
| 1095 ElementsKind from_kind = object->GetElementsKind(); | 1095 ElementsKind from_kind = object->GetElementsKind(); |
| 1096 ElementsKind to_kind = FastElementsAccessorSubclass::kind(); | 1096 ElementsKind to_kind = FastElementsAccessorSubclass::kind(); |
| 1097 if (IsDictionaryElementsKind(from_kind) || | 1097 if (IsDictionaryElementsKind(from_kind) || |
| 1098 IsFastDoubleElementsKind(from_kind) != | 1098 IsFastDoubleElementsKind(from_kind) != |
| 1099 IsFastDoubleElementsKind(to_kind) || | 1099 IsFastDoubleElementsKind(to_kind) || |
| 1100 FastElementsAccessorSubclass::GetCapacityImpl( | 1100 FastElementsAccessorSubclass::GetCapacityImpl( |
| 1101 *object, object->elements()) != new_capacity) { | 1101 *object, object->elements()) != new_capacity) { |
| 1102 FastElementsAccessorSubclass::GrowCapacityAndConvertImpl(object, | 1102 FastElementsAccessorSubclass::GrowCapacityAndConvertImpl(object, |
| 1103 new_capacity); | 1103 new_capacity); |
| 1104 } else { | 1104 } else { |
| 1105 if (from_kind != to_kind) { | 1105 if (from_kind != to_kind) { |
| 1106 JSObject::TransitionElementsKind(object, to_kind); | 1106 JSObject::TransitionElementsKind(object, to_kind); |
| 1107 } | 1107 } |
| 1108 if (IsFastSmiOrObjectElementsKind(from_kind)) { | 1108 if (IsFastSmiOrObjectElementsKind(from_kind)) { |
| 1109 DCHECK(IsFastSmiOrObjectElementsKind(to_kind)); | 1109 DCHECK(IsFastSmiOrObjectElementsKind(to_kind)); |
| 1110 JSObject::EnsureWritableFastElements(object); | 1110 JSObject::EnsureWritableFastElements(object); |
| 1111 } | 1111 } |
| 1112 } | 1112 } |
| 1113 FastElementsAccessorSubclass::SetImpl(object->elements(), index, *value); | 1113 FastElementsAccessorSubclass::SetImpl(object->elements(), entry, *value); |
| 1114 } | 1114 } |
| 1115 | 1115 |
| 1116 static void DeleteImpl(Handle<JSObject> obj, uint32_t index) { | 1116 static void DeleteImpl(Handle<JSObject> obj, uint32_t entry) { |
| 1117 ElementsKind kind = KindTraits::Kind; | 1117 ElementsKind kind = KindTraits::Kind; |
| 1118 if (IsFastPackedElementsKind(kind)) { | 1118 if (IsFastPackedElementsKind(kind)) { |
| 1119 JSObject::TransitionElementsKind(obj, GetHoleyElementsKind(kind)); | 1119 JSObject::TransitionElementsKind(obj, GetHoleyElementsKind(kind)); |
| 1120 } | 1120 } |
| 1121 if (IsFastSmiOrObjectElementsKind(KindTraits::Kind)) { | 1121 if (IsFastSmiOrObjectElementsKind(KindTraits::Kind)) { |
| 1122 JSObject::EnsureWritableFastElements(obj); | 1122 JSObject::EnsureWritableFastElements(obj); |
| 1123 } | 1123 } |
| 1124 DeleteCommon(obj, index, handle(obj->elements())); | 1124 DeleteCommon(obj, entry, handle(obj->elements())); |
| 1125 } | 1125 } |
| 1126 | 1126 |
| 1127 static bool HasIndexImpl(FixedArrayBase* backing_store, uint32_t index) { | 1127 static bool HasEntryImpl(FixedArrayBase* backing_store, uint32_t entry) { |
| 1128 return !BackingStore::cast(backing_store)->is_the_hole(index); | 1128 return !BackingStore::cast(backing_store)->is_the_hole(entry); |
| 1129 } | 1129 } |
| 1130 | 1130 |
| 1131 static void ValidateContents(Handle<JSObject> holder, int length) { | 1131 static void ValidateContents(Handle<JSObject> holder, int length) { |
| 1132 #if DEBUG | 1132 #if DEBUG |
| 1133 Isolate* isolate = holder->GetIsolate(); | 1133 Isolate* isolate = holder->GetIsolate(); |
| 1134 HandleScope scope(isolate); | 1134 HandleScope scope(isolate); |
| 1135 Handle<FixedArrayBase> elements(holder->elements(), isolate); | 1135 Handle<FixedArrayBase> elements(holder->elements(), isolate); |
| 1136 Map* map = elements->map(); | 1136 Map* map = elements->map(); |
| 1137 DCHECK((IsFastSmiOrObjectElementsKind(KindTraits::Kind) && | 1137 DCHECK((IsFastSmiOrObjectElementsKind(KindTraits::Kind) && |
| 1138 (map == isolate->heap()->fixed_array_map() || | 1138 (map == isolate->heap()->fixed_array_map() || |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1335 : public ElementsAccessorBase<TypedElementsAccessor<Kind>, | 1335 : public ElementsAccessorBase<TypedElementsAccessor<Kind>, |
| 1336 ElementsKindTraits<Kind> > { | 1336 ElementsKindTraits<Kind> > { |
| 1337 public: | 1337 public: |
| 1338 explicit TypedElementsAccessor(const char* name) | 1338 explicit TypedElementsAccessor(const char* name) |
| 1339 : ElementsAccessorBase<AccessorClass, | 1339 : ElementsAccessorBase<AccessorClass, |
| 1340 ElementsKindTraits<Kind> >(name) {} | 1340 ElementsKindTraits<Kind> >(name) {} |
| 1341 | 1341 |
| 1342 typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore; | 1342 typedef typename ElementsKindTraits<Kind>::BackingStore BackingStore; |
| 1343 typedef TypedElementsAccessor<Kind> AccessorClass; | 1343 typedef TypedElementsAccessor<Kind> AccessorClass; |
| 1344 | 1344 |
| 1345 static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key, | 1345 static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t index, |
| 1346 Handle<FixedArrayBase> backing_store) { | 1346 Handle<FixedArrayBase> backing_store) { |
| 1347 if (key < AccessorClass::GetCapacityImpl(*obj, *backing_store)) { | 1347 if (index < AccessorClass::GetCapacityImpl(*obj, *backing_store)) { |
| 1348 return BackingStore::get(Handle<BackingStore>::cast(backing_store), key); | 1348 return BackingStore::get(Handle<BackingStore>::cast(backing_store), |
| 1349 index); | |
| 1349 } else { | 1350 } else { |
| 1350 return backing_store->GetIsolate()->factory()->undefined_value(); | 1351 return backing_store->GetIsolate()->factory()->undefined_value(); |
| 1351 } | 1352 } |
| 1352 } | 1353 } |
| 1353 | 1354 |
| 1354 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, | 1355 static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, |
| 1355 uint32_t index) { | 1356 uint32_t entry) { |
| 1356 return PropertyDetails(DONT_DELETE, DATA, 0, PropertyCellType::kNoCell); | 1357 return PropertyDetails(DONT_DELETE, DATA, 0, PropertyCellType::kNoCell); |
| 1357 } | 1358 } |
| 1358 | 1359 |
| 1359 static void SetLengthImpl(Handle<JSArray> array, uint32_t length, | 1360 static void SetLengthImpl(Handle<JSArray> array, uint32_t length, |
| 1360 Handle<FixedArrayBase> backing_store) { | 1361 Handle<FixedArrayBase> backing_store) { |
| 1361 // External arrays do not support changing their length. | 1362 // External arrays do not support changing their length. |
| 1362 UNREACHABLE(); | 1363 UNREACHABLE(); |
| 1363 } | 1364 } |
| 1364 | 1365 |
| 1365 static void DeleteImpl(Handle<JSObject> obj, uint32_t index) { | 1366 static void DeleteImpl(Handle<JSObject> obj, uint32_t entry) { |
| 1366 UNREACHABLE(); | 1367 UNREACHABLE(); |
| 1367 } | 1368 } |
| 1368 | 1369 |
| 1369 static uint32_t GetIndexForKeyImpl(JSObject* holder, | 1370 static uint32_t GetEntryForIndexImpl(JSObject* holder, |
| 1370 FixedArrayBase* backing_store, | 1371 FixedArrayBase* backing_store, |
| 1371 uint32_t key) { | 1372 uint32_t index) { |
| 1372 return key < AccessorClass::GetCapacityImpl(holder, backing_store) | 1373 return index < AccessorClass::GetCapacityImpl(holder, backing_store) |
| 1373 ? key | 1374 ? index |
| 1374 : kMaxUInt32; | 1375 : kMaxUInt32; |
| 1375 } | 1376 } |
| 1376 | 1377 |
| 1377 static uint32_t GetCapacityImpl(JSObject* holder, | 1378 static uint32_t GetCapacityImpl(JSObject* holder, |
| 1378 FixedArrayBase* backing_store) { | 1379 FixedArrayBase* backing_store) { |
| 1379 JSArrayBufferView* view = JSArrayBufferView::cast(holder); | 1380 JSArrayBufferView* view = JSArrayBufferView::cast(holder); |
| 1380 if (view->WasNeutered()) return 0; | 1381 if (view->WasNeutered()) return 0; |
| 1381 return backing_store->length(); | 1382 return backing_store->length(); |
| 1382 } | 1383 } |
| 1383 }; | 1384 }; |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 1402 template <typename SloppyArgumentsElementsAccessorSubclass, | 1403 template <typename SloppyArgumentsElementsAccessorSubclass, |
| 1403 typename ArgumentsAccessor, typename KindTraits> | 1404 typename ArgumentsAccessor, typename KindTraits> |
| 1404 class SloppyArgumentsElementsAccessor | 1405 class SloppyArgumentsElementsAccessor |
| 1405 : public ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass, | 1406 : public ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass, |
| 1406 KindTraits> { | 1407 KindTraits> { |
| 1407 public: | 1408 public: |
| 1408 explicit SloppyArgumentsElementsAccessor(const char* name) | 1409 explicit SloppyArgumentsElementsAccessor(const char* name) |
| 1409 : ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass, | 1410 : ElementsAccessorBase<SloppyArgumentsElementsAccessorSubclass, |
| 1410 KindTraits>(name) {} | 1411 KindTraits>(name) {} |
| 1411 | 1412 |
| 1412 static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t key, | 1413 static Handle<Object> GetImpl(Handle<JSObject> obj, uint32_t index, |
| 1413 Handle<FixedArrayBase> parameters) { | 1414 Handle<FixedArrayBase> parameters) { |
| 1414 Isolate* isolate = obj->GetIsolate(); | 1415 Isolate* isolate = obj->GetIsolate(); |
| 1415 Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters); | 1416 Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(parameters); |
| 1416 Handle<Object> probe(GetParameterMapArg(*parameter_map, key), isolate); | 1417 Handle<Object> probe(GetParameterMapArg(*parameter_map, index), isolate); |
| 1417 if (!probe->IsTheHole()) { | 1418 if (!probe->IsTheHole()) { |
| 1418 DisallowHeapAllocation no_gc; | 1419 DisallowHeapAllocation no_gc; |
| 1419 Context* context = Context::cast(parameter_map->get(0)); | 1420 Context* context = Context::cast(parameter_map->get(0)); |
| 1420 int context_index = Handle<Smi>::cast(probe)->value(); | 1421 int context_entry = Handle<Smi>::cast(probe)->value(); |
| 1421 DCHECK(!context->get(context_index)->IsTheHole()); | 1422 DCHECK(!context->get(context_entry)->IsTheHole()); |
| 1422 return handle(context->get(context_index), isolate); | 1423 return handle(context->get(context_entry), isolate); |
| 1423 } else { | 1424 } else { |
| 1424 // Object is not mapped, defer to the arguments. | 1425 // Object is not mapped, defer to the arguments. |
| 1425 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)), | 1426 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1)), |
| 1426 isolate); | 1427 isolate); |
| 1427 Handle<Object> result = ArgumentsAccessor::GetImpl(obj, key, arguments); | 1428 Handle<Object> result = ArgumentsAccessor::GetImpl(obj, index, arguments); |
| 1428 // Elements of the arguments object in slow mode might be slow aliases. | 1429 // Elements of the arguments object in slow mode might be slow aliases. |
| 1429 if (result->IsAliasedArgumentsEntry()) { | 1430 if (result->IsAliasedArgumentsEntry()) { |
| 1430 DisallowHeapAllocation no_gc; | 1431 DisallowHeapAllocation no_gc; |
| 1431 AliasedArgumentsEntry* entry = AliasedArgumentsEntry::cast(*result); | 1432 AliasedArgumentsEntry* entry = AliasedArgumentsEntry::cast(*result); |
| 1432 Context* context = Context::cast(parameter_map->get(0)); | 1433 Context* context = Context::cast(parameter_map->get(0)); |
| 1433 int context_index = entry->aliased_context_slot(); | 1434 int context_entry = entry->aliased_context_slot(); |
| 1434 DCHECK(!context->get(context_index)->IsTheHole()); | 1435 DCHECK(!context->get(context_entry)->IsTheHole()); |
| 1435 return handle(context->get(context_index), isolate); | 1436 return handle(context->get(context_entry), isolate); |
| 1436 } else { | 1437 } else { |
| 1437 return result; | 1438 return result; |
| 1438 } | 1439 } |
| 1439 } | 1440 } |
| 1440 } | 1441 } |
| 1441 | 1442 |
| 1442 static void GrowCapacityAndConvertImpl(Handle<JSObject> object, | 1443 static void GrowCapacityAndConvertImpl(Handle<JSObject> object, |
| 1443 uint32_t capacity) { | 1444 uint32_t capacity) { |
| 1444 UNREACHABLE(); | 1445 UNREACHABLE(); |
| 1445 } | 1446 } |
| 1446 | 1447 |
| 1447 static void SetImpl(FixedArrayBase* store, uint32_t key, Object* value) { | 1448 static void SetImpl(FixedArrayBase* store, uint32_t index, Object* value) { |
| 1448 FixedArray* parameter_map = FixedArray::cast(store); | 1449 FixedArray* parameter_map = FixedArray::cast(store); |
| 1449 Object* probe = GetParameterMapArg(parameter_map, key); | 1450 Object* probe = GetParameterMapArg(parameter_map, index); |
| 1450 if (!probe->IsTheHole()) { | 1451 if (!probe->IsTheHole()) { |
| 1451 Context* context = Context::cast(parameter_map->get(0)); | 1452 Context* context = Context::cast(parameter_map->get(0)); |
| 1452 int context_index = Smi::cast(probe)->value(); | 1453 int context_entry = Smi::cast(probe)->value(); |
| 1453 DCHECK(!context->get(context_index)->IsTheHole()); | 1454 DCHECK(!context->get(context_entry)->IsTheHole()); |
| 1454 context->set(context_index, value); | 1455 context->set(context_entry, value); |
| 1455 } else { | 1456 } else { |
| 1456 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1457 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 1457 ArgumentsAccessor::SetImpl(arguments, key, value); | 1458 ArgumentsAccessor::SetImpl(arguments, index, value); |
| 1458 } | 1459 } |
| 1459 } | 1460 } |
| 1460 | 1461 |
| 1461 static void SetLengthImpl(Handle<JSArray> array, uint32_t length, | 1462 static void SetLengthImpl(Handle<JSArray> array, uint32_t length, |
| 1462 Handle<FixedArrayBase> parameter_map) { | 1463 Handle<FixedArrayBase> parameter_map) { |
| 1463 // Sloppy arguments objects are not arrays. | 1464 // Sloppy arguments objects are not arrays. |
| 1464 UNREACHABLE(); | 1465 UNREACHABLE(); |
| 1465 } | 1466 } |
| 1466 | 1467 |
| 1467 static uint32_t GetCapacityImpl(JSObject* holder, | 1468 static uint32_t GetCapacityImpl(JSObject* holder, |
| 1468 FixedArrayBase* backing_store) { | 1469 FixedArrayBase* backing_store) { |
| 1469 FixedArray* parameter_map = FixedArray::cast(backing_store); | 1470 FixedArray* parameter_map = FixedArray::cast(backing_store); |
| 1470 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); | 1471 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); |
| 1471 return parameter_map->length() - 2 + | 1472 return parameter_map->length() - 2 + |
| 1472 ArgumentsAccessor::GetCapacityImpl(holder, arguments); | 1473 ArgumentsAccessor::GetCapacityImpl(holder, arguments); |
| 1473 } | 1474 } |
| 1474 | 1475 |
| 1475 static bool HasIndexImpl(FixedArrayBase* parameters, uint32_t index) { | 1476 static bool HasEntryImpl(FixedArrayBase* parameters, uint32_t entry) { |
| 1476 FixedArray* parameter_map = FixedArray::cast(parameters); | 1477 FixedArray* parameter_map = FixedArray::cast(parameters); |
| 1477 uint32_t length = parameter_map->length() - 2; | 1478 uint32_t length = parameter_map->length() - 2; |
| 1478 if (index < length) { | 1479 if (entry < length) { |
| 1479 return !GetParameterMapArg(parameter_map, index)->IsTheHole(); | 1480 return !GetParameterMapArg(parameter_map, entry)->IsTheHole(); |
| 1480 } | 1481 } |
| 1481 | 1482 |
| 1482 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); | 1483 FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); |
| 1483 return ArgumentsAccessor::HasIndexImpl(arguments, index - length); | 1484 return ArgumentsAccessor::HasEntryImpl(arguments, entry - length); |
| 1484 } | 1485 } |
| 1485 | 1486 |
| 1486 static uint32_t GetKeyForIndexImpl(FixedArrayBase* parameters, | 1487 static uint32_t GetIndexForEntryImpl(FixedArrayBase* parameters, |
| 1487 uint32_t index) { | 1488 uint32_t entry) { |
| 1488 FixedArray* parameter_map = FixedArray::cast(parameters); | 1489 FixedArray* parameter_map = FixedArray::cast(parameters); |
| 1489 uint32_t length = parameter_map->length() - 2; | 1490 uint32_t length = parameter_map->length() - 2; |
| 1490 if (index < length) return index; | 1491 if (entry < length) return entry; |
| 1491 | 1492 |
| 1492 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1493 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 1493 return ArgumentsAccessor::GetKeyForIndexImpl(arguments, index - length); | 1494 return ArgumentsAccessor::GetIndexForEntryImpl(arguments, entry - length); |
| 1494 } | 1495 } |
| 1495 | 1496 |
| 1496 static uint32_t GetIndexForKeyImpl(JSObject* holder, | 1497 static uint32_t GetEntryForIndexImpl(JSObject* holder, |
| 1497 FixedArrayBase* parameters, uint32_t key) { | 1498 FixedArrayBase* parameters, |
| 1499 uint32_t index) { | |
| 1498 FixedArray* parameter_map = FixedArray::cast(parameters); | 1500 FixedArray* parameter_map = FixedArray::cast(parameters); |
| 1499 Object* probe = GetParameterMapArg(parameter_map, key); | 1501 Object* probe = GetParameterMapArg(parameter_map, index); |
| 1500 if (!probe->IsTheHole()) return key; | 1502 if (!probe->IsTheHole()) return index; |
| 1501 | 1503 |
| 1502 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1504 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 1503 uint32_t index = | 1505 uint32_t entry = |
| 1504 ArgumentsAccessor::GetIndexForKeyImpl(holder, arguments, key); | 1506 ArgumentsAccessor::GetEntryForIndexImpl(holder, arguments, index); |
| 1505 if (index == kMaxUInt32) return index; | 1507 if (entry == kMaxUInt32) return entry; |
| 1506 return (parameter_map->length() - 2) + index; | 1508 return (parameter_map->length() - 2) + entry; |
| 1507 } | 1509 } |
| 1508 | 1510 |
| 1509 static PropertyDetails GetDetailsImpl(FixedArrayBase* parameters, | 1511 static PropertyDetails GetDetailsImpl(FixedArrayBase* parameters, |
| 1510 uint32_t index) { | 1512 uint32_t entry) { |
| 1511 FixedArray* parameter_map = FixedArray::cast(parameters); | 1513 FixedArray* parameter_map = FixedArray::cast(parameters); |
| 1512 uint32_t length = parameter_map->length() - 2; | 1514 uint32_t length = parameter_map->length() - 2; |
| 1513 if (index < length) { | 1515 if (entry < length) { |
| 1514 return PropertyDetails(NONE, DATA, 0, PropertyCellType::kNoCell); | 1516 return PropertyDetails(NONE, DATA, 0, PropertyCellType::kNoCell); |
| 1515 } | 1517 } |
| 1516 index -= length; | 1518 entry -= length; |
| 1517 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 1519 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
| 1518 return ArgumentsAccessor::GetDetailsImpl(arguments, index); | 1520 return ArgumentsAccessor::GetDetailsImpl(arguments, entry); |
| 1519 } | 1521 } |
| 1520 | 1522 |
| 1521 static Object* GetParameterMapArg(FixedArray* parameter_map, uint32_t key) { | 1523 static Object* GetParameterMapArg(FixedArray* parameter_map, uint32_t index) { |
| 1522 uint32_t length = parameter_map->length() - 2; | 1524 uint32_t length = parameter_map->length() - 2; |
| 1523 return key < length | 1525 return index < length |
| 1524 ? parameter_map->get(key + 2) | 1526 ? parameter_map->get(index + 2) |
| 1525 : Object::cast(parameter_map->GetHeap()->the_hole_value()); | 1527 : Object::cast(parameter_map->GetHeap()->the_hole_value()); |
| 1526 } | 1528 } |
| 1527 | 1529 |
| 1528 static void DeleteImpl(Handle<JSObject> obj, uint32_t index) { | 1530 static void DeleteImpl(Handle<JSObject> obj, uint32_t entry) { |
| 1529 FixedArray* parameter_map = FixedArray::cast(obj->elements()); | 1531 FixedArray* parameter_map = FixedArray::cast(obj->elements()); |
| 1530 uint32_t length = static_cast<uint32_t>(parameter_map->length()) - 2; | 1532 uint32_t length = static_cast<uint32_t>(parameter_map->length()) - 2; |
| 1531 if (index < length) { | 1533 if (entry < length) { |
| 1532 // TODO(kmillikin): We could check if this was the last aliased | 1534 // TODO(kmillikin): We could check if this was the last aliased |
| 1533 // parameter, and revert to normal elements in that case. That | 1535 // parameter, and revert to normal elements in that case. That |
| 1534 // would enable GC of the context. | 1536 // would enable GC of the context. |
| 1535 parameter_map->set_the_hole(index + 2); | 1537 parameter_map->set_the_hole(entry + 2); |
| 1536 } else { | 1538 } else { |
| 1537 SloppyArgumentsElementsAccessorSubclass::DeleteFromArguments( | 1539 SloppyArgumentsElementsAccessorSubclass::DeleteFromArguments( |
| 1538 obj, index - length); | 1540 obj, entry - length); |
| 1539 } | 1541 } |
| 1540 } | 1542 } |
| 1541 }; | 1543 }; |
| 1542 | 1544 |
| 1543 | 1545 |
| 1544 class SlowSloppyArgumentsElementsAccessor | 1546 class SlowSloppyArgumentsElementsAccessor |
| 1545 : public SloppyArgumentsElementsAccessor< | 1547 : public SloppyArgumentsElementsAccessor< |
| 1546 SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor, | 1548 SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor, |
| 1547 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> > { | 1549 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> > { |
| 1548 public: | 1550 public: |
| 1549 explicit SlowSloppyArgumentsElementsAccessor(const char* name) | 1551 explicit SlowSloppyArgumentsElementsAccessor(const char* name) |
| 1550 : SloppyArgumentsElementsAccessor< | 1552 : SloppyArgumentsElementsAccessor< |
| 1551 SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor, | 1553 SlowSloppyArgumentsElementsAccessor, DictionaryElementsAccessor, |
| 1552 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> >(name) {} | 1554 ElementsKindTraits<SLOW_SLOPPY_ARGUMENTS_ELEMENTS> >(name) {} |
| 1553 | 1555 |
| 1554 static void DeleteFromArguments(Handle<JSObject> obj, uint32_t index) { | 1556 static void DeleteFromArguments(Handle<JSObject> obj, uint32_t entry) { |
| 1555 Handle<FixedArray> parameter_map(FixedArray::cast(obj->elements())); | 1557 Handle<FixedArray> parameter_map(FixedArray::cast(obj->elements())); |
| 1556 Handle<SeededNumberDictionary> dict( | 1558 Handle<SeededNumberDictionary> dict( |
| 1557 SeededNumberDictionary::cast(parameter_map->get(1))); | 1559 SeededNumberDictionary::cast(parameter_map->get(1))); |
| 1558 // TODO(verwaest): Remove reliance on key in Shrink. | 1560 // TODO(verwaest): Remove reliance on index in Shrink. |
| 1559 uint32_t key = GetKeyForIndexImpl(*dict, index); | 1561 uint32_t index = GetIndexForEntryImpl(*dict, entry); |
| 1560 Handle<Object> result = SeededNumberDictionary::DeleteProperty(dict, index); | 1562 Handle<Object> result = SeededNumberDictionary::DeleteProperty(dict, entry); |
| 1561 USE(result); | 1563 USE(result); |
| 1562 DCHECK(result->IsTrue()); | 1564 DCHECK(result->IsTrue()); |
| 1563 Handle<FixedArray> new_elements = SeededNumberDictionary::Shrink(dict, key); | 1565 Handle<FixedArray> new_elements = |
| 1566 SeededNumberDictionary::Shrink(dict, index); | |
| 1564 parameter_map->set(1, *new_elements); | 1567 parameter_map->set(1, *new_elements); |
| 1565 } | 1568 } |
| 1566 | 1569 |
| 1567 static void AddImpl(Handle<JSObject> object, uint32_t key, | 1570 static void AddImpl(Handle<JSObject> object, uint32_t index, |
| 1568 Handle<Object> value, PropertyAttributes attributes, | 1571 Handle<Object> value, PropertyAttributes attributes, |
| 1569 uint32_t new_capacity) { | 1572 uint32_t new_capacity) { |
| 1570 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements())); | 1573 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements())); |
| 1571 Handle<FixedArrayBase> old_elements( | 1574 Handle<FixedArrayBase> old_elements( |
| 1572 FixedArrayBase::cast(parameter_map->get(1))); | 1575 FixedArrayBase::cast(parameter_map->get(1))); |
| 1573 Handle<SeededNumberDictionary> dictionary = | 1576 Handle<SeededNumberDictionary> dictionary = |
| 1574 old_elements->IsSeededNumberDictionary() | 1577 old_elements->IsSeededNumberDictionary() |
| 1575 ? Handle<SeededNumberDictionary>::cast(old_elements) | 1578 ? Handle<SeededNumberDictionary>::cast(old_elements) |
| 1576 : JSObject::NormalizeElements(object); | 1579 : JSObject::NormalizeElements(object); |
| 1577 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); | 1580 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); |
| 1578 Handle<SeededNumberDictionary> new_dictionary = | 1581 Handle<SeededNumberDictionary> new_dictionary = |
| 1579 SeededNumberDictionary::AddNumberEntry(dictionary, key, value, details); | 1582 SeededNumberDictionary::AddNumberEntry(dictionary, index, value, |
| 1583 details); | |
| 1580 if (attributes != NONE) new_dictionary->set_requires_slow_elements(); | 1584 if (attributes != NONE) new_dictionary->set_requires_slow_elements(); |
| 1581 if (*dictionary != *new_dictionary) { | 1585 if (*dictionary != *new_dictionary) { |
| 1582 FixedArray::cast(object->elements())->set(1, *new_dictionary); | 1586 FixedArray::cast(object->elements())->set(1, *new_dictionary); |
| 1583 } | 1587 } |
| 1584 } | 1588 } |
| 1585 | 1589 |
| 1586 static void ReconfigureImpl(Handle<JSObject> object, | 1590 static void ReconfigureImpl(Handle<JSObject> object, |
| 1587 Handle<FixedArrayBase> store, uint32_t index, | 1591 Handle<FixedArrayBase> store, uint32_t entry, |
| 1588 Handle<Object> value, | 1592 Handle<Object> value, |
| 1589 PropertyAttributes attributes) { | 1593 PropertyAttributes attributes) { |
| 1590 Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(store); | 1594 Handle<FixedArray> parameter_map = Handle<FixedArray>::cast(store); |
| 1591 uint32_t length = parameter_map->length() - 2; | 1595 uint32_t length = parameter_map->length() - 2; |
| 1592 if (index < length) { | 1596 if (entry < length) { |
| 1593 Object* probe = parameter_map->get(index + 2); | 1597 Object* probe = parameter_map->get(entry + 2); |
| 1594 DCHECK(!probe->IsTheHole()); | 1598 DCHECK(!probe->IsTheHole()); |
| 1595 Context* context = Context::cast(parameter_map->get(0)); | 1599 Context* context = Context::cast(parameter_map->get(0)); |
| 1596 int context_index = Smi::cast(probe)->value(); | 1600 int context_entry = Smi::cast(probe)->value(); |
| 1597 DCHECK(!context->get(context_index)->IsTheHole()); | 1601 DCHECK(!context->get(context_entry)->IsTheHole()); |
| 1598 context->set(context_index, *value); | 1602 context->set(context_entry, *value); |
| 1599 | 1603 |
| 1600 // Redefining attributes of an aliased element destroys fast aliasing. | 1604 // Redefining attributes of an aliased element destroys fast aliasing. |
| 1601 parameter_map->set_the_hole(index + 2); | 1605 parameter_map->set_the_hole(entry + 2); |
| 1602 // For elements that are still writable we re-establish slow aliasing. | 1606 // For elements that are still writable we re-establish slow aliasing. |
| 1603 if ((attributes & READ_ONLY) == 0) { | 1607 if ((attributes & READ_ONLY) == 0) { |
| 1604 Isolate* isolate = store->GetIsolate(); | 1608 Isolate* isolate = store->GetIsolate(); |
| 1605 value = isolate->factory()->NewAliasedArgumentsEntry(context_index); | 1609 value = isolate->factory()->NewAliasedArgumentsEntry(context_entry); |
| 1606 } | 1610 } |
| 1607 | 1611 |
| 1608 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); | 1612 PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell); |
| 1609 Handle<SeededNumberDictionary> arguments( | 1613 Handle<SeededNumberDictionary> arguments( |
| 1610 SeededNumberDictionary::cast(parameter_map->get(1))); | 1614 SeededNumberDictionary::cast(parameter_map->get(1))); |
| 1611 arguments = SeededNumberDictionary::AddNumberEntry(arguments, index, | 1615 arguments = SeededNumberDictionary::AddNumberEntry(arguments, entry, |
| 1612 value, details); | 1616 value, details); |
| 1613 parameter_map->set(1, *arguments); | 1617 parameter_map->set(1, *arguments); |
| 1614 } else { | 1618 } else { |
| 1615 Handle<FixedArrayBase> arguments( | 1619 Handle<FixedArrayBase> arguments( |
| 1616 FixedArrayBase::cast(parameter_map->get(1))); | 1620 FixedArrayBase::cast(parameter_map->get(1))); |
| 1617 DictionaryElementsAccessor::ReconfigureImpl( | 1621 DictionaryElementsAccessor::ReconfigureImpl( |
| 1618 object, arguments, index - length, value, attributes); | 1622 object, arguments, entry - length, value, attributes); |
| 1619 } | 1623 } |
| 1620 } | 1624 } |
| 1621 }; | 1625 }; |
| 1622 | 1626 |
| 1623 | 1627 |
| 1624 class FastSloppyArgumentsElementsAccessor | 1628 class FastSloppyArgumentsElementsAccessor |
| 1625 : public SloppyArgumentsElementsAccessor< | 1629 : public SloppyArgumentsElementsAccessor< |
| 1626 FastSloppyArgumentsElementsAccessor, FastHoleyObjectElementsAccessor, | 1630 FastSloppyArgumentsElementsAccessor, FastHoleyObjectElementsAccessor, |
| 1627 ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> > { | 1631 ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> > { |
| 1628 public: | 1632 public: |
| 1629 explicit FastSloppyArgumentsElementsAccessor(const char* name) | 1633 explicit FastSloppyArgumentsElementsAccessor(const char* name) |
| 1630 : SloppyArgumentsElementsAccessor< | 1634 : SloppyArgumentsElementsAccessor< |
| 1631 FastSloppyArgumentsElementsAccessor, | 1635 FastSloppyArgumentsElementsAccessor, |
| 1632 FastHoleyObjectElementsAccessor, | 1636 FastHoleyObjectElementsAccessor, |
| 1633 ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >(name) {} | 1637 ElementsKindTraits<FAST_SLOPPY_ARGUMENTS_ELEMENTS> >(name) {} |
| 1634 | 1638 |
| 1635 static void DeleteFromArguments(Handle<JSObject> obj, uint32_t index) { | 1639 static void DeleteFromArguments(Handle<JSObject> obj, uint32_t entry) { |
| 1636 FixedArray* parameter_map = FixedArray::cast(obj->elements()); | 1640 FixedArray* parameter_map = FixedArray::cast(obj->elements()); |
| 1637 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1))); | 1641 Handle<FixedArray> arguments(FixedArray::cast(parameter_map->get(1))); |
| 1638 FastHoleyObjectElementsAccessor::DeleteCommon(obj, index, arguments); | 1642 FastHoleyObjectElementsAccessor::DeleteCommon(obj, entry, arguments); |
| 1639 } | 1643 } |
| 1640 | 1644 |
| 1641 static void AddImpl(Handle<JSObject> object, uint32_t key, | 1645 static void AddImpl(Handle<JSObject> object, uint32_t index, |
| 1642 Handle<Object> value, PropertyAttributes attributes, | 1646 Handle<Object> value, PropertyAttributes attributes, |
| 1643 uint32_t new_capacity) { | 1647 uint32_t new_capacity) { |
| 1644 DCHECK_EQ(NONE, attributes); | 1648 DCHECK_EQ(NONE, attributes); |
| 1645 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements())); | 1649 Handle<FixedArray> parameter_map(FixedArray::cast(object->elements())); |
| 1646 Handle<FixedArrayBase> old_elements( | 1650 Handle<FixedArrayBase> old_elements( |
| 1647 FixedArrayBase::cast(parameter_map->get(1))); | 1651 FixedArrayBase::cast(parameter_map->get(1))); |
| 1648 if (old_elements->IsSeededNumberDictionary() || | 1652 if (old_elements->IsSeededNumberDictionary() || |
| 1649 static_cast<uint32_t>(old_elements->length()) < new_capacity) { | 1653 static_cast<uint32_t>(old_elements->length()) < new_capacity) { |
| 1650 GrowCapacityAndConvertImpl(object, new_capacity); | 1654 GrowCapacityAndConvertImpl(object, new_capacity); |
| 1651 } | 1655 } |
| 1652 SetImpl(object->elements(), key, *value); | 1656 SetImpl(object->elements(), index, *value); |
| 1653 } | 1657 } |
| 1654 | 1658 |
| 1655 static void ReconfigureImpl(Handle<JSObject> object, | 1659 static void ReconfigureImpl(Handle<JSObject> object, |
| 1656 Handle<FixedArrayBase> store, uint32_t index, | 1660 Handle<FixedArrayBase> store, uint32_t entry, |
| 1657 Handle<Object> value, | 1661 Handle<Object> value, |
| 1658 PropertyAttributes attributes) { | 1662 PropertyAttributes attributes) { |
| 1659 Handle<SeededNumberDictionary> dictionary = | 1663 Handle<SeededNumberDictionary> dictionary = |
| 1660 JSObject::NormalizeElements(object); | 1664 JSObject::NormalizeElements(object); |
| 1661 FixedArray::cast(*store)->set(1, *dictionary); | 1665 FixedArray::cast(*store)->set(1, *dictionary); |
| 1662 uint32_t length = static_cast<uint32_t>(store->length()) - 2; | 1666 uint32_t length = static_cast<uint32_t>(store->length()) - 2; |
| 1663 if (index >= length) { | 1667 if (entry >= length) { |
| 1664 index = dictionary->FindEntry(index - length) + length; | 1668 entry = dictionary->FindEntry(entry - length) + length; |
| 1665 } | 1669 } |
| 1666 SlowSloppyArgumentsElementsAccessor::ReconfigureImpl(object, store, index, | 1670 SlowSloppyArgumentsElementsAccessor::ReconfigureImpl(object, store, entry, |
| 1667 value, attributes); | 1671 value, attributes); |
| 1668 } | 1672 } |
| 1669 | 1673 |
| 1670 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, | 1674 static void CopyElementsImpl(FixedArrayBase* from, uint32_t from_start, |
| 1671 FixedArrayBase* to, ElementsKind from_kind, | 1675 FixedArrayBase* to, ElementsKind from_kind, |
| 1672 uint32_t to_start, int packed_size, | 1676 uint32_t to_start, int packed_size, |
| 1673 int copy_size) { | 1677 int copy_size) { |
| 1674 DCHECK(!to->IsDictionary()); | 1678 DCHECK(!to->IsDictionary()); |
| 1675 if (from_kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS) { | 1679 if (from_kind == SLOW_SLOPPY_ARGUMENTS_ELEMENTS) { |
| 1676 CopyDictionaryToObjectElements(from, from_start, to, FAST_HOLEY_ELEMENTS, | 1680 CopyDictionaryToObjectElements(from, from_start, to, FAST_HOLEY_ELEMENTS, |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1742 capacity = Max(length, JSObject::NewElementsCapacity(capacity)); | 1746 capacity = Max(length, JSObject::NewElementsCapacity(capacity)); |
| 1743 ElementsAccessorSubclass::GrowCapacityAndConvertImpl(array, capacity); | 1747 ElementsAccessorSubclass::GrowCapacityAndConvertImpl(array, capacity); |
| 1744 } | 1748 } |
| 1745 | 1749 |
| 1746 array->set_length(Smi::FromInt(length)); | 1750 array->set_length(Smi::FromInt(length)); |
| 1747 JSObject::ValidateElements(array); | 1751 JSObject::ValidateElements(array); |
| 1748 } | 1752 } |
| 1749 } // namespace | 1753 } // namespace |
| 1750 | 1754 |
| 1751 | 1755 |
| 1752 void CheckArrayAbuse(Handle<JSObject> obj, const char* op, uint32_t key, | 1756 void CheckArrayAbuse(Handle<JSObject> obj, const char* op, uint32_t index, |
| 1753 bool allow_appending) { | 1757 bool allow_appending) { |
| 1754 DisallowHeapAllocation no_allocation; | 1758 DisallowHeapAllocation no_allocation; |
| 1755 Object* raw_length = NULL; | 1759 Object* raw_length = NULL; |
| 1756 const char* elements_type = "array"; | 1760 const char* elements_type = "array"; |
| 1757 if (obj->IsJSArray()) { | 1761 if (obj->IsJSArray()) { |
| 1758 JSArray* array = JSArray::cast(*obj); | 1762 JSArray* array = JSArray::cast(*obj); |
| 1759 raw_length = array->length(); | 1763 raw_length = array->length(); |
| 1760 } else { | 1764 } else { |
| 1761 raw_length = Smi::FromInt(obj->elements()->length()); | 1765 raw_length = Smi::FromInt(obj->elements()->length()); |
| 1762 elements_type = "object"; | 1766 elements_type = "object"; |
| 1763 } | 1767 } |
| 1764 | 1768 |
| 1765 if (raw_length->IsNumber()) { | 1769 if (raw_length->IsNumber()) { |
| 1766 double n = raw_length->Number(); | 1770 double n = raw_length->Number(); |
| 1767 if (FastI2D(FastD2UI(n)) == n) { | 1771 if (FastI2D(FastD2UI(n)) == n) { |
| 1768 int32_t int32_length = DoubleToInt32(n); | 1772 int32_t int32_length = DoubleToInt32(n); |
| 1769 uint32_t compare_length = static_cast<uint32_t>(int32_length); | 1773 uint32_t compare_length = static_cast<uint32_t>(int32_length); |
| 1770 if (allow_appending) compare_length++; | 1774 if (allow_appending) compare_length++; |
| 1771 if (key >= compare_length) { | 1775 if (index >= compare_length) { |
| 1772 PrintF("[OOB %s %s (%s length = %d, element accessed = %d) in ", | 1776 PrintF("[OOB %s %s (%s length = %d, element accessed = %d) in ", |
| 1773 elements_type, op, elements_type, static_cast<int>(int32_length), | 1777 elements_type, op, elements_type, static_cast<int>(int32_length), |
| 1774 static_cast<int>(key)); | 1778 static_cast<int>(index)); |
| 1775 TraceTopFrame(obj->GetIsolate()); | 1779 TraceTopFrame(obj->GetIsolate()); |
| 1776 PrintF("]\n"); | 1780 PrintF("]\n"); |
| 1777 } | 1781 } |
| 1778 } else { | 1782 } else { |
| 1779 PrintF("[%s elements length not integer value in ", elements_type); | 1783 PrintF("[%s elements length not integer value in ", elements_type); |
| 1780 TraceTopFrame(obj->GetIsolate()); | 1784 TraceTopFrame(obj->GetIsolate()); |
| 1781 PrintF("]\n"); | 1785 PrintF("]\n"); |
| 1782 } | 1786 } |
| 1783 } else { | 1787 } else { |
| 1784 PrintF("[%s elements length not a number in ", elements_type); | 1788 PrintF("[%s elements length not a number in ", elements_type); |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1837 } else { | 1841 } else { |
| 1838 elms = Handle<FixedArrayBase>::cast( | 1842 elms = Handle<FixedArrayBase>::cast( |
| 1839 factory->NewFixedArrayWithHoles(number_of_elements)); | 1843 factory->NewFixedArrayWithHoles(number_of_elements)); |
| 1840 } | 1844 } |
| 1841 | 1845 |
| 1842 // Fill in the content | 1846 // Fill in the content |
| 1843 switch (array->GetElementsKind()) { | 1847 switch (array->GetElementsKind()) { |
| 1844 case FAST_HOLEY_SMI_ELEMENTS: | 1848 case FAST_HOLEY_SMI_ELEMENTS: |
| 1845 case FAST_SMI_ELEMENTS: { | 1849 case FAST_SMI_ELEMENTS: { |
| 1846 Handle<FixedArray> smi_elms = Handle<FixedArray>::cast(elms); | 1850 Handle<FixedArray> smi_elms = Handle<FixedArray>::cast(elms); |
| 1847 for (int index = 0; index < number_of_elements; index++) { | 1851 for (int entry = 0; entry < number_of_elements; entry++) { |
| 1848 smi_elms->set(index, (*args)[index], SKIP_WRITE_BARRIER); | 1852 smi_elms->set(entry, (*args)[entry], SKIP_WRITE_BARRIER); |
| 1849 } | 1853 } |
| 1850 break; | 1854 break; |
| 1851 } | 1855 } |
| 1852 case FAST_HOLEY_ELEMENTS: | 1856 case FAST_HOLEY_ELEMENTS: |
| 1853 case FAST_ELEMENTS: { | 1857 case FAST_ELEMENTS: { |
| 1854 DisallowHeapAllocation no_gc; | 1858 DisallowHeapAllocation no_gc; |
| 1855 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); | 1859 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc); |
| 1856 Handle<FixedArray> object_elms = Handle<FixedArray>::cast(elms); | 1860 Handle<FixedArray> object_elms = Handle<FixedArray>::cast(elms); |
| 1857 for (int index = 0; index < number_of_elements; index++) { | 1861 for (int entry = 0; entry < number_of_elements; entry++) { |
| 1858 object_elms->set(index, (*args)[index], mode); | 1862 object_elms->set(entry, (*args)[entry], mode); |
| 1859 } | 1863 } |
| 1860 break; | 1864 break; |
| 1861 } | 1865 } |
| 1862 case FAST_HOLEY_DOUBLE_ELEMENTS: | 1866 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 1863 case FAST_DOUBLE_ELEMENTS: { | 1867 case FAST_DOUBLE_ELEMENTS: { |
| 1864 Handle<FixedDoubleArray> double_elms = | 1868 Handle<FixedDoubleArray> double_elms = |
| 1865 Handle<FixedDoubleArray>::cast(elms); | 1869 Handle<FixedDoubleArray>::cast(elms); |
| 1866 for (int index = 0; index < number_of_elements; index++) { | 1870 for (int entry = 0; entry < number_of_elements; entry++) { |
| 1867 double_elms->set(index, (*args)[index]->Number()); | 1871 double_elms->set(entry, (*args)[entry]->Number()); |
| 1868 } | 1872 } |
| 1869 break; | 1873 break; |
| 1870 } | 1874 } |
| 1871 default: | 1875 default: |
| 1872 UNREACHABLE(); | 1876 UNREACHABLE(); |
| 1873 break; | 1877 break; |
| 1874 } | 1878 } |
| 1875 | 1879 |
| 1876 array->set_elements(*elms); | 1880 array->set_elements(*elms); |
| 1877 array->set_length(Smi::FromInt(number_of_elements)); | 1881 array->set_length(Smi::FromInt(number_of_elements)); |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 1898 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind]; | 1902 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind]; |
| 1899 ELEMENTS_LIST(ACCESSOR_DELETE) | 1903 ELEMENTS_LIST(ACCESSOR_DELETE) |
| 1900 #undef ACCESSOR_DELETE | 1904 #undef ACCESSOR_DELETE |
| 1901 elements_accessors_ = NULL; | 1905 elements_accessors_ = NULL; |
| 1902 } | 1906 } |
| 1903 | 1907 |
| 1904 | 1908 |
| 1905 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; | 1909 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; |
| 1906 } // namespace internal | 1910 } // namespace internal |
| 1907 } // namespace v8 | 1911 } // namespace v8 |
| OLD | NEW |