Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(420)

Side by Side Diff: src/builtins/builtins-array-gen.cc

Issue 2881763003: [array] Simplify index calculation in Array.p.indexOf (Closed)
Patch Set: Rebase and address comments Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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(&not_heap_num); 1768 BIND(&not_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 &not_nan_loop); 1788 &not_nan_loop);
1825 1789
1826 BIND(&not_nan_loop); 1790 BIND(&not_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), &not_smi); 1796 GotoIfNot(TaggedIsSmi(element_k), &not_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(&not_smi); 1800 BIND(&not_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(&not_nan_loop); 1807 Goto(&not_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(&not_nan_loop); 1840 Goto(&not_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, &not_nan_loop); 1847 BranchIfFloat64IsNaN(search_num.value(), &return_not_found, &not_nan_loop);
1883 1848
1884 // Search for HeapNumber 1849 // Search for HeapNumber
1885 BIND(&not_nan_loop); 1850 BIND(&not_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(&not_nan_loop); 1859 Goto(&not_nan_loop);
1895 } 1860 }
1896 } 1861 }
1897 1862
(...skipping 10 matching lines...) Expand all
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, &not_nan_loop); 1877 BranchIfFloat64IsNaN(search_num.value(), &return_not_found, &not_nan_loop);
1913 1878
1914 // Search for HeapNumber 1879 // Search for HeapNumber
1915 BIND(&not_nan_loop); 1880 BIND(&not_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(&not_nan_loop); 1895 Goto(&not_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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698