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 |
1701 Node* len = nullptr; | |
vabr (Chromium)
2017/02/25 21:25:55
I tried to initialize |len| with LoadAndUntagObjec
Benedikt Meurer
2017/02/26 18:34:27
Just remove the { and } in 1704, and declare the N
vabr (Chromium)
2017/02/26 20:30:24
Done.
| |
1703 Bind(&init_len); | 1702 Bind(&init_len); |
1704 { | 1703 { |
1705 // Handle case where JSArray length is not an Smi in the runtime | 1704 // JSArray length is always an Smi for fast arrays. |
1706 Node* len = LoadObjectField(array, JSArray::kLengthOffset); | 1705 CSA_ASSERT(this, |
1707 GotoIfNot(TaggedIsSmi(len), &call_runtime); | 1706 TaggedIsSmi(LoadObjectField(array, JSArray::kLengthOffset))); |
1708 | 1707 len = LoadAndUntagObjectField(array, JSArray::kLengthOffset); |
1709 len_var.Bind(SmiToWord(len)); | |
1710 | 1708 |
1711 GotoIf(IsUndefined(start_from), &select_loop); | 1709 GotoIf(IsUndefined(start_from), &select_loop); |
1712 | 1710 |
1713 // Bailout to slow path if startIndex is not an Smi. | 1711 // Bailout to slow path if startIndex is not an Smi. |
1714 Branch(TaggedIsSmi(start_from), &init_k, &call_runtime); | 1712 Branch(TaggedIsSmi(start_from), &init_k, &call_runtime); |
1715 } | 1713 } |
1716 | 1714 |
1717 Bind(&init_k); | 1715 Bind(&init_k); |
1718 CSA_ASSERT(this, TaggedIsSmi(start_from)); | 1716 CSA_ASSERT(this, TaggedIsSmi(start_from)); |
1719 Node* const untagged_start_from = SmiToWord(start_from); | 1717 Node* const untagged_start_from = SmiToWord(start_from); |
1720 index_var.Bind(Select( | 1718 index_var.Bind(Select( |
1721 IntPtrGreaterThanOrEqual(untagged_start_from, IntPtrConstant(0)), | 1719 IntPtrGreaterThanOrEqual(untagged_start_from, IntPtrConstant(0)), |
1722 [=]() { return untagged_start_from; }, | 1720 [=]() { return untagged_start_from; }, |
1723 [=]() { | 1721 [=]() { |
1724 Node* const index = IntPtrAdd(len_var.value(), untagged_start_from); | 1722 Node* const index = IntPtrAdd(len, untagged_start_from); |
1725 return SelectConstant(IntPtrLessThan(index, IntPtrConstant(0)), | 1723 return SelectConstant(IntPtrLessThan(index, IntPtrConstant(0)), |
1726 IntPtrConstant(0), index, | 1724 IntPtrConstant(0), index, |
1727 MachineType::PointerRepresentation()); | 1725 MachineType::PointerRepresentation()); |
1728 }, | 1726 }, |
1729 MachineType::PointerRepresentation())); | 1727 MachineType::PointerRepresentation())); |
1730 | 1728 |
1731 Goto(&select_loop); | 1729 Goto(&select_loop); |
1732 Bind(&select_loop); | 1730 Bind(&select_loop); |
1733 static int32_t kElementsKind[] = { | 1731 static int32_t kElementsKind[] = { |
1734 FAST_SMI_ELEMENTS, FAST_HOLEY_SMI_ELEMENTS, FAST_ELEMENTS, | 1732 FAST_SMI_ELEMENTS, FAST_HOLEY_SMI_ELEMENTS, FAST_ELEMENTS, |
(...skipping 29 matching lines...) Expand all Loading... | |
1764 search_num.Bind(LoadHeapNumberValue(search_element)); | 1762 search_num.Bind(LoadHeapNumberValue(search_element)); |
1765 Goto(&heap_num_loop); | 1763 Goto(&heap_num_loop); |
1766 | 1764 |
1767 Bind(¬_heap_num); | 1765 Bind(¬_heap_num); |
1768 Node* search_type = LoadMapInstanceType(map); | 1766 Node* search_type = LoadMapInstanceType(map); |
1769 GotoIf(IsStringInstanceType(search_type), &string_loop); | 1767 GotoIf(IsStringInstanceType(search_type), &string_loop); |
1770 Goto(&ident_loop); | 1768 Goto(&ident_loop); |
1771 | 1769 |
1772 Bind(&ident_loop); | 1770 Bind(&ident_loop); |
1773 { | 1771 { |
1774 GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()), | 1772 GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false); |
1775 &return_false); | |
1776 Node* element_k = LoadFixedArrayElement(elements, index_var.value()); | 1773 Node* element_k = LoadFixedArrayElement(elements, index_var.value()); |
1777 GotoIf(WordEqual(element_k, search_element), &return_true); | 1774 GotoIf(WordEqual(element_k, search_element), &return_true); |
1778 | 1775 |
1779 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); | 1776 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); |
1780 Goto(&ident_loop); | 1777 Goto(&ident_loop); |
1781 } | 1778 } |
1782 | 1779 |
1783 Bind(&undef_loop); | 1780 Bind(&undef_loop); |
1784 { | 1781 { |
1785 GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()), | 1782 GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false); |
1786 &return_false); | |
1787 Node* element_k = LoadFixedArrayElement(elements, index_var.value()); | 1783 Node* element_k = LoadFixedArrayElement(elements, index_var.value()); |
1788 GotoIf(WordEqual(element_k, UndefinedConstant()), &return_true); | 1784 GotoIf(WordEqual(element_k, UndefinedConstant()), &return_true); |
1789 GotoIf(WordEqual(element_k, TheHoleConstant()), &return_true); | 1785 GotoIf(WordEqual(element_k, TheHoleConstant()), &return_true); |
1790 | 1786 |
1791 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); | 1787 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); |
1792 Goto(&undef_loop); | 1788 Goto(&undef_loop); |
1793 } | 1789 } |
1794 | 1790 |
1795 Bind(&heap_num_loop); | 1791 Bind(&heap_num_loop); |
1796 { | 1792 { |
1797 Label nan_loop(this, &index_var), not_nan_loop(this, &index_var); | 1793 Label nan_loop(this, &index_var), not_nan_loop(this, &index_var); |
1798 BranchIfFloat64IsNaN(search_num.value(), &nan_loop, ¬_nan_loop); | 1794 BranchIfFloat64IsNaN(search_num.value(), &nan_loop, ¬_nan_loop); |
1799 | 1795 |
1800 Bind(¬_nan_loop); | 1796 Bind(¬_nan_loop); |
1801 { | 1797 { |
1802 Label continue_loop(this), not_smi(this); | 1798 Label continue_loop(this), not_smi(this); |
1803 GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()), | 1799 GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false); |
1804 &return_false); | |
1805 Node* element_k = LoadFixedArrayElement(elements, index_var.value()); | 1800 Node* element_k = LoadFixedArrayElement(elements, index_var.value()); |
1806 GotoIfNot(TaggedIsSmi(element_k), ¬_smi); | 1801 GotoIfNot(TaggedIsSmi(element_k), ¬_smi); |
1807 Branch(Float64Equal(search_num.value(), SmiToFloat64(element_k)), | 1802 Branch(Float64Equal(search_num.value(), SmiToFloat64(element_k)), |
1808 &return_true, &continue_loop); | 1803 &return_true, &continue_loop); |
1809 | 1804 |
1810 Bind(¬_smi); | 1805 Bind(¬_smi); |
1811 GotoIfNot(IsHeapNumber(element_k), &continue_loop); | 1806 GotoIfNot(IsHeapNumber(element_k), &continue_loop); |
1812 Branch(Float64Equal(search_num.value(), LoadHeapNumberValue(element_k)), | 1807 Branch(Float64Equal(search_num.value(), LoadHeapNumberValue(element_k)), |
1813 &return_true, &continue_loop); | 1808 &return_true, &continue_loop); |
1814 | 1809 |
1815 Bind(&continue_loop); | 1810 Bind(&continue_loop); |
1816 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); | 1811 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); |
1817 Goto(¬_nan_loop); | 1812 Goto(¬_nan_loop); |
1818 } | 1813 } |
1819 | 1814 |
1820 Bind(&nan_loop); | 1815 Bind(&nan_loop); |
1821 { | 1816 { |
1822 Label continue_loop(this); | 1817 Label continue_loop(this); |
1823 GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()), | 1818 GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false); |
1824 &return_false); | |
1825 Node* element_k = LoadFixedArrayElement(elements, index_var.value()); | 1819 Node* element_k = LoadFixedArrayElement(elements, index_var.value()); |
1826 GotoIf(TaggedIsSmi(element_k), &continue_loop); | 1820 GotoIf(TaggedIsSmi(element_k), &continue_loop); |
1827 GotoIfNot(IsHeapNumber(element_k), &continue_loop); | 1821 GotoIfNot(IsHeapNumber(element_k), &continue_loop); |
1828 BranchIfFloat64IsNaN(LoadHeapNumberValue(element_k), &return_true, | 1822 BranchIfFloat64IsNaN(LoadHeapNumberValue(element_k), &return_true, |
1829 &continue_loop); | 1823 &continue_loop); |
1830 | 1824 |
1831 Bind(&continue_loop); | 1825 Bind(&continue_loop); |
1832 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); | 1826 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); |
1833 Goto(&nan_loop); | 1827 Goto(&nan_loop); |
1834 } | 1828 } |
1835 } | 1829 } |
1836 | 1830 |
1837 Bind(&string_loop); | 1831 Bind(&string_loop); |
1838 { | 1832 { |
1839 Label continue_loop(this); | 1833 Label continue_loop(this); |
1840 GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()), | 1834 GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false); |
1841 &return_false); | |
1842 Node* element_k = LoadFixedArrayElement(elements, index_var.value()); | 1835 Node* element_k = LoadFixedArrayElement(elements, index_var.value()); |
1843 GotoIf(TaggedIsSmi(element_k), &continue_loop); | 1836 GotoIf(TaggedIsSmi(element_k), &continue_loop); |
1844 GotoIfNot(IsStringInstanceType(LoadInstanceType(element_k)), | 1837 GotoIfNot(IsStringInstanceType(LoadInstanceType(element_k)), |
1845 &continue_loop); | 1838 &continue_loop); |
1846 | 1839 |
1847 // TODO(bmeurer): Consider inlining the StringEqual logic here. | 1840 // TODO(bmeurer): Consider inlining the StringEqual logic here. |
1848 Node* result = CallStub(CodeFactory::StringEqual(isolate()), context, | 1841 Node* result = CallStub(CodeFactory::StringEqual(isolate()), context, |
1849 search_element, element_k); | 1842 search_element, element_k); |
1850 Branch(WordEqual(BooleanConstant(true), result), &return_true, | 1843 Branch(WordEqual(BooleanConstant(true), result), &return_true, |
1851 &continue_loop); | 1844 &continue_loop); |
(...skipping 18 matching lines...) Expand all Loading... | |
1870 GotoIfNot(IsHeapNumber(search_element), &return_false); | 1863 GotoIfNot(IsHeapNumber(search_element), &return_false); |
1871 | 1864 |
1872 search_num.Bind(LoadHeapNumberValue(search_element)); | 1865 search_num.Bind(LoadHeapNumberValue(search_element)); |
1873 | 1866 |
1874 BranchIfFloat64IsNaN(search_num.value(), &nan_loop, ¬_nan_loop); | 1867 BranchIfFloat64IsNaN(search_num.value(), &nan_loop, ¬_nan_loop); |
1875 | 1868 |
1876 // Search for HeapNumber | 1869 // Search for HeapNumber |
1877 Bind(¬_nan_loop); | 1870 Bind(¬_nan_loop); |
1878 { | 1871 { |
1879 Label continue_loop(this); | 1872 Label continue_loop(this); |
1880 GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()), | 1873 GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false); |
1881 &return_false); | |
1882 Node* element_k = LoadFixedDoubleArrayElement(elements, index_var.value(), | 1874 Node* element_k = LoadFixedDoubleArrayElement(elements, index_var.value(), |
1883 MachineType::Float64()); | 1875 MachineType::Float64()); |
1884 Branch(Float64Equal(element_k, search_num.value()), &return_true, | 1876 Branch(Float64Equal(element_k, search_num.value()), &return_true, |
1885 &continue_loop); | 1877 &continue_loop); |
1886 Bind(&continue_loop); | 1878 Bind(&continue_loop); |
1887 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); | 1879 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); |
1888 Goto(¬_nan_loop); | 1880 Goto(¬_nan_loop); |
1889 } | 1881 } |
1890 | 1882 |
1891 // Search for NaN | 1883 // Search for NaN |
1892 Bind(&nan_loop); | 1884 Bind(&nan_loop); |
1893 { | 1885 { |
1894 Label continue_loop(this); | 1886 Label continue_loop(this); |
1895 GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()), | 1887 GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false); |
1896 &return_false); | |
1897 Node* element_k = LoadFixedDoubleArrayElement(elements, index_var.value(), | 1888 Node* element_k = LoadFixedDoubleArrayElement(elements, index_var.value(), |
1898 MachineType::Float64()); | 1889 MachineType::Float64()); |
1899 BranchIfFloat64IsNaN(element_k, &return_true, &continue_loop); | 1890 BranchIfFloat64IsNaN(element_k, &return_true, &continue_loop); |
1900 Bind(&continue_loop); | 1891 Bind(&continue_loop); |
1901 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); | 1892 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); |
1902 Goto(&nan_loop); | 1893 Goto(&nan_loop); |
1903 } | 1894 } |
1904 } | 1895 } |
1905 | 1896 |
1906 Bind(&if_holey_doubles); | 1897 Bind(&if_holey_doubles); |
(...skipping 11 matching lines...) Expand all Loading... | |
1918 GotoIfNot(IsHeapNumber(search_element), &return_false); | 1909 GotoIfNot(IsHeapNumber(search_element), &return_false); |
1919 | 1910 |
1920 search_num.Bind(LoadHeapNumberValue(search_element)); | 1911 search_num.Bind(LoadHeapNumberValue(search_element)); |
1921 | 1912 |
1922 BranchIfFloat64IsNaN(search_num.value(), &nan_loop, ¬_nan_loop); | 1913 BranchIfFloat64IsNaN(search_num.value(), &nan_loop, ¬_nan_loop); |
1923 | 1914 |
1924 // Search for HeapNumber | 1915 // Search for HeapNumber |
1925 Bind(¬_nan_loop); | 1916 Bind(¬_nan_loop); |
1926 { | 1917 { |
1927 Label continue_loop(this); | 1918 Label continue_loop(this); |
1928 GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()), | 1919 GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false); |
1929 &return_false); | |
1930 | 1920 |
1931 // Load double value or continue if it contains a double hole. | 1921 // Load double value or continue if it contains a double hole. |
1932 Node* element_k = LoadFixedDoubleArrayElement( | 1922 Node* element_k = LoadFixedDoubleArrayElement( |
1933 elements, index_var.value(), MachineType::Float64(), 0, | 1923 elements, index_var.value(), MachineType::Float64(), 0, |
1934 CodeStubAssembler::INTPTR_PARAMETERS, &continue_loop); | 1924 CodeStubAssembler::INTPTR_PARAMETERS, &continue_loop); |
1935 | 1925 |
1936 Branch(Float64Equal(element_k, search_num.value()), &return_true, | 1926 Branch(Float64Equal(element_k, search_num.value()), &return_true, |
1937 &continue_loop); | 1927 &continue_loop); |
1938 Bind(&continue_loop); | 1928 Bind(&continue_loop); |
1939 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); | 1929 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); |
1940 Goto(¬_nan_loop); | 1930 Goto(¬_nan_loop); |
1941 } | 1931 } |
1942 | 1932 |
1943 // Search for NaN | 1933 // Search for NaN |
1944 Bind(&nan_loop); | 1934 Bind(&nan_loop); |
1945 { | 1935 { |
1946 Label continue_loop(this); | 1936 Label continue_loop(this); |
1947 GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()), | 1937 GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false); |
1948 &return_false); | |
1949 | 1938 |
1950 // Load double value or continue if it contains a double hole. | 1939 // Load double value or continue if it contains a double hole. |
1951 Node* element_k = LoadFixedDoubleArrayElement( | 1940 Node* element_k = LoadFixedDoubleArrayElement( |
1952 elements, index_var.value(), MachineType::Float64(), 0, | 1941 elements, index_var.value(), MachineType::Float64(), 0, |
1953 CodeStubAssembler::INTPTR_PARAMETERS, &continue_loop); | 1942 CodeStubAssembler::INTPTR_PARAMETERS, &continue_loop); |
1954 | 1943 |
1955 BranchIfFloat64IsNaN(element_k, &return_true, &continue_loop); | 1944 BranchIfFloat64IsNaN(element_k, &return_true, &continue_loop); |
1956 Bind(&continue_loop); | 1945 Bind(&continue_loop); |
1957 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); | 1946 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); |
1958 Goto(&nan_loop); | 1947 Goto(&nan_loop); |
1959 } | 1948 } |
1960 | 1949 |
1961 // Search for the Hole | 1950 // Search for the Hole |
1962 Bind(&hole_loop); | 1951 Bind(&hole_loop); |
1963 { | 1952 { |
1964 GotoIfNot(UintPtrLessThan(index_var.value(), len_var.value()), | 1953 GotoIfNot(UintPtrLessThan(index_var.value(), len), &return_false); |
1965 &return_false); | |
1966 | 1954 |
1967 // Check if the element is a double hole, but don't load it. | 1955 // Check if the element is a double hole, but don't load it. |
1968 LoadFixedDoubleArrayElement( | 1956 LoadFixedDoubleArrayElement( |
1969 elements, index_var.value(), MachineType::None(), 0, | 1957 elements, index_var.value(), MachineType::None(), 0, |
1970 CodeStubAssembler::INTPTR_PARAMETERS, &return_true); | 1958 CodeStubAssembler::INTPTR_PARAMETERS, &return_true); |
1971 | 1959 |
1972 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); | 1960 index_var.Bind(IntPtrAdd(index_var.value(), IntPtrConstant(1))); |
1973 Goto(&hole_loop); | 1961 Goto(&hole_loop); |
1974 } | 1962 } |
1975 } | 1963 } |
(...skipping 875 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2851 { | 2839 { |
2852 Node* message = assembler.SmiConstant(MessageTemplate::kDetachedOperation); | 2840 Node* message = assembler.SmiConstant(MessageTemplate::kDetachedOperation); |
2853 assembler.CallRuntime(Runtime::kThrowTypeError, context, message, | 2841 assembler.CallRuntime(Runtime::kThrowTypeError, context, message, |
2854 assembler.HeapConstant(operation)); | 2842 assembler.HeapConstant(operation)); |
2855 assembler.Unreachable(); | 2843 assembler.Unreachable(); |
2856 } | 2844 } |
2857 } | 2845 } |
2858 | 2846 |
2859 } // namespace internal | 2847 } // namespace internal |
2860 } // namespace v8 | 2848 } // namespace v8 |
OLD | NEW |