OLD | NEW |
1 // Copyright 2017 the V8 project authors. All rights reserved. | 1 // Copyright 2017 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/builtins/builtins-utils-gen.h" | 5 #include "src/builtins/builtins-utils-gen.h" |
6 #include "src/builtins/builtins.h" | 6 #include "src/builtins/builtins.h" |
7 #include "src/code-stub-assembler.h" | 7 #include "src/code-stub-assembler.h" |
8 | 8 |
9 namespace v8 { | 9 namespace v8 { |
10 namespace internal { | 10 namespace internal { |
(...skipping 1661 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1672 const int kSearchElementArg = 0; | 1672 const int kSearchElementArg = 0; |
1673 const int kFromIndexArg = 1; | 1673 const int kFromIndexArg = 1; |
1674 | 1674 |
1675 Node* argc = | 1675 Node* argc = |
1676 ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount)); | 1676 ChangeInt32ToIntPtr(Parameter(BuiltinDescriptor::kArgumentsCount)); |
1677 CodeStubArguments args(this, argc); | 1677 CodeStubArguments args(this, argc); |
1678 | 1678 |
1679 Node* array = args.GetReceiver(); | 1679 Node* array = args.GetReceiver(); |
1680 Node* search_element = | 1680 Node* search_element = |
1681 args.GetOptionalArgumentValue(kSearchElementArg, UndefinedConstant()); | 1681 args.GetOptionalArgumentValue(kSearchElementArg, UndefinedConstant()); |
1682 Node* start_from = | |
1683 args.GetOptionalArgumentValue(kFromIndexArg, UndefinedConstant()); | |
1684 Node* context = Parameter(BuiltinDescriptor::kContext); | 1682 Node* context = Parameter(BuiltinDescriptor::kContext); |
1685 | 1683 |
1686 Node* intptr_zero = IntPtrConstant(0); | 1684 Node* intptr_zero = IntPtrConstant(0); |
1687 Node* intptr_one = IntPtrConstant(1); | 1685 Node* intptr_one = IntPtrConstant(1); |
1688 | 1686 |
1689 VARIABLE(len_var, MachineType::PointerRepresentation()); | 1687 Label init_index(this), return_found(this), return_not_found(this), |
1690 VARIABLE(index_var, MachineType::PointerRepresentation()); | |
1691 VARIABLE(start_from_var, MachineType::PointerRepresentation()); | |
1692 | |
1693 Label init_k(this), return_found(this), return_not_found(this), | |
1694 call_runtime(this); | 1688 call_runtime(this); |
1695 | 1689 |
1696 Label init_len(this); | |
1697 | |
1698 index_var.Bind(intptr_zero); | |
1699 len_var.Bind(intptr_zero); | |
1700 | |
1701 // Take slow path if not a JSArray, if retrieving elements requires | 1690 // Take slow path if not a JSArray, if retrieving elements requires |
1702 // traversing prototype, or if access checks are required. | 1691 // traversing prototype, or if access checks are required. |
1703 BranchIfFastJSArray(array, context, FastJSArrayAccessMode::INBOUNDS_READ, | 1692 BranchIfFastJSArray(array, context, FastJSArrayAccessMode::INBOUNDS_READ, |
1704 &init_len, &call_runtime); | 1693 &init_index, &call_runtime); |
1705 | 1694 |
1706 BIND(&init_len); | 1695 BIND(&init_index); |
1707 { | 1696 VARIABLE(index_var, MachineType::PointerRepresentation(), intptr_zero); |
1708 // JSArray length is always an Smi for fast arrays. | |
1709 CSA_ASSERT(this, | |
1710 TaggedIsSmi(LoadObjectField(array, JSArray::kLengthOffset))); | |
1711 Node* len = LoadAndUntagObjectField(array, JSArray::kLengthOffset); | |
1712 | 1697 |
1713 len_var.Bind(len); | 1698 // JSArray length is always a positive Smi for fast arrays. |
1714 Branch(WordEqual(len_var.value(), intptr_zero), &return_not_found, &init_k); | 1699 CSA_ASSERT(this, TaggedIsPositiveSmi(LoadJSArrayLength(array))); |
1715 } | 1700 Node* array_length = SmiUntag(LoadJSArrayLength(array)); |
1716 | 1701 |
1717 BIND(&init_k); | |
1718 { | 1702 { |
1719 // For now only deal with undefined and Smis here; we must be really careful | 1703 // For now only deal with undefined and Smis here; we must be really careful |
1720 // with side-effects from the ToInteger conversion as the side-effects might | 1704 // with side-effects from the ToInteger conversion as the side-effects might |
1721 // render our assumptions about the receiver being a fast JSArray and the | 1705 // render our assumptions about the receiver being a fast JSArray and the |
1722 // length invalid. | 1706 // length invalid. |
1723 Label done(this), init_k_smi(this), init_k_other(this), init_k_zero(this), | 1707 Label done(this); |
1724 init_k_n(this); | |
1725 Branch(TaggedIsSmi(start_from), &init_k_smi, &init_k_other); | |
1726 | 1708 |
1727 BIND(&init_k_smi); | 1709 // If no fromIndex was passed, default to 0. |
| 1710 GotoIf(IntPtrLessThanOrEqual(argc, IntPtrConstant(kFromIndexArg)), &done); |
| 1711 |
| 1712 // Handle Smis here and everything else in runtime. |
| 1713 Node* start_from = args.AtIndex(kFromIndexArg); |
| 1714 GotoIfNot(TaggedIsSmi(start_from), &call_runtime); |
| 1715 |
| 1716 Node* intptr_start_from = SmiUntag(start_from); |
| 1717 index_var.Bind(intptr_start_from); |
| 1718 |
| 1719 Label if_negative(this); |
| 1720 Branch(IntPtrLessThan(intptr_start_from, intptr_zero), &if_negative, &done); |
| 1721 |
| 1722 BIND(&if_negative); |
1728 { | 1723 { |
1729 // The fromIndex is a Smi. | 1724 Node* len_minus_start_from = IntPtrAdd(array_length, intptr_start_from); |
1730 start_from_var.Bind(SmiUntag(start_from)); | 1725 index_var.Bind(IntPtrMax(len_minus_start_from, intptr_zero)); |
1731 Goto(&init_k_n); | 1726 Goto(&done); |
1732 } | 1727 } |
1733 | 1728 |
1734 BIND(&init_k_other); | 1729 BIND(&done); |
1735 { | 1730 } |
1736 // The fromIndex must be undefined then, otherwise bailout and let the | |
1737 // runtime deal with the full ToInteger conversion. | |
1738 GotoIfNot(IsUndefined(start_from), &call_runtime); | |
1739 start_from_var.Bind(intptr_zero); | |
1740 Goto(&init_k_n); | |
1741 } | |
1742 | 1731 |
1743 BIND(&init_k_n); | 1732 // Fail early if startIndex >= array.length. |
1744 { | 1733 GotoIf(IntPtrGreaterThanOrEqual(index_var.value(), array_length), |
1745 Label if_positive(this), if_negative(this), done(this); | 1734 &return_not_found); |
1746 Branch(IntPtrLessThan(start_from_var.value(), intptr_zero), &if_negative, | |
1747 &if_positive); | |
1748 | |
1749 BIND(&if_positive); | |
1750 { | |
1751 index_var.Bind(start_from_var.value()); | |
1752 Goto(&done); | |
1753 } | |
1754 | |
1755 BIND(&if_negative); | |
1756 { | |
1757 index_var.Bind(IntPtrAdd(len_var.value(), start_from_var.value())); | |
1758 Branch(IntPtrLessThan(index_var.value(), intptr_zero), &init_k_zero, | |
1759 &done); | |
1760 } | |
1761 | |
1762 BIND(&init_k_zero); | |
1763 { | |
1764 index_var.Bind(intptr_zero); | |
1765 Goto(&done); | |
1766 } | |
1767 | |
1768 BIND(&done); | |
1769 } | |
1770 } | |
1771 | 1735 |
1772 static int32_t kElementsKind[] = { | 1736 static int32_t kElementsKind[] = { |
1773 FAST_SMI_ELEMENTS, FAST_HOLEY_SMI_ELEMENTS, FAST_ELEMENTS, | 1737 FAST_SMI_ELEMENTS, FAST_HOLEY_SMI_ELEMENTS, FAST_ELEMENTS, |
1774 FAST_HOLEY_ELEMENTS, FAST_DOUBLE_ELEMENTS, FAST_HOLEY_DOUBLE_ELEMENTS, | 1738 FAST_HOLEY_ELEMENTS, FAST_DOUBLE_ELEMENTS, FAST_HOLEY_DOUBLE_ELEMENTS, |
1775 }; | 1739 }; |
1776 | 1740 |
1777 Label if_smiorobjects(this), if_packed_doubles(this), if_holey_doubles(this); | 1741 Label if_smiorobjects(this), if_packed_doubles(this), if_holey_doubles(this); |
1778 Label* element_kind_handlers[] = {&if_smiorobjects, &if_smiorobjects, | 1742 Label* element_kind_handlers[] = {&if_smiorobjects, &if_smiorobjects, |
1779 &if_smiorobjects, &if_smiorobjects, | 1743 &if_smiorobjects, &if_smiorobjects, |
1780 &if_packed_doubles, &if_holey_doubles}; | 1744 &if_packed_doubles, &if_holey_doubles}; |
(...skipping 20 matching lines...) Expand all Loading... |
1801 search_num.Bind(LoadHeapNumberValue(search_element)); | 1765 search_num.Bind(LoadHeapNumberValue(search_element)); |
1802 Goto(&heap_num_loop); | 1766 Goto(&heap_num_loop); |
1803 | 1767 |
1804 BIND(¬_heap_num); | 1768 BIND(¬_heap_num); |
1805 Node* search_type = LoadMapInstanceType(map); | 1769 Node* search_type = LoadMapInstanceType(map); |
1806 GotoIf(IsStringInstanceType(search_type), &string_loop); | 1770 GotoIf(IsStringInstanceType(search_type), &string_loop); |
1807 Goto(&ident_loop); | 1771 Goto(&ident_loop); |
1808 | 1772 |
1809 BIND(&ident_loop); | 1773 BIND(&ident_loop); |
1810 { | 1774 { |
1811 GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()), | 1775 GotoIfNot(UintPtrLessThan(index_var.value(), array_length), |
1812 &return_not_found); | 1776 &return_not_found); |
1813 Node* element_k = LoadFixedArrayElement(elements, index_var.value()); | 1777 Node* element_k = LoadFixedArrayElement(elements, index_var.value()); |
1814 GotoIf(WordEqual(element_k, search_element), &return_found); | 1778 GotoIf(WordEqual(element_k, search_element), &return_found); |
1815 | 1779 |
1816 index_var.Bind(IntPtrAdd(index_var.value(), intptr_one)); | 1780 index_var.Bind(IntPtrAdd(index_var.value(), intptr_one)); |
1817 Goto(&ident_loop); | 1781 Goto(&ident_loop); |
1818 } | 1782 } |
1819 | 1783 |
1820 BIND(&heap_num_loop); | 1784 BIND(&heap_num_loop); |
1821 { | 1785 { |
1822 Label not_nan_loop(this, &index_var); | 1786 Label not_nan_loop(this, &index_var); |
1823 BranchIfFloat64IsNaN(search_num.value(), &return_not_found, | 1787 BranchIfFloat64IsNaN(search_num.value(), &return_not_found, |
1824 ¬_nan_loop); | 1788 ¬_nan_loop); |
1825 | 1789 |
1826 BIND(¬_nan_loop); | 1790 BIND(¬_nan_loop); |
1827 { | 1791 { |
1828 Label continue_loop(this), not_smi(this); | 1792 Label continue_loop(this), not_smi(this); |
1829 GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()), | 1793 GotoIfNot(UintPtrLessThan(index_var.value(), array_length), |
1830 &return_not_found); | 1794 &return_not_found); |
1831 Node* element_k = LoadFixedArrayElement(elements, index_var.value()); | 1795 Node* element_k = LoadFixedArrayElement(elements, index_var.value()); |
1832 GotoIfNot(TaggedIsSmi(element_k), ¬_smi); | 1796 GotoIfNot(TaggedIsSmi(element_k), ¬_smi); |
1833 Branch(Float64Equal(search_num.value(), SmiToFloat64(element_k)), | 1797 Branch(Float64Equal(search_num.value(), SmiToFloat64(element_k)), |
1834 &return_found, &continue_loop); | 1798 &return_found, &continue_loop); |
1835 | 1799 |
1836 BIND(¬_smi); | 1800 BIND(¬_smi); |
1837 GotoIfNot(IsHeapNumber(element_k), &continue_loop); | 1801 GotoIfNot(IsHeapNumber(element_k), &continue_loop); |
1838 Branch(Float64Equal(search_num.value(), LoadHeapNumberValue(element_k)), | 1802 Branch(Float64Equal(search_num.value(), LoadHeapNumberValue(element_k)), |
1839 &return_found, &continue_loop); | 1803 &return_found, &continue_loop); |
1840 | 1804 |
1841 BIND(&continue_loop); | 1805 BIND(&continue_loop); |
1842 index_var.Bind(IntPtrAdd(index_var.value(), intptr_one)); | 1806 index_var.Bind(IntPtrAdd(index_var.value(), intptr_one)); |
1843 Goto(¬_nan_loop); | 1807 Goto(¬_nan_loop); |
1844 } | 1808 } |
1845 } | 1809 } |
1846 | 1810 |
1847 BIND(&string_loop); | 1811 BIND(&string_loop); |
1848 { | 1812 { |
| 1813 CSA_ASSERT(this, IsString(search_element)); |
1849 Label continue_loop(this); | 1814 Label continue_loop(this); |
1850 GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()), | 1815 GotoIfNot(UintPtrLessThan(index_var.value(), array_length), |
1851 &return_not_found); | 1816 &return_not_found); |
1852 Node* element_k = LoadFixedArrayElement(elements, index_var.value()); | 1817 Node* element_k = LoadFixedArrayElement(elements, index_var.value()); |
1853 GotoIf(TaggedIsSmi(element_k), &continue_loop); | 1818 GotoIf(TaggedIsSmi(element_k), &continue_loop); |
1854 GotoIfNot(IsString(element_k), &continue_loop); | 1819 GotoIfNot(IsString(element_k), &continue_loop); |
1855 | 1820 |
1856 // TODO(bmeurer): Consider inlining the StringEqual logic here. | 1821 // TODO(bmeurer): Consider inlining the StringEqual logic here. |
1857 Callable callable = CodeFactory::StringEqual(isolate()); | 1822 Callable callable = CodeFactory::StringEqual(isolate()); |
1858 Node* result = CallStub(callable, context, search_element, element_k); | 1823 Node* result = CallStub(callable, context, search_element, element_k); |
1859 Branch(WordEqual(BooleanConstant(true), result), &return_found, | 1824 Branch(WordEqual(BooleanConstant(true), result), &return_found, |
1860 &continue_loop); | 1825 &continue_loop); |
1861 | 1826 |
1862 BIND(&continue_loop); | 1827 BIND(&continue_loop); |
1863 index_var.Bind(IntPtrAdd(index_var.value(), intptr_one)); | 1828 Increment(index_var); |
1864 Goto(&string_loop); | 1829 Goto(&string_loop); |
1865 } | 1830 } |
1866 } | 1831 } |
1867 | 1832 |
1868 BIND(&if_packed_doubles); | 1833 BIND(&if_packed_doubles); |
1869 { | 1834 { |
1870 Label not_nan_loop(this, &index_var), search_notnan(this); | 1835 Label not_nan_loop(this, &index_var), search_notnan(this); |
1871 VARIABLE(search_num, MachineRepresentation::kFloat64); | 1836 VARIABLE(search_num, MachineRepresentation::kFloat64); |
1872 | 1837 |
1873 GotoIfNot(TaggedIsSmi(search_element), &search_notnan); | 1838 GotoIfNot(TaggedIsSmi(search_element), &search_notnan); |
1874 search_num.Bind(SmiToFloat64(search_element)); | 1839 search_num.Bind(SmiToFloat64(search_element)); |
1875 Goto(¬_nan_loop); | 1840 Goto(¬_nan_loop); |
1876 | 1841 |
1877 BIND(&search_notnan); | 1842 BIND(&search_notnan); |
1878 GotoIfNot(IsHeapNumber(search_element), &return_not_found); | 1843 GotoIfNot(IsHeapNumber(search_element), &return_not_found); |
1879 | 1844 |
1880 search_num.Bind(LoadHeapNumberValue(search_element)); | 1845 search_num.Bind(LoadHeapNumberValue(search_element)); |
1881 | 1846 |
1882 BranchIfFloat64IsNaN(search_num.value(), &return_not_found, ¬_nan_loop); | 1847 BranchIfFloat64IsNaN(search_num.value(), &return_not_found, ¬_nan_loop); |
1883 | 1848 |
1884 // Search for HeapNumber | 1849 // Search for HeapNumber |
1885 BIND(¬_nan_loop); | 1850 BIND(¬_nan_loop); |
1886 { | 1851 { |
1887 GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()), | 1852 GotoIfNot(UintPtrLessThan(index_var.value(), array_length), |
1888 &return_not_found); | 1853 &return_not_found); |
1889 Node* element_k = LoadFixedDoubleArrayElement(elements, index_var.value(), | 1854 Node* element_k = LoadFixedDoubleArrayElement(elements, index_var.value(), |
1890 MachineType::Float64()); | 1855 MachineType::Float64()); |
1891 GotoIf(Float64Equal(element_k, search_num.value()), &return_found); | 1856 GotoIf(Float64Equal(element_k, search_num.value()), &return_found); |
1892 | 1857 |
1893 index_var.Bind(IntPtrAdd(index_var.value(), intptr_one)); | 1858 index_var.Bind(IntPtrAdd(index_var.value(), intptr_one)); |
1894 Goto(¬_nan_loop); | 1859 Goto(¬_nan_loop); |
1895 } | 1860 } |
1896 } | 1861 } |
1897 | 1862 |
(...skipping 10 matching lines...) Expand all Loading... |
1908 GotoIfNot(IsHeapNumber(search_element), &return_not_found); | 1873 GotoIfNot(IsHeapNumber(search_element), &return_not_found); |
1909 | 1874 |
1910 search_num.Bind(LoadHeapNumberValue(search_element)); | 1875 search_num.Bind(LoadHeapNumberValue(search_element)); |
1911 | 1876 |
1912 BranchIfFloat64IsNaN(search_num.value(), &return_not_found, ¬_nan_loop); | 1877 BranchIfFloat64IsNaN(search_num.value(), &return_not_found, ¬_nan_loop); |
1913 | 1878 |
1914 // Search for HeapNumber | 1879 // Search for HeapNumber |
1915 BIND(¬_nan_loop); | 1880 BIND(¬_nan_loop); |
1916 { | 1881 { |
1917 Label continue_loop(this); | 1882 Label continue_loop(this); |
1918 GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()), | 1883 GotoIfNot(UintPtrLessThan(index_var.value(), array_length), |
1919 &return_not_found); | 1884 &return_not_found); |
1920 | 1885 |
1921 // Load double value or continue if it contains a double hole. | 1886 // Load double value or continue if it contains a double hole. |
1922 Node* element_k = LoadFixedDoubleArrayElement( | 1887 Node* element_k = LoadFixedDoubleArrayElement( |
1923 elements, index_var.value(), MachineType::Float64(), 0, | 1888 elements, index_var.value(), MachineType::Float64(), 0, |
1924 INTPTR_PARAMETERS, &continue_loop); | 1889 INTPTR_PARAMETERS, &continue_loop); |
1925 | 1890 |
1926 Branch(Float64Equal(element_k, search_num.value()), &return_found, | 1891 Branch(Float64Equal(element_k, search_num.value()), &return_found, |
1927 &continue_loop); | 1892 &continue_loop); |
1928 BIND(&continue_loop); | 1893 BIND(&continue_loop); |
1929 index_var.Bind(IntPtrAdd(index_var.value(), intptr_one)); | 1894 index_var.Bind(IntPtrAdd(index_var.value(), intptr_one)); |
1930 Goto(¬_nan_loop); | 1895 Goto(¬_nan_loop); |
1931 } | 1896 } |
1932 } | 1897 } |
1933 | 1898 |
1934 BIND(&return_found); | 1899 BIND(&return_found); |
1935 args.PopAndReturn(SmiTag(index_var.value())); | 1900 args.PopAndReturn(SmiTag(index_var.value())); |
1936 | 1901 |
1937 BIND(&return_not_found); | 1902 BIND(&return_not_found); |
1938 args.PopAndReturn(NumberConstant(-1)); | 1903 args.PopAndReturn(NumberConstant(-1)); |
1939 | 1904 |
1940 BIND(&call_runtime); | 1905 BIND(&call_runtime); |
1941 args.PopAndReturn(CallRuntime(Runtime::kArrayIndexOf, context, array, | 1906 { |
1942 search_element, start_from)); | 1907 Node* start_from = |
| 1908 args.GetOptionalArgumentValue(kFromIndexArg, UndefinedConstant()); |
| 1909 args.PopAndReturn(CallRuntime(Runtime::kArrayIndexOf, context, array, |
| 1910 search_element, start_from)); |
| 1911 } |
1943 } | 1912 } |
1944 | 1913 |
1945 class ArrayPrototypeIterationAssembler : public CodeStubAssembler { | 1914 class ArrayPrototypeIterationAssembler : public CodeStubAssembler { |
1946 public: | 1915 public: |
1947 explicit ArrayPrototypeIterationAssembler(compiler::CodeAssemblerState* state) | 1916 explicit ArrayPrototypeIterationAssembler(compiler::CodeAssemblerState* state) |
1948 : CodeStubAssembler(state) {} | 1917 : CodeStubAssembler(state) {} |
1949 | 1918 |
1950 protected: | 1919 protected: |
1951 void Generate_ArrayPrototypeIterationMethod(Node* context, Node* receiver, | 1920 void Generate_ArrayPrototypeIterationMethod(Node* context, Node* receiver, |
1952 IterationKind iteration_kind) { | 1921 IterationKind iteration_kind) { |
(...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2416 { | 2385 { |
2417 Node* message = SmiConstant(MessageTemplate::kDetachedOperation); | 2386 Node* message = SmiConstant(MessageTemplate::kDetachedOperation); |
2418 CallRuntime(Runtime::kThrowTypeError, context, message, | 2387 CallRuntime(Runtime::kThrowTypeError, context, message, |
2419 HeapConstant(operation)); | 2388 HeapConstant(operation)); |
2420 Unreachable(); | 2389 Unreachable(); |
2421 } | 2390 } |
2422 } | 2391 } |
2423 | 2392 |
2424 } // namespace internal | 2393 } // namespace internal |
2425 } // namespace v8 | 2394 } // namespace v8 |
OLD | NEW |