OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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.h" | 5 #include "src/builtins/builtins.h" |
6 #include "src/builtins/builtins-utils.h" | 6 #include "src/builtins/builtins-utils.h" |
7 | 7 |
8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
9 #include "src/code-stub-assembler.h" | 9 #include "src/code-stub-assembler.h" |
10 #include "src/contexts.h" | 10 #include "src/contexts.h" |
(...skipping 1667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1678 assembler.Return( | 1678 assembler.Return( |
1679 assembler.CallRuntime(Runtime::kArrayIsArray, context, object)); | 1679 assembler.CallRuntime(Runtime::kArrayIsArray, context, object)); |
1680 } | 1680 } |
1681 | 1681 |
1682 TF_BUILTIN(ArrayIncludes, CodeStubAssembler) { | 1682 TF_BUILTIN(ArrayIncludes, CodeStubAssembler) { |
1683 Node* const array = Parameter(0); | 1683 Node* const array = Parameter(0); |
1684 Node* const search_element = Parameter(1); | 1684 Node* const search_element = Parameter(1); |
1685 Node* const start_from = Parameter(2); | 1685 Node* const start_from = Parameter(2); |
1686 Node* const context = Parameter(3 + 2); | 1686 Node* const context = Parameter(3 + 2); |
1687 | 1687 |
1688 Variable len_var(this, MachineType::PointerRepresentation()), | 1688 Variable index_var(this, MachineType::PointerRepresentation()); |
1689 index_var(this, MachineType::PointerRepresentation()); | |
1690 | 1689 |
1691 Label init_k(this), return_true(this), return_false(this), call_runtime(this); | 1690 Label init_k(this), return_true(this), return_false(this), call_runtime(this); |
1692 Label init_len(this), select_loop(this); | 1691 Label init_len(this), select_loop(this); |
1693 | 1692 |
1694 index_var.Bind(IntPtrConstant(0)); | 1693 index_var.Bind(IntPtrConstant(0)); |
1695 len_var.Bind(IntPtrConstant(0)); | |
1696 | 1694 |
1697 // Take slow path if not a JSArray, if retrieving elements requires | 1695 // Take slow path if not a JSArray, if retrieving elements requires |
1698 // traversing prototype, or if access checks are required. | 1696 // traversing prototype, or if access checks are required. |
1699 BranchIfFastJSArray(array, context, | 1697 BranchIfFastJSArray(array, context, |
1700 CodeStubAssembler::FastJSArrayAccessMode::INBOUNDS_READ, | 1698 CodeStubAssembler::FastJSArrayAccessMode::INBOUNDS_READ, |
1701 &init_len, &call_runtime); | 1699 &init_len, &call_runtime); |
1702 | 1700 |
1703 Bind(&init_len); | 1701 Bind(&init_len); |
1704 { | 1702 // JSArray length is always an Smi for fast arrays. |
1705 // Handle case where JSArray length is not an Smi in the runtime | 1703 CSA_ASSERT(this, TaggedIsSmi(LoadObjectField(array, JSArray::kLengthOffset))); |
1706 Node* len = LoadObjectField(array, JSArray::kLengthOffset); | 1704 Node* const len = LoadAndUntagObjectField(array, JSArray::kLengthOffset); |
1707 GotoIfNot(TaggedIsSmi(len), &call_runtime); | |
1708 | 1705 |
1709 len_var.Bind(SmiToWord(len)); | 1706 GotoIf(IsUndefined(start_from), &select_loop); |
1710 | 1707 |
1711 GotoIf(IsUndefined(start_from), &select_loop); | 1708 // Bailout to slow path if startIndex is not an Smi. |
1712 | 1709 Branch(TaggedIsSmi(start_from), &init_k, &call_runtime); |
1713 // Bailout to slow path if startIndex is not an Smi. | |
1714 Branch(TaggedIsSmi(start_from), &init_k, &call_runtime); | |
1715 } | |
1716 | 1710 |
1717 Bind(&init_k); | 1711 Bind(&init_k); |
1718 CSA_ASSERT(this, TaggedIsSmi(start_from)); | 1712 CSA_ASSERT(this, TaggedIsSmi(start_from)); |
1719 Node* const untagged_start_from = SmiToWord(start_from); | 1713 Node* const untagged_start_from = SmiToWord(start_from); |
1720 index_var.Bind(Select( | 1714 index_var.Bind(Select( |
1721 IntPtrGreaterThanOrEqual(untagged_start_from, IntPtrConstant(0)), | 1715 IntPtrGreaterThanOrEqual(untagged_start_from, IntPtrConstant(0)), |
1722 [=]() { return untagged_start_from; }, | 1716 [=]() { return untagged_start_from; }, |
1723 [=]() { | 1717 [=]() { |
1724 Node* const index = IntPtrAdd(len_var.value(), untagged_start_from); | 1718 Node* const index = IntPtrAdd(len, untagged_start_from); |
1725 return SelectConstant(IntPtrLessThan(index, IntPtrConstant(0)), | 1719 return SelectConstant(IntPtrLessThan(index, IntPtrConstant(0)), |
1726 IntPtrConstant(0), index, | 1720 IntPtrConstant(0), index, |
1727 MachineType::PointerRepresentation()); | 1721 MachineType::PointerRepresentation()); |
1728 }, | 1722 }, |
1729 MachineType::PointerRepresentation())); | 1723 MachineType::PointerRepresentation())); |
1730 | 1724 |
1731 Goto(&select_loop); | 1725 Goto(&select_loop); |
1732 Bind(&select_loop); | 1726 Bind(&select_loop); |
1733 static int32_t kElementsKind[] = { | 1727 static int32_t kElementsKind[] = { |
1734 FAST_SMI_ELEMENTS, FAST_HOLEY_SMI_ELEMENTS, FAST_ELEMENTS, | 1728 FAST_SMI_ELEMENTS, FAST_HOLEY_SMI_ELEMENTS, FAST_ELEMENTS, |
(...skipping 29 matching lines...) Expand all Loading... |
1764 search_num.Bind(LoadHeapNumberValue(search_element)); | 1758 search_num.Bind(LoadHeapNumberValue(search_element)); |
1765 Goto(&heap_num_loop); | 1759 Goto(&heap_num_loop); |
1766 | 1760 |
1767 Bind(¬_heap_num); | 1761 Bind(¬_heap_num); |
1768 Node* search_type = LoadMapInstanceType(map); | 1762 Node* search_type = LoadMapInstanceType(map); |
1769 GotoIf(IsStringInstanceType(search_type), &string_loop); | 1763 GotoIf(IsStringInstanceType(search_type), &string_loop); |
1770 Goto(&ident_loop); | 1764 Goto(&ident_loop); |
1771 | 1765 |
1772 Bind(&ident_loop); | 1766 Bind(&ident_loop); |
1773 { | 1767 { |
1774 GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()), | 1768 GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false); |
1775 &return_false); | |
1776 Node* element_k = LoadFixedArrayElement(elements, index_var.value()); | 1769 Node* element_k = LoadFixedArrayElement(elements, index_var.value()); |
1777 GotoIf(WordEqual(element_k, search_element), &return_true); | 1770 GotoIf(WordEqual(element_k, search_element), &return_true); |
1778 | 1771 |
1779 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); | 1772 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); |
1780 Goto(&ident_loop); | 1773 Goto(&ident_loop); |
1781 } | 1774 } |
1782 | 1775 |
1783 Bind(&undef_loop); | 1776 Bind(&undef_loop); |
1784 { | 1777 { |
1785 GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()), | 1778 GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false); |
1786 &return_false); | |
1787 Node* element_k = LoadFixedArrayElement(elements, index_var.value()); | 1779 Node* element_k = LoadFixedArrayElement(elements, index_var.value()); |
1788 GotoIf(WordEqual(element_k, UndefinedConstant()), &return_true); | 1780 GotoIf(WordEqual(element_k, UndefinedConstant()), &return_true); |
1789 GotoIf(WordEqual(element_k, TheHoleConstant()), &return_true); | 1781 GotoIf(WordEqual(element_k, TheHoleConstant()), &return_true); |
1790 | 1782 |
1791 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); | 1783 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); |
1792 Goto(&undef_loop); | 1784 Goto(&undef_loop); |
1793 } | 1785 } |
1794 | 1786 |
1795 Bind(&heap_num_loop); | 1787 Bind(&heap_num_loop); |
1796 { | 1788 { |
1797 Label nan_loop(this, &index_var), not_nan_loop(this, &index_var); | 1789 Label nan_loop(this, &index_var), not_nan_loop(this, &index_var); |
1798 BranchIfFloat64IsNaN(search_num.value(), &nan_loop, ¬_nan_loop); | 1790 BranchIfFloat64IsNaN(search_num.value(), &nan_loop, ¬_nan_loop); |
1799 | 1791 |
1800 Bind(¬_nan_loop); | 1792 Bind(¬_nan_loop); |
1801 { | 1793 { |
1802 Label continue_loop(this), not_smi(this); | 1794 Label continue_loop(this), not_smi(this); |
1803 GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()), | 1795 GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false); |
1804 &return_false); | |
1805 Node* element_k = LoadFixedArrayElement(elements, index_var.value()); | 1796 Node* element_k = LoadFixedArrayElement(elements, index_var.value()); |
1806 GotoIfNot(TaggedIsSmi(element_k), ¬_smi); | 1797 GotoIfNot(TaggedIsSmi(element_k), ¬_smi); |
1807 Branch(Float64Equal(search_num.value(), SmiToFloat64(element_k)), | 1798 Branch(Float64Equal(search_num.value(), SmiToFloat64(element_k)), |
1808 &return_true, &continue_loop); | 1799 &return_true, &continue_loop); |
1809 | 1800 |
1810 Bind(¬_smi); | 1801 Bind(¬_smi); |
1811 GotoIfNot(IsHeapNumber(element_k), &continue_loop); | 1802 GotoIfNot(IsHeapNumber(element_k), &continue_loop); |
1812 Branch(Float64Equal(search_num.value(), LoadHeapNumberValue(element_k)), | 1803 Branch(Float64Equal(search_num.value(), LoadHeapNumberValue(element_k)), |
1813 &return_true, &continue_loop); | 1804 &return_true, &continue_loop); |
1814 | 1805 |
1815 Bind(&continue_loop); | 1806 Bind(&continue_loop); |
1816 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); | 1807 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); |
1817 Goto(¬_nan_loop); | 1808 Goto(¬_nan_loop); |
1818 } | 1809 } |
1819 | 1810 |
1820 Bind(&nan_loop); | 1811 Bind(&nan_loop); |
1821 { | 1812 { |
1822 Label continue_loop(this); | 1813 Label continue_loop(this); |
1823 GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()), | 1814 GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false); |
1824 &return_false); | |
1825 Node* element_k = LoadFixedArrayElement(elements, index_var.value()); | 1815 Node* element_k = LoadFixedArrayElement(elements, index_var.value()); |
1826 GotoIf(TaggedIsSmi(element_k), &continue_loop); | 1816 GotoIf(TaggedIsSmi(element_k), &continue_loop); |
1827 GotoIfNot(IsHeapNumber(element_k), &continue_loop); | 1817 GotoIfNot(IsHeapNumber(element_k), &continue_loop); |
1828 BranchIfFloat64IsNaN(LoadHeapNumberValue(element_k), &return_true, | 1818 BranchIfFloat64IsNaN(LoadHeapNumberValue(element_k), &return_true, |
1829 &continue_loop); | 1819 &continue_loop); |
1830 | 1820 |
1831 Bind(&continue_loop); | 1821 Bind(&continue_loop); |
1832 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); | 1822 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); |
1833 Goto(&nan_loop); | 1823 Goto(&nan_loop); |
1834 } | 1824 } |
1835 } | 1825 } |
1836 | 1826 |
1837 Bind(&string_loop); | 1827 Bind(&string_loop); |
1838 { | 1828 { |
1839 Label continue_loop(this); | 1829 Label continue_loop(this); |
1840 GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()), | 1830 GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false); |
1841 &return_false); | |
1842 Node* element_k = LoadFixedArrayElement(elements, index_var.value()); | 1831 Node* element_k = LoadFixedArrayElement(elements, index_var.value()); |
1843 GotoIf(TaggedIsSmi(element_k), &continue_loop); | 1832 GotoIf(TaggedIsSmi(element_k), &continue_loop); |
1844 GotoIfNot(IsStringInstanceType(LoadInstanceType(element_k)), | 1833 GotoIfNot(IsStringInstanceType(LoadInstanceType(element_k)), |
1845 &continue_loop); | 1834 &continue_loop); |
1846 | 1835 |
1847 // TODO(bmeurer): Consider inlining the StringEqual logic here. | 1836 // TODO(bmeurer): Consider inlining the StringEqual logic here. |
1848 Node* result = CallStub(CodeFactory::StringEqual(isolate()), context, | 1837 Node* result = CallStub(CodeFactory::StringEqual(isolate()), context, |
1849 search_element, element_k); | 1838 search_element, element_k); |
1850 Branch(WordEqual(BooleanConstant(true), result), &return_true, | 1839 Branch(WordEqual(BooleanConstant(true), result), &return_true, |
1851 &continue_loop); | 1840 &continue_loop); |
(...skipping 18 matching lines...) Expand all Loading... |
1870 GotoIfNot(IsHeapNumber(search_element), &return_false); | 1859 GotoIfNot(IsHeapNumber(search_element), &return_false); |
1871 | 1860 |
1872 search_num.Bind(LoadHeapNumberValue(search_element)); | 1861 search_num.Bind(LoadHeapNumberValue(search_element)); |
1873 | 1862 |
1874 BranchIfFloat64IsNaN(search_num.value(), &nan_loop, ¬_nan_loop); | 1863 BranchIfFloat64IsNaN(search_num.value(), &nan_loop, ¬_nan_loop); |
1875 | 1864 |
1876 // Search for HeapNumber | 1865 // Search for HeapNumber |
1877 Bind(¬_nan_loop); | 1866 Bind(¬_nan_loop); |
1878 { | 1867 { |
1879 Label continue_loop(this); | 1868 Label continue_loop(this); |
1880 GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()), | 1869 GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false); |
1881 &return_false); | |
1882 Node* element_k = LoadFixedDoubleArrayElement(elements, index_var.value(), | 1870 Node* element_k = LoadFixedDoubleArrayElement(elements, index_var.value(), |
1883 MachineType::Float64()); | 1871 MachineType::Float64()); |
1884 Branch(Float64Equal(element_k, search_num.value()), &return_true, | 1872 Branch(Float64Equal(element_k, search_num.value()), &return_true, |
1885 &continue_loop); | 1873 &continue_loop); |
1886 Bind(&continue_loop); | 1874 Bind(&continue_loop); |
1887 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); | 1875 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); |
1888 Goto(¬_nan_loop); | 1876 Goto(¬_nan_loop); |
1889 } | 1877 } |
1890 | 1878 |
1891 // Search for NaN | 1879 // Search for NaN |
1892 Bind(&nan_loop); | 1880 Bind(&nan_loop); |
1893 { | 1881 { |
1894 Label continue_loop(this); | 1882 Label continue_loop(this); |
1895 GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()), | 1883 GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false); |
1896 &return_false); | |
1897 Node* element_k = LoadFixedDoubleArrayElement(elements, index_var.value(), | 1884 Node* element_k = LoadFixedDoubleArrayElement(elements, index_var.value(), |
1898 MachineType::Float64()); | 1885 MachineType::Float64()); |
1899 BranchIfFloat64IsNaN(element_k, &return_true, &continue_loop); | 1886 BranchIfFloat64IsNaN(element_k, &return_true, &continue_loop); |
1900 Bind(&continue_loop); | 1887 Bind(&continue_loop); |
1901 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); | 1888 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); |
1902 Goto(&nan_loop); | 1889 Goto(&nan_loop); |
1903 } | 1890 } |
1904 } | 1891 } |
1905 | 1892 |
1906 Bind(&if_holey_doubles); | 1893 Bind(&if_holey_doubles); |
(...skipping 11 matching lines...) Expand all Loading... |
1918 GotoIfNot(IsHeapNumber(search_element), &return_false); | 1905 GotoIfNot(IsHeapNumber(search_element), &return_false); |
1919 | 1906 |
1920 search_num.Bind(LoadHeapNumberValue(search_element)); | 1907 search_num.Bind(LoadHeapNumberValue(search_element)); |
1921 | 1908 |
1922 BranchIfFloat64IsNaN(search_num.value(), &nan_loop, ¬_nan_loop); | 1909 BranchIfFloat64IsNaN(search_num.value(), &nan_loop, ¬_nan_loop); |
1923 | 1910 |
1924 // Search for HeapNumber | 1911 // Search for HeapNumber |
1925 Bind(¬_nan_loop); | 1912 Bind(¬_nan_loop); |
1926 { | 1913 { |
1927 Label continue_loop(this); | 1914 Label continue_loop(this); |
1928 GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()), | 1915 GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false); |
1929 &return_false); | |
1930 | 1916 |
1931 // Load double value or continue if it contains a double hole. | 1917 // Load double value or continue if it contains a double hole. |
1932 Node* element_k = LoadFixedDoubleArrayElement( | 1918 Node* element_k = LoadFixedDoubleArrayElement( |
1933 elements, index_var.value(), MachineType::Float64(), 0, | 1919 elements, index_var.value(), MachineType::Float64(), 0, |
1934 CodeStubAssembler::INTPTR_PARAMETERS, &continue_loop); | 1920 CodeStubAssembler::INTPTR_PARAMETERS, &continue_loop); |
1935 | 1921 |
1936 Branch(Float64Equal(element_k, search_num.value()), &return_true, | 1922 Branch(Float64Equal(element_k, search_num.value()), &return_true, |
1937 &continue_loop); | 1923 &continue_loop); |
1938 Bind(&continue_loop); | 1924 Bind(&continue_loop); |
1939 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); | 1925 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); |
1940 Goto(¬_nan_loop); | 1926 Goto(¬_nan_loop); |
1941 } | 1927 } |
1942 | 1928 |
1943 // Search for NaN | 1929 // Search for NaN |
1944 Bind(&nan_loop); | 1930 Bind(&nan_loop); |
1945 { | 1931 { |
1946 Label continue_loop(this); | 1932 Label continue_loop(this); |
1947 GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()), | 1933 GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false); |
1948 &return_false); | |
1949 | 1934 |
1950 // Load double value or continue if it contains a double hole. | 1935 // Load double value or continue if it contains a double hole. |
1951 Node* element_k = LoadFixedDoubleArrayElement( | 1936 Node* element_k = LoadFixedDoubleArrayElement( |
1952 elements, index_var.value(), MachineType::Float64(), 0, | 1937 elements, index_var.value(), MachineType::Float64(), 0, |
1953 CodeStubAssembler::INTPTR_PARAMETERS, &continue_loop); | 1938 CodeStubAssembler::INTPTR_PARAMETERS, &continue_loop); |
1954 | 1939 |
1955 BranchIfFloat64IsNaN(element_k, &return_true, &continue_loop); | 1940 BranchIfFloat64IsNaN(element_k, &return_true, &continue_loop); |
1956 Bind(&continue_loop); | 1941 Bind(&continue_loop); |
1957 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); | 1942 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); |
1958 Goto(&nan_loop); | 1943 Goto(&nan_loop); |
1959 } | 1944 } |
1960 | 1945 |
1961 // Search for the Hole | 1946 // Search for the Hole |
1962 Bind(&hole_loop); | 1947 Bind(&hole_loop); |
1963 { | 1948 { |
1964 GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()), | 1949 GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false); |
1965 &return_false); | |
1966 | 1950 |
1967 // Check if the element is a double hole, but don't load it. | 1951 // Check if the element is a double hole, but don't load it. |
1968 LoadFixedDoubleArrayElement( | 1952 LoadFixedDoubleArrayElement( |
1969 elements, index_var.value(), MachineType::None(), 0, | 1953 elements, index_var.value(), MachineType::None(), 0, |
1970 CodeStubAssembler::INTPTR_PARAMETERS, &return_true); | 1954 CodeStubAssembler::INTPTR_PARAMETERS, &return_true); |
1971 | 1955 |
1972 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); | 1956 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); |
1973 Goto(&hole_loop); | 1957 Goto(&hole_loop); |
1974 } | 1958 } |
1975 } | 1959 } |
(...skipping 875 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2851 { | 2835 { |
2852 Node* message = assembler.SmiConstant(MessageTemplate::kDetachedOperation); | 2836 Node* message = assembler.SmiConstant(MessageTemplate::kDetachedOperation); |
2853 assembler.CallRuntime(Runtime::kThrowTypeError, context, message, | 2837 assembler.CallRuntime(Runtime::kThrowTypeError, context, message, |
2854 assembler.HeapConstant(operation)); | 2838 assembler.HeapConstant(operation)); |
2855 assembler.Unreachable(); | 2839 assembler.Unreachable(); |
2856 } | 2840 } |
2857 } | 2841 } |
2858 | 2842 |
2859 } // namespace internal | 2843 } // namespace internal |
2860 } // namespace v8 | 2844 } // namespace v8 |
OLD | NEW |