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/elements.h" | 5 #include "src/elements.h" | 
| 6 | 6 | 
| 7 #include "src/arguments.h" | 7 #include "src/arguments.h" | 
| 8 #include "src/conversions.h" | 8 #include "src/conversions.h" | 
| 9 #include "src/factory.h" | 9 #include "src/factory.h" | 
| 10 #include "src/isolate-inl.h" | 10 #include "src/isolate-inl.h" | 
| (...skipping 1554 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1565 if (IsFastPackedElementsKind(KindTraits::Kind) || | 1565 if (IsFastPackedElementsKind(KindTraits::Kind) || | 
| 1566 HasEntryImpl(*elements, i)) { | 1566 HasEntryImpl(*elements, i)) { | 
| 1567 accumulator->AddKey(Subclass::GetImpl(*elements, i), convert); | 1567 accumulator->AddKey(Subclass::GetImpl(*elements, i), convert); | 
| 1568 } | 1568 } | 
| 1569 } | 1569 } | 
| 1570 } | 1570 } | 
| 1571 | 1571 | 
| 1572 static void ValidateContents(Handle<JSObject> holder, int length) { | 1572 static void ValidateContents(Handle<JSObject> holder, int length) { | 
| 1573 #if DEBUG | 1573 #if DEBUG | 
| 1574 Isolate* isolate = holder->GetIsolate(); | 1574 Isolate* isolate = holder->GetIsolate(); | 
| 1575 Heap* heap = isolate->heap(); | |
| 1575 HandleScope scope(isolate); | 1576 HandleScope scope(isolate); | 
| 1576 Handle<FixedArrayBase> elements(holder->elements(), isolate); | 1577 Handle<FixedArrayBase> elements(holder->elements(), isolate); | 
| 1577 Map* map = elements->map(); | 1578 Map* map = elements->map(); | 
| 1578 DCHECK((IsFastSmiOrObjectElementsKind(KindTraits::Kind) && | 1579 if (IsFastSmiOrObjectElementsKind(KindTraits::Kind)) { | 
| 1579 (map == isolate->heap()->fixed_array_map() || | 1580 DCHECK(map != heap->fixed_double_array_map()); | 
| 1580 map == isolate->heap()->fixed_cow_array_map())) || | 1581 } else if (IsFastDoubleElementsKind(KindTraits::Kind)) { | 
| 1581 (IsFastDoubleElementsKind(KindTraits::Kind) == | 1582 DCHECK(map != heap->fixed_cow_array_map()); | 
| 
 
Toon Verwaest
2016/04/07 13:01:39
DCHECK_NE Would already be included in the suggest
 
 | |
| 1582 ((map == isolate->heap()->fixed_array_map() && length == 0) || | 1583 if (map == heap->fixed_array_map()) DCHECK_EQ(0, length); | 
| 
 
Toon Verwaest
2016/04/07 13:01:39
DCHECK(map == fixed_double_array_map() ||
       (
 
Camillo Bruni
2016/04/07 13:12:38
I prefer the separate checks, makes it easier for
 
 | |
| 1583 map == isolate->heap()->fixed_double_array_map()))); | 1584 } else { | 
| 1585 UNREACHABLE(); | |
| 1586 } | |
| 1584 if (length == 0) return; // nothing to do! | 1587 if (length == 0) return; // nothing to do! | 
| 1585 DisallowHeapAllocation no_gc; | 1588 DisallowHeapAllocation no_gc; | 
| 1586 Handle<BackingStore> backing_store = Handle<BackingStore>::cast(elements); | 1589 Handle<BackingStore> backing_store = Handle<BackingStore>::cast(elements); | 
| 1587 if (IsFastSmiElementsKind(KindTraits::Kind)) { | 1590 if (IsFastSmiElementsKind(KindTraits::Kind)) { | 
| 1588 for (int i = 0; i < length; i++) { | 1591 for (int i = 0; i < length; i++) { | 
| 1589 DCHECK(BackingStore::get(*backing_store, i, isolate)->IsSmi() || | 1592 DCHECK(BackingStore::get(*backing_store, i, isolate)->IsSmi() || | 
| 1590 (IsFastHoleyElementsKind(KindTraits::Kind) && | 1593 (IsFastHoleyElementsKind(KindTraits::Kind) && | 
| 1591 backing_store->is_the_hole(i))); | 1594 backing_store->is_the_hole(i))); | 
| 1592 } | 1595 } | 
| 1596 } else if (KindTraits::Kind == FAST_ELEMENTS || | |
| 1597 KindTraits::Kind == FAST_DOUBLE_ELEMENTS) { | |
| 1598 for (int i = 0; i < length; i++) { | |
| 
 
Toon Verwaest
2016/04/07 13:01:39
This probably should be SLOW_ASSERTS
 
Camillo Bruni
2016/04/07 13:12:38
yup
 
 | |
| 1599 DCHECK(!backing_store->is_the_hole(i)); | |
| 1600 } | |
| 1601 } else { | |
| 1602 DCHECK(IsFastHoleyElementsKind(KindTraits::Kind)); | |
| 1593 } | 1603 } | 
| 1594 #endif | 1604 #endif | 
| 1595 } | 1605 } | 
| 1596 | 1606 | 
| 1597 static Handle<Object> PopImpl(Handle<JSArray> receiver) { | 1607 static Handle<Object> PopImpl(Handle<JSArray> receiver) { | 
| 1598 return Subclass::RemoveElement(receiver, AT_END); | 1608 return Subclass::RemoveElement(receiver, AT_END); | 
| 1599 } | 1609 } | 
| 1600 | 1610 | 
| 1601 static Handle<Object> ShiftImpl(Handle<JSArray> receiver) { | 1611 static Handle<Object> ShiftImpl(Handle<JSArray> receiver) { | 
| 1602 return Subclass::RemoveElement(receiver, AT_START); | 1612 return Subclass::RemoveElement(receiver, AT_START); | 
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1798 | 1808 | 
| 1799 if (IsHoleyElementsKind(kind) && result->IsTheHole()) { | 1809 if (IsHoleyElementsKind(kind) && result->IsTheHole()) { | 
| 1800 return isolate->factory()->undefined_value(); | 1810 return isolate->factory()->undefined_value(); | 
| 1801 } | 1811 } | 
| 1802 return result; | 1812 return result; | 
| 1803 } | 1813 } | 
| 1804 | 1814 | 
| 1805 static uint32_t AddArguments(Handle<JSArray> receiver, | 1815 static uint32_t AddArguments(Handle<JSArray> receiver, | 
| 1806 Handle<FixedArrayBase> backing_store, | 1816 Handle<FixedArrayBase> backing_store, | 
| 1807 Arguments* args, uint32_t add_size, | 1817 Arguments* args, uint32_t add_size, | 
| 1808 Where remove_position) { | 1818 Where add_position) { | 
| 1809 uint32_t length = Smi::cast(receiver->length())->value(); | 1819 uint32_t length = Smi::cast(receiver->length())->value(); | 
| 1810 DCHECK(0 < add_size); | 1820 DCHECK(0 < add_size); | 
| 1811 uint32_t elms_len = backing_store->length(); | 1821 uint32_t elms_len = backing_store->length(); | 
| 1812 // Check we do not overflow the new_length. | 1822 // Check we do not overflow the new_length. | 
| 1813 DCHECK(add_size <= static_cast<uint32_t>(Smi::kMaxValue - length)); | 1823 DCHECK(add_size <= static_cast<uint32_t>(Smi::kMaxValue - length)); | 
| 1814 uint32_t new_length = length + add_size; | 1824 uint32_t new_length = length + add_size; | 
| 1815 | 1825 | 
| 1816 if (new_length > elms_len) { | 1826 if (new_length > elms_len) { | 
| 1817 // New backing storage is needed. | 1827 // New backing storage is needed. | 
| 1818 uint32_t capacity = JSObject::NewElementsCapacity(new_length); | 1828 uint32_t capacity = JSObject::NewElementsCapacity(new_length); | 
| 1819 // If we add arguments to the start we have to shift the existing objects. | 1829 // If we add arguments to the start we have to shift the existing objects. | 
| 1820 int copy_dst_index = remove_position == AT_START ? add_size : 0; | 1830 int copy_dst_index = add_position == AT_START ? add_size : 0; | 
| 1821 // Copy over all objects to a new backing_store. | 1831 // Copy over all objects to a new backing_store. | 
| 1822 backing_store = Subclass::ConvertElementsWithCapacity( | 1832 backing_store = Subclass::ConvertElementsWithCapacity( | 
| 1823 receiver, backing_store, KindTraits::Kind, capacity, 0, | 1833 receiver, backing_store, KindTraits::Kind, capacity, 0, | 
| 1824 copy_dst_index, ElementsAccessor::kCopyToEndAndInitializeToHole); | 1834 copy_dst_index, ElementsAccessor::kCopyToEndAndInitializeToHole); | 
| 1825 receiver->set_elements(*backing_store); | 1835 receiver->set_elements(*backing_store); | 
| 1826 } else if (remove_position == AT_START) { | 1836 } else if (add_position == AT_START) { | 
| 1827 // If the backing store has enough capacity and we add elements to the | 1837 // If the backing store has enough capacity and we add elements to the | 
| 1828 // start we have to shift the existing objects. | 1838 // start we have to shift the existing objects. | 
| 1829 Isolate* isolate = receiver->GetIsolate(); | 1839 Isolate* isolate = receiver->GetIsolate(); | 
| 1830 Subclass::MoveElements(isolate, receiver, backing_store, add_size, 0, | 1840 Subclass::MoveElements(isolate, receiver, backing_store, add_size, 0, | 
| 1831 length, 0, 0); | 1841 length, 0, 0); | 
| 1832 } | 1842 } | 
| 1833 | 1843 | 
| 1834 int insertion_index = remove_position == AT_START ? 0 : length; | 1844 int insertion_index = add_position == AT_START ? 0 : length; | 
| 1835 // Copy the arguments to the start. | 1845 // Copy the arguments to the start. | 
| 1836 Subclass::CopyArguments(args, backing_store, add_size, 1, insertion_index); | 1846 Subclass::CopyArguments(args, backing_store, add_size, 1, insertion_index); | 
| 1837 // Set the length. | 1847 // Set the length. | 
| 1838 receiver->set_length(Smi::FromInt(new_length)); | 1848 receiver->set_length(Smi::FromInt(new_length)); | 
| 1839 return new_length; | 1849 return new_length; | 
| 1840 } | 1850 } | 
| 1841 | 1851 | 
| 1842 static void CopyArguments(Arguments* args, Handle<FixedArrayBase> dst_store, | 1852 static void CopyArguments(Arguments* args, Handle<FixedArrayBase> dst_store, | 
| 1843 uint32_t copy_size, uint32_t src_index, | 1853 uint32_t copy_size, uint32_t src_index, | 
| 1844 uint32_t dst_index) { | 1854 uint32_t dst_index) { | 
| 1845 // Add the provided values. | 1855 // Add the provided values. | 
| 1846 DisallowHeapAllocation no_gc; | 1856 DisallowHeapAllocation no_gc; | 
| 1847 FixedArrayBase* raw_backing_store = *dst_store; | 1857 FixedArrayBase* raw_backing_store = *dst_store; | 
| 1848 WriteBarrierMode mode = raw_backing_store->GetWriteBarrierMode(no_gc); | 1858 WriteBarrierMode mode = raw_backing_store->GetWriteBarrierMode(no_gc); | 
| 1849 for (uint32_t i = 0; i < copy_size; i++) { | 1859 for (uint32_t i = 0; i < copy_size; i++) { | 
| 1850 Object* argument = (*args)[i + src_index]; | 1860 Object* argument = (*args)[src_index + i]; | 
| 1851 Subclass::SetImpl(raw_backing_store, i + dst_index, argument, mode); | 1861 DCHECK(!argument->IsTheHole()); | 
| 1862 Subclass::SetImpl(raw_backing_store, dst_index + i, argument, mode); | |
| 1852 } | 1863 } | 
| 1853 } | 1864 } | 
| 1854 }; | 1865 }; | 
| 1855 | 1866 | 
| 1856 template <typename Subclass, typename KindTraits> | 1867 template <typename Subclass, typename KindTraits> | 
| 1857 class FastSmiOrObjectElementsAccessor | 1868 class FastSmiOrObjectElementsAccessor | 
| 1858 : public FastElementsAccessor<Subclass, KindTraits> { | 1869 : public FastElementsAccessor<Subclass, KindTraits> { | 
| 1859 public: | 1870 public: | 
| 1860 explicit FastSmiOrObjectElementsAccessor(const char* name) | 1871 explicit FastSmiOrObjectElementsAccessor(const char* name) | 
| 1861 : FastElementsAccessor<Subclass, KindTraits>(name) {} | 1872 : FastElementsAccessor<Subclass, KindTraits>(name) {} | 
| (...skipping 1047 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2909 Handle<FixedArrayBase> elms; | 2920 Handle<FixedArrayBase> elms; | 
| 2910 if (IsFastDoubleElementsKind(elements_kind)) { | 2921 if (IsFastDoubleElementsKind(elements_kind)) { | 
| 2911 elms = Handle<FixedArrayBase>::cast( | 2922 elms = Handle<FixedArrayBase>::cast( | 
| 2912 factory->NewFixedDoubleArray(number_of_elements)); | 2923 factory->NewFixedDoubleArray(number_of_elements)); | 
| 2913 } else { | 2924 } else { | 
| 2914 elms = Handle<FixedArrayBase>::cast( | 2925 elms = Handle<FixedArrayBase>::cast( | 
| 2915 factory->NewFixedArrayWithHoles(number_of_elements)); | 2926 factory->NewFixedArrayWithHoles(number_of_elements)); | 
| 2916 } | 2927 } | 
| 2917 | 2928 | 
| 2918 // Fill in the content | 2929 // Fill in the content | 
| 2919 switch (array->GetElementsKind()) { | 2930 switch (elements_kind) { | 
| 2920 case FAST_HOLEY_SMI_ELEMENTS: | 2931 case FAST_HOLEY_SMI_ELEMENTS: | 
| 2921 case FAST_SMI_ELEMENTS: { | 2932 case FAST_SMI_ELEMENTS: { | 
| 2922 Handle<FixedArray> smi_elms = Handle<FixedArray>::cast(elms); | 2933 Handle<FixedArray> smi_elms = Handle<FixedArray>::cast(elms); | 
| 2923 for (int entry = 0; entry < number_of_elements; entry++) { | 2934 for (int entry = 0; entry < number_of_elements; entry++) { | 
| 2924 smi_elms->set(entry, (*args)[entry], SKIP_WRITE_BARRIER); | 2935 smi_elms->set(entry, (*args)[entry], SKIP_WRITE_BARRIER); | 
| 2925 } | 2936 } | 
| 2926 break; | 2937 break; | 
| 2927 } | 2938 } | 
| 2928 case FAST_HOLEY_ELEMENTS: | 2939 case FAST_HOLEY_ELEMENTS: | 
| 2929 case FAST_ELEMENTS: { | 2940 case FAST_ELEMENTS: { | 
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3039 insertion_index += len; | 3050 insertion_index += len; | 
| 3040 } | 3051 } | 
| 3041 | 3052 | 
| 3042 DCHECK_EQ(insertion_index, result_len); | 3053 DCHECK_EQ(insertion_index, result_len); | 
| 3043 return result_array; | 3054 return result_array; | 
| 3044 } | 3055 } | 
| 3045 | 3056 | 
| 3046 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; | 3057 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; | 
| 3047 } // namespace internal | 3058 } // namespace internal | 
| 3048 } // namespace v8 | 3059 } // namespace v8 | 
| OLD | NEW |