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/elements.h" | 9 #include "src/elements.h" |
10 | 10 |
(...skipping 1721 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1732 | 1732 |
1733 assembler->Bind(&return_false); | 1733 assembler->Bind(&return_false); |
1734 assembler->Return(assembler->BooleanConstant(false)); | 1734 assembler->Return(assembler->BooleanConstant(false)); |
1735 | 1735 |
1736 assembler->Bind(&call_runtime); | 1736 assembler->Bind(&call_runtime); |
1737 assembler->Return(assembler->CallRuntime(Runtime::kArrayIncludes_Slow, | 1737 assembler->Return(assembler->CallRuntime(Runtime::kArrayIncludes_Slow, |
1738 context, array, search_element, | 1738 context, array, search_element, |
1739 start_from)); | 1739 start_from)); |
1740 } | 1740 } |
1741 | 1741 |
| 1742 void Builtins::Generate_ArrayIndexOf(CodeStubAssembler* assembler) { |
| 1743 typedef compiler::Node Node; |
| 1744 typedef CodeStubAssembler::Label Label; |
| 1745 typedef CodeStubAssembler::Variable Variable; |
| 1746 |
| 1747 Node* array = assembler->Parameter(0); |
| 1748 Node* search_element = assembler->Parameter(1); |
| 1749 Node* start_from = assembler->Parameter(2); |
| 1750 Node* context = assembler->Parameter(3 + 2); |
| 1751 |
| 1752 Node* int32_zero = assembler->Int32Constant(0); |
| 1753 Node* int32_one = assembler->Int32Constant(1); |
| 1754 |
| 1755 Node* undefined = assembler->UndefinedConstant(); |
| 1756 Node* heap_number_map = assembler->HeapNumberMapConstant(); |
| 1757 |
| 1758 Variable len_var(assembler, MachineRepresentation::kWord32), |
| 1759 index_var(assembler, MachineRepresentation::kWord32), |
| 1760 start_from_var(assembler, MachineRepresentation::kWord32); |
| 1761 |
| 1762 Label init_k(assembler), return_found(assembler), return_not_found(assembler), |
| 1763 call_runtime(assembler); |
| 1764 |
| 1765 Label init_len(assembler); |
| 1766 |
| 1767 index_var.Bind(int32_zero); |
| 1768 len_var.Bind(int32_zero); |
| 1769 |
| 1770 // Take slow path if not a JSArray, if retrieving elements requires |
| 1771 // traversing prototype, or if access checks are required. |
| 1772 assembler->BranchIfFastJSArray(array, context, &init_len, &call_runtime); |
| 1773 |
| 1774 assembler->Bind(&init_len); |
| 1775 { |
| 1776 // Handle case where JSArray length is not an Smi in the runtime |
| 1777 Node* len = assembler->LoadObjectField(array, JSArray::kLengthOffset); |
| 1778 assembler->GotoUnless(assembler->WordIsSmi(len), &call_runtime); |
| 1779 |
| 1780 len_var.Bind(assembler->SmiToWord(len)); |
| 1781 assembler->Branch(assembler->Word32Equal(len_var.value(), int32_zero), |
| 1782 &return_not_found, &init_k); |
| 1783 } |
| 1784 |
| 1785 assembler->Bind(&init_k); |
| 1786 { |
| 1787 Label done(assembler), init_k_smi(assembler), init_k_heap_num(assembler), |
| 1788 init_k_zero(assembler), init_k_n(assembler); |
| 1789 Callable call_to_integer = CodeFactory::ToInteger(assembler->isolate()); |
| 1790 Node* tagged_n = assembler->CallStub(call_to_integer, context, start_from); |
| 1791 |
| 1792 assembler->Branch(assembler->WordIsSmi(tagged_n), &init_k_smi, |
| 1793 &init_k_heap_num); |
| 1794 |
| 1795 assembler->Bind(&init_k_smi); |
| 1796 { |
| 1797 start_from_var.Bind(assembler->SmiToWord32(tagged_n)); |
| 1798 assembler->Goto(&init_k_n); |
| 1799 } |
| 1800 |
| 1801 assembler->Bind(&init_k_heap_num); |
| 1802 { |
| 1803 Label do_return_not_found(assembler); |
| 1804 Node* fp_len = assembler->ChangeInt32ToFloat64(len_var.value()); |
| 1805 Node* fp_n = assembler->LoadHeapNumberValue(tagged_n); |
| 1806 assembler->GotoIf(assembler->Float64GreaterThanOrEqual(fp_n, fp_len), |
| 1807 &do_return_not_found); |
| 1808 start_from_var.Bind(assembler->TruncateFloat64ToWord32(fp_n)); |
| 1809 assembler->Goto(&init_k_n); |
| 1810 |
| 1811 assembler->Bind(&do_return_not_found); |
| 1812 { |
| 1813 index_var.Bind(int32_zero); |
| 1814 assembler->Goto(&return_not_found); |
| 1815 } |
| 1816 } |
| 1817 |
| 1818 assembler->Bind(&init_k_n); |
| 1819 { |
| 1820 Label if_positive(assembler), if_negative(assembler), done(assembler); |
| 1821 assembler->Branch( |
| 1822 assembler->Int32LessThan(start_from_var.value(), int32_zero), |
| 1823 &if_negative, &if_positive); |
| 1824 |
| 1825 assembler->Bind(&if_positive); |
| 1826 { |
| 1827 index_var.Bind(start_from_var.value()); |
| 1828 assembler->Goto(&done); |
| 1829 } |
| 1830 |
| 1831 assembler->Bind(&if_negative); |
| 1832 { |
| 1833 index_var.Bind( |
| 1834 assembler->Int32Add(len_var.value(), start_from_var.value())); |
| 1835 assembler->Branch( |
| 1836 assembler->Int32LessThan(index_var.value(), int32_zero), |
| 1837 &init_k_zero, &done); |
| 1838 } |
| 1839 |
| 1840 assembler->Bind(&init_k_zero); |
| 1841 { |
| 1842 index_var.Bind(int32_zero); |
| 1843 assembler->Goto(&done); |
| 1844 } |
| 1845 |
| 1846 assembler->Bind(&done); |
| 1847 } |
| 1848 } |
| 1849 |
| 1850 static int32_t kElementsKind[] = { |
| 1851 FAST_SMI_ELEMENTS, FAST_HOLEY_SMI_ELEMENTS, FAST_ELEMENTS, |
| 1852 FAST_HOLEY_ELEMENTS, FAST_DOUBLE_ELEMENTS, FAST_HOLEY_DOUBLE_ELEMENTS, |
| 1853 }; |
| 1854 |
| 1855 Label if_smiorobjects(assembler), if_packed_doubles(assembler), |
| 1856 if_holey_doubles(assembler); |
| 1857 Label* element_kind_handlers[] = {&if_smiorobjects, &if_smiorobjects, |
| 1858 &if_smiorobjects, &if_smiorobjects, |
| 1859 &if_packed_doubles, &if_holey_doubles}; |
| 1860 |
| 1861 Node* map = assembler->LoadMap(array); |
| 1862 Node* bit_field2 = assembler->LoadMapBitField2(map); |
| 1863 Node* elements_kind = |
| 1864 assembler->BitFieldDecode<Map::ElementsKindBits>(bit_field2); |
| 1865 Node* elements = assembler->LoadElements(array); |
| 1866 assembler->Switch(elements_kind, &return_not_found, kElementsKind, |
| 1867 element_kind_handlers, arraysize(kElementsKind)); |
| 1868 |
| 1869 assembler->Bind(&if_smiorobjects); |
| 1870 { |
| 1871 Variable search_num(assembler, MachineRepresentation::kFloat64); |
| 1872 Label ident_loop(assembler, &index_var), |
| 1873 heap_num_loop(assembler, &search_num), |
| 1874 string_loop(assembler, &index_var), simd_loop(assembler), |
| 1875 undef_loop(assembler, &index_var), not_smi(assembler), |
| 1876 not_heap_num(assembler); |
| 1877 |
| 1878 assembler->GotoUnless(assembler->WordIsSmi(search_element), ¬_smi); |
| 1879 search_num.Bind(assembler->SmiToFloat64(search_element)); |
| 1880 assembler->Goto(&heap_num_loop); |
| 1881 |
| 1882 assembler->Bind(¬_smi); |
| 1883 assembler->GotoIf(assembler->WordEqual(search_element, undefined), |
| 1884 &undef_loop); |
| 1885 Node* map = assembler->LoadMap(search_element); |
| 1886 assembler->GotoIf(assembler->WordNotEqual(map, heap_number_map), |
| 1887 ¬_heap_num); |
| 1888 search_num.Bind(assembler->LoadHeapNumberValue(search_element)); |
| 1889 assembler->Goto(&heap_num_loop); |
| 1890 |
| 1891 assembler->Bind(¬_heap_num); |
| 1892 Node* search_type = assembler->LoadMapInstanceType(map); |
| 1893 assembler->GotoIf( |
| 1894 assembler->Int32LessThan( |
| 1895 search_type, assembler->Int32Constant(FIRST_NONSTRING_TYPE)), |
| 1896 &string_loop); |
| 1897 assembler->GotoIf( |
| 1898 assembler->WordEqual(search_type, |
| 1899 assembler->Int32Constant(SIMD128_VALUE_TYPE)), |
| 1900 &simd_loop); |
| 1901 assembler->Goto(&ident_loop); |
| 1902 |
| 1903 assembler->Bind(&ident_loop); |
| 1904 { |
| 1905 assembler->GotoUnless( |
| 1906 assembler->Int32LessThan(index_var.value(), len_var.value()), |
| 1907 &return_not_found); |
| 1908 Node* element_k = |
| 1909 assembler->LoadFixedArrayElement(elements, index_var.value()); |
| 1910 assembler->GotoIf(assembler->WordEqual(element_k, search_element), |
| 1911 &return_found); |
| 1912 |
| 1913 index_var.Bind(assembler->Int32Add(index_var.value(), int32_one)); |
| 1914 assembler->Goto(&ident_loop); |
| 1915 } |
| 1916 |
| 1917 assembler->Bind(&undef_loop); |
| 1918 { |
| 1919 assembler->GotoUnless( |
| 1920 assembler->Int32LessThan(index_var.value(), len_var.value()), |
| 1921 &return_not_found); |
| 1922 Node* element_k = |
| 1923 assembler->LoadFixedArrayElement(elements, index_var.value()); |
| 1924 assembler->GotoIf(assembler->WordEqual(element_k, undefined), |
| 1925 &return_found); |
| 1926 |
| 1927 index_var.Bind(assembler->Int32Add(index_var.value(), int32_one)); |
| 1928 assembler->Goto(&undef_loop); |
| 1929 } |
| 1930 |
| 1931 assembler->Bind(&heap_num_loop); |
| 1932 { |
| 1933 Label not_nan_loop(assembler, &index_var); |
| 1934 assembler->BranchIfFloat64IsNaN(search_num.value(), &return_not_found, |
| 1935 ¬_nan_loop); |
| 1936 |
| 1937 assembler->Bind(¬_nan_loop); |
| 1938 { |
| 1939 Label continue_loop(assembler), not_smi(assembler); |
| 1940 assembler->GotoUnless( |
| 1941 assembler->Int32LessThan(index_var.value(), len_var.value()), |
| 1942 &return_not_found); |
| 1943 Node* element_k = |
| 1944 assembler->LoadFixedArrayElement(elements, index_var.value()); |
| 1945 assembler->GotoUnless(assembler->WordIsSmi(element_k), ¬_smi); |
| 1946 assembler->Branch( |
| 1947 assembler->Float64Equal(search_num.value(), |
| 1948 assembler->SmiToFloat64(element_k)), |
| 1949 &return_found, &continue_loop); |
| 1950 |
| 1951 assembler->Bind(¬_smi); |
| 1952 assembler->GotoIf(assembler->WordNotEqual(assembler->LoadMap(element_k), |
| 1953 heap_number_map), |
| 1954 &continue_loop); |
| 1955 assembler->BranchIfFloat64Equal( |
| 1956 search_num.value(), assembler->LoadHeapNumberValue(element_k), |
| 1957 &return_found, &continue_loop); |
| 1958 |
| 1959 assembler->Bind(&continue_loop); |
| 1960 index_var.Bind(assembler->Int32Add(index_var.value(), int32_one)); |
| 1961 assembler->Goto(¬_nan_loop); |
| 1962 } |
| 1963 } |
| 1964 |
| 1965 assembler->Bind(&string_loop); |
| 1966 { |
| 1967 Label continue_loop(assembler); |
| 1968 assembler->GotoUnless( |
| 1969 assembler->Int32LessThan(index_var.value(), len_var.value()), |
| 1970 &return_not_found); |
| 1971 Node* element_k = |
| 1972 assembler->LoadFixedArrayElement(elements, index_var.value()); |
| 1973 assembler->GotoIf(assembler->WordIsSmi(element_k), &continue_loop); |
| 1974 assembler->GotoUnless(assembler->Int32LessThan( |
| 1975 assembler->LoadInstanceType(element_k), |
| 1976 assembler->Int32Constant(FIRST_NONSTRING_TYPE)), |
| 1977 &continue_loop); |
| 1978 |
| 1979 // TODO(bmeurer): Consider inlining the StringEqual logic here. |
| 1980 Callable callable = CodeFactory::StringEqual(assembler->isolate()); |
| 1981 Node* result = |
| 1982 assembler->CallStub(callable, context, search_element, element_k); |
| 1983 assembler->Branch( |
| 1984 assembler->WordEqual(assembler->BooleanConstant(true), result), |
| 1985 &return_found, &continue_loop); |
| 1986 |
| 1987 assembler->Bind(&continue_loop); |
| 1988 index_var.Bind(assembler->Int32Add(index_var.value(), int32_one)); |
| 1989 assembler->Goto(&string_loop); |
| 1990 } |
| 1991 |
| 1992 assembler->Bind(&simd_loop); |
| 1993 { |
| 1994 Label continue_loop(assembler, &index_var), |
| 1995 loop_body(assembler, &index_var); |
| 1996 Node* map = assembler->LoadMap(search_element); |
| 1997 |
| 1998 assembler->Goto(&loop_body); |
| 1999 assembler->Bind(&loop_body); |
| 2000 assembler->GotoUnless( |
| 2001 assembler->Int32LessThan(index_var.value(), len_var.value()), |
| 2002 &return_not_found); |
| 2003 |
| 2004 Node* element_k = |
| 2005 assembler->LoadFixedArrayElement(elements, index_var.value()); |
| 2006 assembler->GotoIf(assembler->WordIsSmi(element_k), &continue_loop); |
| 2007 |
| 2008 Node* map_k = assembler->LoadMap(element_k); |
| 2009 assembler->BranchIfSimd128Equal(search_element, map, element_k, map_k, |
| 2010 &return_found, &continue_loop); |
| 2011 |
| 2012 assembler->Bind(&continue_loop); |
| 2013 index_var.Bind(assembler->Int32Add(index_var.value(), int32_one)); |
| 2014 assembler->Goto(&loop_body); |
| 2015 } |
| 2016 } |
| 2017 |
| 2018 assembler->Bind(&if_packed_doubles); |
| 2019 { |
| 2020 Label not_nan_loop(assembler, &index_var), search_notnan(assembler); |
| 2021 Variable search_num(assembler, MachineRepresentation::kFloat64); |
| 2022 |
| 2023 assembler->GotoUnless(assembler->WordIsSmi(search_element), &search_notnan); |
| 2024 search_num.Bind(assembler->SmiToFloat64(search_element)); |
| 2025 assembler->Goto(¬_nan_loop); |
| 2026 |
| 2027 assembler->Bind(&search_notnan); |
| 2028 assembler->GotoIf(assembler->WordNotEqual( |
| 2029 assembler->LoadMap(search_element), heap_number_map), |
| 2030 &return_not_found); |
| 2031 |
| 2032 search_num.Bind(assembler->LoadHeapNumberValue(search_element)); |
| 2033 |
| 2034 assembler->BranchIfFloat64IsNaN(search_num.value(), &return_not_found, |
| 2035 ¬_nan_loop); |
| 2036 |
| 2037 // Search for HeapNumber |
| 2038 assembler->Bind(¬_nan_loop); |
| 2039 { |
| 2040 Label continue_loop(assembler); |
| 2041 assembler->GotoUnless( |
| 2042 assembler->Int32LessThan(index_var.value(), len_var.value()), |
| 2043 &return_not_found); |
| 2044 Node* element_k = assembler->LoadFixedDoubleArrayElement( |
| 2045 elements, index_var.value(), MachineType::Float64()); |
| 2046 assembler->BranchIfFloat64Equal(element_k, search_num.value(), |
| 2047 &return_found, &continue_loop); |
| 2048 assembler->Bind(&continue_loop); |
| 2049 index_var.Bind(assembler->Int32Add(index_var.value(), int32_one)); |
| 2050 assembler->Goto(¬_nan_loop); |
| 2051 } |
| 2052 } |
| 2053 |
| 2054 assembler->Bind(&if_holey_doubles); |
| 2055 { |
| 2056 Label not_nan_loop(assembler, &index_var), search_notnan(assembler); |
| 2057 Variable search_num(assembler, MachineRepresentation::kFloat64); |
| 2058 |
| 2059 assembler->GotoUnless(assembler->WordIsSmi(search_element), &search_notnan); |
| 2060 search_num.Bind(assembler->SmiToFloat64(search_element)); |
| 2061 assembler->Goto(¬_nan_loop); |
| 2062 |
| 2063 assembler->Bind(&search_notnan); |
| 2064 assembler->GotoIf(assembler->WordNotEqual( |
| 2065 assembler->LoadMap(search_element), heap_number_map), |
| 2066 &return_not_found); |
| 2067 |
| 2068 search_num.Bind(assembler->LoadHeapNumberValue(search_element)); |
| 2069 |
| 2070 assembler->BranchIfFloat64IsNaN(search_num.value(), &return_not_found, |
| 2071 ¬_nan_loop); |
| 2072 |
| 2073 // Search for HeapNumber |
| 2074 assembler->Bind(¬_nan_loop); |
| 2075 { |
| 2076 Label continue_loop(assembler); |
| 2077 assembler->GotoUnless( |
| 2078 assembler->Int32LessThan(index_var.value(), len_var.value()), |
| 2079 &return_not_found); |
| 2080 |
| 2081 if (kPointerSize == kDoubleSize) { |
| 2082 Node* element = assembler->LoadFixedDoubleArrayElement( |
| 2083 elements, index_var.value(), MachineType::Uint64()); |
| 2084 Node* the_hole = assembler->Int64Constant(kHoleNanInt64); |
| 2085 assembler->GotoIf(assembler->Word64Equal(element, the_hole), |
| 2086 &continue_loop); |
| 2087 } else { |
| 2088 Node* element_upper = assembler->LoadFixedDoubleArrayElement( |
| 2089 elements, index_var.value(), MachineType::Uint32(), |
| 2090 kIeeeDoubleExponentWordOffset); |
| 2091 assembler->GotoIf( |
| 2092 assembler->Word32Equal(element_upper, |
| 2093 assembler->Int32Constant(kHoleNanUpper32)), |
| 2094 &continue_loop); |
| 2095 } |
| 2096 |
| 2097 Node* element_k = assembler->LoadFixedDoubleArrayElement( |
| 2098 elements, index_var.value(), MachineType::Float64()); |
| 2099 assembler->BranchIfFloat64Equal(element_k, search_num.value(), |
| 2100 &return_found, &continue_loop); |
| 2101 assembler->Bind(&continue_loop); |
| 2102 index_var.Bind(assembler->Int32Add(index_var.value(), int32_one)); |
| 2103 assembler->Goto(¬_nan_loop); |
| 2104 } |
| 2105 } |
| 2106 |
| 2107 assembler->Bind(&return_found); |
| 2108 assembler->Return(assembler->ChangeInt32ToTagged(index_var.value())); |
| 2109 |
| 2110 assembler->Bind(&return_not_found); |
| 2111 assembler->Return(assembler->NumberConstant(-1)); |
| 2112 |
| 2113 assembler->Bind(&call_runtime); |
| 2114 assembler->Return(assembler->CallRuntime(Runtime::kArrayIndexOf, context, |
| 2115 array, search_element, start_from)); |
| 2116 } |
| 2117 |
1742 } // namespace internal | 2118 } // namespace internal |
1743 } // namespace v8 | 2119 } // namespace v8 |
OLD | NEW |