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

Side by Side Diff: src/code-stubs.cc

Issue 2670843002: [stubs] Also port the CallICStub to CSA. (Closed)
Patch Set: Introduce FullCodeGenerator::IntFromSlot. Created 3 years, 10 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 | « src/code-stubs.h ('k') | src/full-codegen/arm/full-codegen-arm.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 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/code-stubs.h" 5 #include "src/code-stubs.h"
6 6
7 #include <sstream> 7 #include <sstream>
8 8
9 #include "src/ast/ast.h" 9 #include "src/ast/ast.h"
10 #include "src/bootstrapper.h" 10 #include "src/bootstrapper.h"
(...skipping 1741 matching lines...) Expand 10 before | Expand all | Expand 10 after
1752 OFStream os(stdout); 1752 OFStream os(stdout);
1753 os << "["; 1753 os << "[";
1754 PrintBaseName(os); 1754 PrintBaseName(os);
1755 os << ": " << from << "=>" << to << "]" << std::endl; 1755 os << ": " << from << "=>" << to << "]" << std::endl;
1756 } 1756 }
1757 1757
1758 void CallICStub::PrintState(std::ostream& os) const { // NOLINT 1758 void CallICStub::PrintState(std::ostream& os) const { // NOLINT
1759 os << convert_mode() << ", " << tail_call_mode(); 1759 os << convert_mode() << ", " << tail_call_mode();
1760 } 1760 }
1761 1761
1762 void CallICStub::GenerateAssembly(compiler::CodeAssemblerState* state) const {
1763 typedef CodeStubAssembler::Label Label;
1764 typedef compiler::Node Node;
1765 CodeStubAssembler assembler(state);
1766
1767 Node* context = assembler.Parameter(Descriptor::kContext);
1768 Node* target = assembler.Parameter(Descriptor::kTarget);
1769 Node* argc = assembler.Parameter(Descriptor::kActualArgumentsCount);
1770 Node* slot = assembler.Parameter(Descriptor::kSlot);
1771 Node* vector = assembler.Parameter(Descriptor::kVector);
1772
1773 // TODO(bmeurer): The slot should actually be an IntPtr, but TurboFan's
1774 // SimplifiedLowering cannot deal with IntPtr machine type properly yet.
1775 slot = assembler.ChangeInt32ToIntPtr(slot);
1776
1777 // Static checks to assert it is safe to examine the type feedback element.
1778 // We don't know that we have a weak cell. We might have a private symbol
1779 // or an AllocationSite, but the memory is safe to examine.
1780 // AllocationSite::kTransitionInfoOffset - contains a Smi or pointer to
1781 // FixedArray.
1782 // WeakCell::kValueOffset - contains a JSFunction or Smi(0)
1783 // Symbol::kHashFieldSlot - if the low bit is 1, then the hash is not
1784 // computed, meaning that it can't appear to be a pointer. If the low bit is
1785 // 0, then hash is computed, but the 0 bit prevents the field from appearing
1786 // to be a pointer.
1787 STATIC_ASSERT(WeakCell::kSize >= kPointerSize);
1788 STATIC_ASSERT(AllocationSite::kTransitionInfoOffset ==
1789 WeakCell::kValueOffset &&
1790 WeakCell::kValueOffset == Symbol::kHashFieldSlot);
1791
1792 // Increment the call count.
1793 // TODO(bmeurer): Would it be beneficial to use Int32Add on 64-bit?
1794 assembler.Comment("increment call count");
1795 Node* call_count =
1796 assembler.LoadFixedArrayElement(vector, slot, 1 * kPointerSize);
1797 Node* new_count = assembler.SmiAdd(call_count, assembler.SmiConstant(1));
1798 // Count is Smi, so we don't need a write barrier.
1799 assembler.StoreFixedArrayElement(vector, slot, new_count, SKIP_WRITE_BARRIER,
1800 1 * kPointerSize);
1801
1802 Label call_function(&assembler), extra_checks(&assembler), call(&assembler);
1803
1804 // The checks. First, does function match the recorded monomorphic target?
1805 Node* feedback_element = assembler.LoadFixedArrayElement(vector, slot);
1806 Node* feedback_value = assembler.LoadWeakCellValueUnchecked(feedback_element);
1807 Node* is_monomorphic = assembler.WordEqual(target, feedback_value);
1808 assembler.GotoUnless(is_monomorphic, &extra_checks);
1809
1810 // The compare above could have been a SMI/SMI comparison. Guard against
1811 // this convincing us that we have a monomorphic JSFunction.
1812 Node* is_smi = assembler.TaggedIsSmi(target);
1813 assembler.Branch(is_smi, &extra_checks, &call_function);
1814
1815 assembler.Bind(&call_function);
1816 {
1817 // Call using CallFunction builtin.
1818 Callable callable =
1819 CodeFactory::CallFunction(isolate(), convert_mode(), tail_call_mode());
1820 assembler.TailCallStub(callable, context, target, argc);
1821 }
1822
1823 assembler.Bind(&extra_checks);
1824 {
1825 Label check_initialized(&assembler), mark_megamorphic(&assembler),
1826 create_allocation_site(&assembler, Label::kDeferred),
1827 create_weak_cell(&assembler, Label::kDeferred);
1828
1829 assembler.Comment("check if megamorphic");
1830 // Check if it is a megamorphic target.
1831 Node* is_megamorphic = assembler.WordEqual(
1832 feedback_element,
1833 assembler.HeapConstant(
1834 TypeFeedbackVector::MegamorphicSentinel(isolate())));
1835 assembler.GotoIf(is_megamorphic, &call);
1836
1837 assembler.Comment("check if it is an allocation site");
1838 assembler.GotoUnless(
1839 assembler.IsAllocationSiteMap(assembler.LoadMap(feedback_element)),
1840 &check_initialized);
1841
1842 // If it is not the Array() function, mark megamorphic.
1843 Node* context_slot = assembler.LoadContextElement(
1844 assembler.LoadNativeContext(context), Context::ARRAY_FUNCTION_INDEX);
1845 Node* is_array_function = assembler.WordEqual(context_slot, target);
1846 assembler.GotoUnless(is_array_function, &mark_megamorphic);
1847
1848 // Call ArrayConstructorStub.
1849 Callable callable = CodeFactory::ArrayConstructor(isolate());
1850 assembler.TailCallStub(callable, context, target, target, argc,
1851 feedback_element);
1852
1853 assembler.Bind(&check_initialized);
1854 {
1855 assembler.Comment("check if uninitialized");
1856 // Check if it is uninitialized target first.
1857 Node* is_uninitialized = assembler.WordEqual(
1858 feedback_element,
1859 assembler.HeapConstant(
1860 TypeFeedbackVector::UninitializedSentinel(isolate())));
1861 assembler.GotoUnless(is_uninitialized, &mark_megamorphic);
1862
1863 assembler.Comment("handle unitinitialized");
1864 // If it is not a JSFunction mark it as megamorphic.
1865 Node* is_smi = assembler.TaggedIsSmi(target);
1866 assembler.GotoIf(is_smi, &mark_megamorphic);
1867
1868 // Check if function is an object of JSFunction type.
1869 Node* is_js_function = assembler.IsJSFunction(target);
1870 assembler.GotoUnless(is_js_function, &mark_megamorphic);
1871
1872 // Check if it is the Array() function.
1873 Node* context_slot = assembler.LoadContextElement(
1874 assembler.LoadNativeContext(context), Context::ARRAY_FUNCTION_INDEX);
1875 Node* is_array_function = assembler.WordEqual(context_slot, target);
1876 assembler.GotoIf(is_array_function, &create_allocation_site);
1877
1878 // Check if the function belongs to the same native context.
1879 Node* native_context = assembler.LoadNativeContext(
1880 assembler.LoadObjectField(target, JSFunction::kContextOffset));
1881 Node* is_same_native_context = assembler.WordEqual(
1882 native_context, assembler.LoadNativeContext(context));
1883 assembler.Branch(is_same_native_context, &create_weak_cell,
1884 &mark_megamorphic);
1885 }
1886
1887 assembler.Bind(&create_weak_cell);
1888 {
1889 // Wrap the {target} in a WeakCell and remember it.
1890 assembler.Comment("create weak cell");
1891 assembler.CreateWeakCellInFeedbackVector(vector, assembler.SmiTag(slot),
1892 target);
1893
1894 // Call using CallFunction builtin.
1895 assembler.Goto(&call_function);
1896 }
1897
1898 assembler.Bind(&create_allocation_site);
1899 {
1900 // Create an AllocationSite for the {target}.
1901 assembler.Comment("create allocation site");
1902 assembler.CreateAllocationSiteInFeedbackVector(vector,
1903 assembler.SmiTag(slot));
1904
1905 // Call using CallFunction builtin. CallICs have a PREMONOMORPHIC state.
1906 // They start collecting feedback only when a call is executed the second
1907 // time. So, do not pass any feedback here.
1908 assembler.Goto(&call_function);
1909 }
1910
1911 assembler.Bind(&mark_megamorphic);
1912 {
1913 // Mark it as a megamorphic.
1914 // MegamorphicSentinel is created as a part of Heap::InitialObjects
1915 // and will not move during a GC. So it is safe to skip write barrier.
1916 DCHECK(Heap::RootIsImmortalImmovable(Heap::kmegamorphic_symbolRootIndex));
1917 assembler.StoreFixedArrayElement(
1918 vector, slot, assembler.HeapConstant(
1919 TypeFeedbackVector::MegamorphicSentinel(isolate())),
1920 SKIP_WRITE_BARRIER);
1921 assembler.Goto(&call);
1922 }
1923 }
1924
1925 assembler.Bind(&call);
1926 {
1927 // Call using call builtin.
1928 assembler.Comment("call using Call builtin");
1929 Callable callable_call =
1930 CodeFactory::Call(isolate(), convert_mode(), tail_call_mode());
1931 assembler.TailCallStub(callable_call, context, target, argc);
1932 }
1933 }
1934
1762 void CallICTrampolineStub::PrintState(std::ostream& os) const { // NOLINT 1935 void CallICTrampolineStub::PrintState(std::ostream& os) const { // NOLINT
1763 os << convert_mode() << ", " << tail_call_mode(); 1936 os << convert_mode() << ", " << tail_call_mode();
1764 } 1937 }
1765 1938
1766 void CallICTrampolineStub::GenerateAssembly( 1939 void CallICTrampolineStub::GenerateAssembly(
1767 compiler::CodeAssemblerState* state) const { 1940 compiler::CodeAssemblerState* state) const {
1768 typedef compiler::Node Node; 1941 typedef compiler::Node Node;
1769 CodeStubAssembler assembler(state); 1942 CodeStubAssembler assembler(state);
1770 1943
1771 Node* context = assembler.Parameter(Descriptor::kContext); 1944 Node* context = assembler.Parameter(Descriptor::kContext);
1772 Node* target = assembler.Parameter(Descriptor::kFunction); 1945 Node* target = assembler.Parameter(Descriptor::kTarget);
1773 Node* argc = assembler.Parameter(Descriptor::kActualArgumentsCount); 1946 Node* argc = assembler.Parameter(Descriptor::kActualArgumentsCount);
1774 Node* slot = assembler.Parameter(Descriptor::kSlot); 1947 Node* slot = assembler.Parameter(Descriptor::kSlot);
1775 Node* vector = assembler.LoadTypeFeedbackVectorForStub(); 1948 Node* vector = assembler.LoadTypeFeedbackVectorForStub();
1776 1949
1777 Callable callable = 1950 Callable callable =
1778 CodeFactory::CallIC(isolate(), convert_mode(), tail_call_mode()); 1951 CodeFactory::CallIC(isolate(), convert_mode(), tail_call_mode());
1779 assembler.TailCallStub(callable, context, target, argc, slot, vector); 1952 assembler.TailCallStub(callable, context, target, argc, slot, vector);
1780 } 1953 }
1781 1954
1782 void JSEntryStub::FinishCode(Handle<Code> code) { 1955 void JSEntryStub::FinishCode(Handle<Code> code) {
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after
2196 } 2369 }
2197 2370
2198 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate) 2371 ArrayConstructorStub::ArrayConstructorStub(Isolate* isolate)
2199 : PlatformCodeStub(isolate) {} 2372 : PlatformCodeStub(isolate) {}
2200 2373
2201 InternalArrayConstructorStub::InternalArrayConstructorStub(Isolate* isolate) 2374 InternalArrayConstructorStub::InternalArrayConstructorStub(Isolate* isolate)
2202 : PlatformCodeStub(isolate) {} 2375 : PlatformCodeStub(isolate) {}
2203 2376
2204 } // namespace internal 2377 } // namespace internal
2205 } // namespace v8 2378 } // namespace v8
OLDNEW
« no previous file with comments | « src/code-stubs.h ('k') | src/full-codegen/arm/full-codegen-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698