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 1690 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1701 void ElementsAccessor::TearDown() { | 1701 void ElementsAccessor::TearDown() { |
1702 if (elements_accessors_ == NULL) return; | 1702 if (elements_accessors_ == NULL) return; |
1703 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind]; | 1703 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind]; |
1704 ELEMENTS_LIST(ACCESSOR_DELETE) | 1704 ELEMENTS_LIST(ACCESSOR_DELETE) |
1705 #undef ACCESSOR_DELETE | 1705 #undef ACCESSOR_DELETE |
1706 elements_accessors_ = NULL; | 1706 elements_accessors_ = NULL; |
1707 } | 1707 } |
1708 | 1708 |
1709 | 1709 |
1710 template <typename ElementsAccessorSubclass, typename ElementsKindTraits> | 1710 template <typename ElementsAccessorSubclass, typename ElementsKindTraits> |
1711 MUST_USE_RESULT | 1711 MUST_USE_RESULT MaybeHandle<Object> ElementsAccessorBase< |
1712 MaybeHandle<Object> ElementsAccessorBase<ElementsAccessorSubclass, | 1712 ElementsAccessorSubclass, |
1713 ElementsKindTraits>:: | 1713 ElementsKindTraits>::SetLengthImpl(Handle<JSObject> obj, |
1714 SetLengthImpl(Handle<JSObject> obj, | 1714 Handle<Object> length_obj, |
1715 Handle<Object> length, | 1715 Handle<FixedArrayBase> backing_store) { |
1716 Handle<FixedArrayBase> backing_store) { | |
1717 Isolate* isolate = obj->GetIsolate(); | |
1718 Handle<JSArray> array = Handle<JSArray>::cast(obj); | 1716 Handle<JSArray> array = Handle<JSArray>::cast(obj); |
1719 | 1717 |
1720 // Fast case: The new length fits into a Smi. | 1718 uint32_t length = 0; |
1721 Handle<Object> smi_length; | 1719 CHECK(length_obj->ToArrayLength(&length)); |
| 1720 // Fast case: length fits in a smi. |
| 1721 if (length <= Smi::kMaxValue) { |
| 1722 Handle<Smi> smi(Smi::FromInt(length), obj->GetIsolate()); |
| 1723 Handle<Object> new_length = |
| 1724 ElementsAccessorSubclass::SetLengthWithoutNormalize(backing_store, |
| 1725 array, smi, length); |
| 1726 DCHECK(!new_length.is_null()); |
1722 | 1727 |
1723 if (Object::ToSmi(isolate, length).ToHandle(&smi_length) && | 1728 // Even though the proposed length was a smi, new_length could |
1724 smi_length->IsSmi()) { | 1729 // still be a heap number because SetLengthWithoutNormalize doesn't |
1725 const int value = Handle<Smi>::cast(smi_length)->value(); | 1730 // allow the array length property to drop below the index of |
1726 if (value >= 0) { | 1731 // non-deletable elements. |
1727 Handle<Object> new_length = ElementsAccessorSubclass:: | 1732 DCHECK(new_length->IsSmi() || new_length->IsHeapNumber() || |
1728 SetLengthWithoutNormalize(backing_store, array, smi_length, value); | 1733 new_length->IsUndefined()); |
1729 DCHECK(!new_length.is_null()); | 1734 if (new_length->IsSmi()) { |
1730 | 1735 array->set_length(*Handle<Smi>::cast(new_length)); |
1731 // even though the proposed length was a smi, new_length could | 1736 return array; |
1732 // still be a heap number because SetLengthWithoutNormalize doesn't | 1737 } else if (new_length->IsHeapNumber()) { |
1733 // allow the array length property to drop below the index of | 1738 array->set_length(*new_length); |
1734 // non-deletable elements. | 1739 return array; |
1735 DCHECK(new_length->IsSmi() || new_length->IsHeapNumber() || | |
1736 new_length->IsUndefined()); | |
1737 if (new_length->IsSmi()) { | |
1738 array->set_length(*Handle<Smi>::cast(new_length)); | |
1739 return array; | |
1740 } else if (new_length->IsHeapNumber()) { | |
1741 array->set_length(*new_length); | |
1742 return array; | |
1743 } | |
1744 } else { | |
1745 return ThrowArrayLengthRangeError(isolate); | |
1746 } | 1740 } |
1747 } | 1741 } |
1748 | 1742 |
1749 // Slow case: The new length does not fit into a Smi or conversion | 1743 // Slow case: The new length does not fit into a Smi or conversion |
1750 // to slow elements is needed for other reasons. | 1744 // to slow elements is needed for other reasons. |
1751 if (length->IsNumber()) { | 1745 Handle<SeededNumberDictionary> dictionary = |
1752 uint32_t value; | 1746 JSObject::NormalizeElements(array); |
1753 if (length->ToArrayLength(&value)) { | 1747 DCHECK(!dictionary.is_null()); |
1754 Handle<SeededNumberDictionary> dictionary = | |
1755 JSObject::NormalizeElements(array); | |
1756 DCHECK(!dictionary.is_null()); | |
1757 | 1748 |
1758 Handle<Object> new_length = DictionaryElementsAccessor:: | 1749 Handle<Object> new_length = |
1759 SetLengthWithoutNormalize(dictionary, array, length, value); | 1750 DictionaryElementsAccessor::SetLengthWithoutNormalize(dictionary, array, |
1760 DCHECK(!new_length.is_null()); | 1751 length_obj, length); |
| 1752 DCHECK(!new_length.is_null()); |
1761 | 1753 |
1762 DCHECK(new_length->IsNumber()); | 1754 DCHECK(new_length->IsNumber()); |
1763 array->set_length(*new_length); | 1755 array->set_length(*new_length); |
1764 return array; | |
1765 } else { | |
1766 return ThrowArrayLengthRangeError(isolate); | |
1767 } | |
1768 } | |
1769 | |
1770 // Fall-back case: The new length is not a number so make the array | |
1771 // size one and set only element to length. | |
1772 Handle<FixedArray> new_backing_store = isolate->factory()->NewFixedArray(1); | |
1773 new_backing_store->set(0, *length); | |
1774 JSArray::SetContent(array, new_backing_store); | |
1775 return array; | 1756 return array; |
1776 } | 1757 } |
1777 | 1758 |
1778 | 1759 |
1779 MaybeHandle<Object> ArrayConstructInitializeElements(Handle<JSArray> array, | 1760 MaybeHandle<Object> ArrayConstructInitializeElements(Handle<JSArray> array, |
1780 Arguments* args) { | 1761 Arguments* args) { |
1781 // Optimize the case where there is one argument and the argument is a | 1762 if (args->length() == 0) { |
1782 // small smi. | 1763 // Optimize the case where there are no parameters passed. |
1783 if (args->length() == 1) { | 1764 JSArray::Initialize(array, JSArray::kPreallocatedArrayElements); |
1784 Handle<Object> obj = args->at<Object>(0); | 1765 return array; |
1785 if (obj->IsSmi()) { | |
1786 int len = Handle<Smi>::cast(obj)->value(); | |
1787 if (len > 0 && len < JSObject::kInitialMaxFastElementArray) { | |
1788 ElementsKind elements_kind = array->GetElementsKind(); | |
1789 JSArray::Initialize(array, len, len); | |
1790 | 1766 |
1791 if (!IsFastHoleyElementsKind(elements_kind)) { | 1767 } else if (args->length() == 1 && args->at<Object>(0)->IsNumber()) { |
1792 elements_kind = GetHoleyElementsKind(elements_kind); | 1768 uint32_t length; |
1793 JSObject::TransitionElementsKind(array, elements_kind); | 1769 if (!args->at<Object>(0)->ToArrayLength(&length)) { |
1794 } | 1770 return ThrowArrayLengthRangeError(array->GetIsolate()); |
1795 return array; | 1771 } |
1796 } else if (len == 0) { | 1772 |
1797 JSArray::Initialize(array, JSArray::kPreallocatedArrayElements); | 1773 // Optimize the case where there is one argument and the argument is a small |
1798 return array; | 1774 // smi. |
| 1775 if (length > 0 && length < JSObject::kInitialMaxFastElementArray) { |
| 1776 ElementsKind elements_kind = array->GetElementsKind(); |
| 1777 JSArray::Initialize(array, length, length); |
| 1778 |
| 1779 if (!IsFastHoleyElementsKind(elements_kind)) { |
| 1780 elements_kind = GetHoleyElementsKind(elements_kind); |
| 1781 JSObject::TransitionElementsKind(array, elements_kind); |
1799 } | 1782 } |
| 1783 return array; |
| 1784 } else if (length == 0) { |
| 1785 JSArray::Initialize(array, JSArray::kPreallocatedArrayElements); |
| 1786 return array; |
1800 } | 1787 } |
1801 | 1788 |
1802 // Take the argument as the length. | 1789 // Take the argument as the length. |
1803 JSArray::Initialize(array, 0); | 1790 JSArray::Initialize(array, 0); |
1804 | 1791 return JSArray::SetElementsLength(array, args->at<Object>(0)); |
1805 return JSArray::SetElementsLength(array, obj); | |
1806 } | |
1807 | |
1808 // Optimize the case where there are no parameters passed. | |
1809 if (args->length() == 0) { | |
1810 JSArray::Initialize(array, JSArray::kPreallocatedArrayElements); | |
1811 return array; | |
1812 } | 1792 } |
1813 | 1793 |
1814 Factory* factory = array->GetIsolate()->factory(); | 1794 Factory* factory = array->GetIsolate()->factory(); |
1815 | 1795 |
1816 // Set length and elements on the array. | 1796 // Set length and elements on the array. |
1817 int number_of_elements = args->length(); | 1797 int number_of_elements = args->length(); |
1818 JSObject::EnsureCanContainElements( | 1798 JSObject::EnsureCanContainElements( |
1819 array, args, 0, number_of_elements, ALLOW_CONVERTED_DOUBLE_ELEMENTS); | 1799 array, args, 0, number_of_elements, ALLOW_CONVERTED_DOUBLE_ELEMENTS); |
1820 | 1800 |
1821 // Allocate an appropriately typed elements array. | 1801 // Allocate an appropriately typed elements array. |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1863 break; | 1843 break; |
1864 } | 1844 } |
1865 | 1845 |
1866 array->set_elements(*elms); | 1846 array->set_elements(*elms); |
1867 array->set_length(Smi::FromInt(number_of_elements)); | 1847 array->set_length(Smi::FromInt(number_of_elements)); |
1868 return array; | 1848 return array; |
1869 } | 1849 } |
1870 | 1850 |
1871 } // namespace internal | 1851 } // namespace internal |
1872 } // namespace v8 | 1852 } // namespace v8 |
OLD | NEW |