OLD | NEW |
1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1704 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1715 context()->Plug(rax); | 1715 context()->Plug(rax); |
1716 } | 1716 } |
1717 | 1717 |
1718 | 1718 |
1719 void FullCodeGenerator::EmitCallWithIC(Call* expr, | 1719 void FullCodeGenerator::EmitCallWithIC(Call* expr, |
1720 Handle<Object> name, | 1720 Handle<Object> name, |
1721 RelocInfo::Mode mode) { | 1721 RelocInfo::Mode mode) { |
1722 // Code common for calls using the IC. | 1722 // Code common for calls using the IC. |
1723 ZoneList<Expression*>* args = expr->arguments(); | 1723 ZoneList<Expression*>* args = expr->arguments(); |
1724 int arg_count = args->length(); | 1724 int arg_count = args->length(); |
1725 { PreserveStatementPositionScope scope(masm()->positions_recorder()); | 1725 { PreservePositionScope scope(masm()->positions_recorder()); |
1726 for (int i = 0; i < arg_count; i++) { | 1726 for (int i = 0; i < arg_count; i++) { |
1727 VisitForStackValue(args->at(i)); | 1727 VisitForStackValue(args->at(i)); |
1728 } | 1728 } |
1729 __ Move(rcx, name); | 1729 __ Move(rcx, name); |
1730 } | 1730 } |
1731 // Record source position for debugger. | 1731 // Record source position for debugger. |
1732 SetSourcePosition(expr->position(), FORCED_POSITION); | 1732 SetSourcePosition(expr->position()); |
1733 // Call the IC initialization code. | 1733 // Call the IC initialization code. |
1734 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 1734 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
1735 Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop); | 1735 Handle<Code> ic = StubCache::ComputeCallInitialize(arg_count, in_loop); |
1736 EmitCallIC(ic, mode); | 1736 EmitCallIC(ic, mode); |
1737 // Restore context register. | 1737 // Restore context register. |
1738 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 1738 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
1739 context()->Plug(rax); | 1739 context()->Plug(rax); |
1740 } | 1740 } |
1741 | 1741 |
1742 | 1742 |
1743 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 1743 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, |
1744 Expression* key, | 1744 Expression* key, |
1745 RelocInfo::Mode mode) { | 1745 RelocInfo::Mode mode) { |
1746 // Load the key. | 1746 // Load the key. |
1747 VisitForAccumulatorValue(key); | 1747 VisitForAccumulatorValue(key); |
1748 | 1748 |
1749 // Swap the name of the function and the receiver on the stack to follow | 1749 // Swap the name of the function and the receiver on the stack to follow |
1750 // the calling convention for call ICs. | 1750 // the calling convention for call ICs. |
1751 __ pop(rcx); | 1751 __ pop(rcx); |
1752 __ push(rax); | 1752 __ push(rax); |
1753 __ push(rcx); | 1753 __ push(rcx); |
1754 | 1754 |
1755 // Load the arguments. | 1755 // Load the arguments. |
1756 ZoneList<Expression*>* args = expr->arguments(); | 1756 ZoneList<Expression*>* args = expr->arguments(); |
1757 int arg_count = args->length(); | 1757 int arg_count = args->length(); |
1758 { PreserveStatementPositionScope scope(masm()->positions_recorder()); | 1758 { PreservePositionScope scope(masm()->positions_recorder()); |
1759 for (int i = 0; i < arg_count; i++) { | 1759 for (int i = 0; i < arg_count; i++) { |
1760 VisitForStackValue(args->at(i)); | 1760 VisitForStackValue(args->at(i)); |
1761 } | 1761 } |
1762 } | 1762 } |
1763 // Record source position for debugger. | 1763 // Record source position for debugger. |
1764 SetSourcePosition(expr->position(), FORCED_POSITION); | 1764 SetSourcePosition(expr->position()); |
1765 // Call the IC initialization code. | 1765 // Call the IC initialization code. |
1766 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 1766 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
1767 Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arg_count, in_loop); | 1767 Handle<Code> ic = StubCache::ComputeKeyedCallInitialize(arg_count, in_loop); |
1768 __ movq(rcx, Operand(rsp, (arg_count + 1) * kPointerSize)); // Key. | 1768 __ movq(rcx, Operand(rsp, (arg_count + 1) * kPointerSize)); // Key. |
1769 EmitCallIC(ic, mode); | 1769 EmitCallIC(ic, mode); |
1770 // Restore context register. | 1770 // Restore context register. |
1771 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 1771 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
1772 context()->DropAndPlug(1, rax); // Drop the key still on the stack. | 1772 context()->DropAndPlug(1, rax); // Drop the key still on the stack. |
1773 } | 1773 } |
1774 | 1774 |
1775 | 1775 |
1776 void FullCodeGenerator::EmitCallWithStub(Call* expr) { | 1776 void FullCodeGenerator::EmitCallWithStub(Call* expr) { |
1777 // Code common for calls using the call stub. | 1777 // Code common for calls using the call stub. |
1778 ZoneList<Expression*>* args = expr->arguments(); | 1778 ZoneList<Expression*>* args = expr->arguments(); |
1779 int arg_count = args->length(); | 1779 int arg_count = args->length(); |
1780 { PreserveStatementPositionScope scope(masm()->positions_recorder()); | 1780 { PreservePositionScope scope(masm()->positions_recorder()); |
1781 for (int i = 0; i < arg_count; i++) { | 1781 for (int i = 0; i < arg_count; i++) { |
1782 VisitForStackValue(args->at(i)); | 1782 VisitForStackValue(args->at(i)); |
1783 } | 1783 } |
1784 } | 1784 } |
1785 // Record source position for debugger. | 1785 // Record source position for debugger. |
1786 SetSourcePosition(expr->position(), FORCED_POSITION); | 1786 SetSourcePosition(expr->position()); |
1787 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 1787 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
1788 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); | 1788 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); |
1789 __ CallStub(&stub); | 1789 __ CallStub(&stub); |
1790 // Restore context register. | 1790 // Restore context register. |
1791 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 1791 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
1792 // Discard the function left on TOS. | 1792 // Discard the function left on TOS. |
1793 context()->DropAndPlug(1, rax); | 1793 context()->DropAndPlug(1, rax); |
1794 } | 1794 } |
1795 | 1795 |
1796 | 1796 |
1797 void FullCodeGenerator::VisitCall(Call* expr) { | 1797 void FullCodeGenerator::VisitCall(Call* expr) { |
1798 Comment cmnt(masm_, "[ Call"); | 1798 Comment cmnt(masm_, "[ Call"); |
1799 Expression* fun = expr->expression(); | 1799 Expression* fun = expr->expression(); |
1800 Variable* var = fun->AsVariableProxy()->AsVariable(); | 1800 Variable* var = fun->AsVariableProxy()->AsVariable(); |
1801 | 1801 |
1802 if (var != NULL && var->is_possibly_eval()) { | 1802 if (var != NULL && var->is_possibly_eval()) { |
1803 // In a call to eval, we first call %ResolvePossiblyDirectEval to | 1803 // In a call to eval, we first call %ResolvePossiblyDirectEval to |
1804 // resolve the function we need to call and the receiver of the | 1804 // resolve the function we need to call and the receiver of the |
1805 // call. The we call the resolved function using the given | 1805 // call. The we call the resolved function using the given |
1806 // arguments. | 1806 // arguments. |
1807 ZoneList<Expression*>* args = expr->arguments(); | 1807 ZoneList<Expression*>* args = expr->arguments(); |
1808 int arg_count = args->length(); | 1808 int arg_count = args->length(); |
1809 { PreserveStatementPositionScope pos_scope(masm()->positions_recorder()); | 1809 { PreservePositionScope pos_scope(masm()->positions_recorder()); |
1810 VisitForStackValue(fun); | 1810 VisitForStackValue(fun); |
1811 __ PushRoot(Heap::kUndefinedValueRootIndex); // Reserved receiver slot. | 1811 __ PushRoot(Heap::kUndefinedValueRootIndex); // Reserved receiver slot. |
1812 | 1812 |
1813 // Push the arguments. | 1813 // Push the arguments. |
1814 for (int i = 0; i < arg_count; i++) { | 1814 for (int i = 0; i < arg_count; i++) { |
1815 VisitForStackValue(args->at(i)); | 1815 VisitForStackValue(args->at(i)); |
1816 } | 1816 } |
1817 | 1817 |
1818 // Push copy of the function - found below the arguments. | 1818 // Push copy of the function - found below the arguments. |
1819 __ push(Operand(rsp, (arg_count + 1) * kPointerSize)); | 1819 __ push(Operand(rsp, (arg_count + 1) * kPointerSize)); |
1820 | 1820 |
1821 // Push copy of the first argument or undefined if it doesn't exist. | 1821 // Push copy of the first argument or undefined if it doesn't exist. |
1822 if (arg_count > 0) { | 1822 if (arg_count > 0) { |
1823 __ push(Operand(rsp, arg_count * kPointerSize)); | 1823 __ push(Operand(rsp, arg_count * kPointerSize)); |
1824 } else { | 1824 } else { |
1825 __ PushRoot(Heap::kUndefinedValueRootIndex); | 1825 __ PushRoot(Heap::kUndefinedValueRootIndex); |
1826 } | 1826 } |
1827 | 1827 |
1828 // Push the receiver of the enclosing function and do runtime call. | 1828 // Push the receiver of the enclosing function and do runtime call. |
1829 __ push(Operand(rbp, (2 + scope()->num_parameters()) * kPointerSize)); | 1829 __ push(Operand(rbp, (2 + scope()->num_parameters()) * kPointerSize)); |
1830 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3); | 1830 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3); |
1831 | 1831 |
1832 // The runtime call returns a pair of values in rax (function) and | 1832 // The runtime call returns a pair of values in rax (function) and |
1833 // rdx (receiver). Touch up the stack with the right values. | 1833 // rdx (receiver). Touch up the stack with the right values. |
1834 __ movq(Operand(rsp, (arg_count + 0) * kPointerSize), rdx); | 1834 __ movq(Operand(rsp, (arg_count + 0) * kPointerSize), rdx); |
1835 __ movq(Operand(rsp, (arg_count + 1) * kPointerSize), rax); | 1835 __ movq(Operand(rsp, (arg_count + 1) * kPointerSize), rax); |
1836 } | 1836 } |
1837 // Record source position for debugger. | 1837 // Record source position for debugger. |
1838 SetSourcePosition(expr->position(), FORCED_POSITION); | 1838 SetSourcePosition(expr->position()); |
1839 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 1839 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
1840 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); | 1840 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); |
1841 __ CallStub(&stub); | 1841 __ CallStub(&stub); |
1842 // Restore context register. | 1842 // Restore context register. |
1843 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 1843 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
1844 context()->DropAndPlug(1, rax); | 1844 context()->DropAndPlug(1, rax); |
1845 } else if (var != NULL && !var->is_this() && var->is_global()) { | 1845 } else if (var != NULL && !var->is_this() && var->is_global()) { |
1846 // Call to a global variable. | 1846 // Call to a global variable. |
1847 // Push global object as receiver for the call IC lookup. | 1847 // Push global object as receiver for the call IC lookup. |
1848 __ push(GlobalObjectOperand()); | 1848 __ push(GlobalObjectOperand()); |
1849 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); | 1849 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); |
1850 } else if (var != NULL && var->AsSlot() != NULL && | 1850 } else if (var != NULL && var->AsSlot() != NULL && |
1851 var->AsSlot()->type() == Slot::LOOKUP) { | 1851 var->AsSlot()->type() == Slot::LOOKUP) { |
1852 // Call to a lookup slot (dynamically introduced variable). | 1852 // Call to a lookup slot (dynamically introduced variable). |
1853 Label slow, done; | 1853 Label slow, done; |
1854 | 1854 |
1855 { PreserveStatementPositionScope scope(masm()->positions_recorder()); | 1855 { PreservePositionScope scope(masm()->positions_recorder()); |
1856 // Generate code for loading from variables potentially shadowed | 1856 // Generate code for loading from variables potentially shadowed |
1857 // by eval-introduced variables. | 1857 // by eval-introduced variables. |
1858 EmitDynamicLoadFromSlotFastCase(var->AsSlot(), | 1858 EmitDynamicLoadFromSlotFastCase(var->AsSlot(), |
1859 NOT_INSIDE_TYPEOF, | 1859 NOT_INSIDE_TYPEOF, |
1860 &slow, | 1860 &slow, |
1861 &done); | 1861 &done); |
1862 | 1862 |
1863 __ bind(&slow); | 1863 __ bind(&slow); |
1864 // Call the runtime to find the function to call (returned in rax) | 1864 // Call the runtime to find the function to call (returned in rax) |
1865 // and the object holding it (returned in rdx). | 1865 // and the object holding it (returned in rdx). |
(...skipping 20 matching lines...) Expand all Loading... |
1886 } | 1886 } |
1887 | 1887 |
1888 EmitCallWithStub(expr); | 1888 EmitCallWithStub(expr); |
1889 | 1889 |
1890 } else if (fun->AsProperty() != NULL) { | 1890 } else if (fun->AsProperty() != NULL) { |
1891 // Call to an object property. | 1891 // Call to an object property. |
1892 Property* prop = fun->AsProperty(); | 1892 Property* prop = fun->AsProperty(); |
1893 Literal* key = prop->key()->AsLiteral(); | 1893 Literal* key = prop->key()->AsLiteral(); |
1894 if (key != NULL && key->handle()->IsSymbol()) { | 1894 if (key != NULL && key->handle()->IsSymbol()) { |
1895 // Call to a named property, use call IC. | 1895 // Call to a named property, use call IC. |
1896 { PreserveStatementPositionScope scope(masm()->positions_recorder()); | 1896 { PreservePositionScope scope(masm()->positions_recorder()); |
1897 VisitForStackValue(prop->obj()); | 1897 VisitForStackValue(prop->obj()); |
1898 } | 1898 } |
1899 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); | 1899 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); |
1900 } else { | 1900 } else { |
1901 // Call to a keyed property. | 1901 // Call to a keyed property. |
1902 // For a synthetic property use keyed load IC followed by function call, | 1902 // For a synthetic property use keyed load IC followed by function call, |
1903 // for a regular property use KeyedCallIC. | 1903 // for a regular property use KeyedCallIC. |
1904 { PreserveStatementPositionScope scope(masm()->positions_recorder()); | 1904 { PreservePositionScope scope(masm()->positions_recorder()); |
1905 VisitForStackValue(prop->obj()); | 1905 VisitForStackValue(prop->obj()); |
1906 } | 1906 } |
1907 if (prop->is_synthetic()) { | 1907 if (prop->is_synthetic()) { |
1908 { PreserveStatementPositionScope scope(masm()->positions_recorder()); | 1908 { PreservePositionScope scope(masm()->positions_recorder()); |
1909 VisitForAccumulatorValue(prop->key()); | 1909 VisitForAccumulatorValue(prop->key()); |
1910 __ movq(rdx, Operand(rsp, 0)); | 1910 __ movq(rdx, Operand(rsp, 0)); |
1911 } | 1911 } |
1912 // Record source code position for IC call. | 1912 // Record source code position for IC call. |
1913 SetSourcePosition(prop->position(), FORCED_POSITION); | 1913 SetSourcePosition(prop->position()); |
1914 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1914 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
1915 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1915 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1916 // Pop receiver. | 1916 // Pop receiver. |
1917 __ pop(rbx); | 1917 __ pop(rbx); |
1918 // Push result (function). | 1918 // Push result (function). |
1919 __ push(rax); | 1919 __ push(rax); |
1920 // Push receiver object on stack. | 1920 // Push receiver object on stack. |
1921 __ movq(rcx, GlobalObjectOperand()); | 1921 __ movq(rcx, GlobalObjectOperand()); |
1922 __ push(FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset)); | 1922 __ push(FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset)); |
1923 EmitCallWithStub(expr); | 1923 EmitCallWithStub(expr); |
1924 } else { | 1924 } else { |
1925 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); | 1925 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); |
1926 } | 1926 } |
1927 } | 1927 } |
1928 } else { | 1928 } else { |
1929 // Call to some other expression. If the expression is an anonymous | 1929 // Call to some other expression. If the expression is an anonymous |
1930 // function literal not called in a loop, mark it as one that should | 1930 // function literal not called in a loop, mark it as one that should |
1931 // also use the fast code generator. | 1931 // also use the fast code generator. |
1932 FunctionLiteral* lit = fun->AsFunctionLiteral(); | 1932 FunctionLiteral* lit = fun->AsFunctionLiteral(); |
1933 if (lit != NULL && | 1933 if (lit != NULL && |
1934 lit->name()->Equals(Heap::empty_string()) && | 1934 lit->name()->Equals(Heap::empty_string()) && |
1935 loop_depth() == 0) { | 1935 loop_depth() == 0) { |
1936 lit->set_try_full_codegen(true); | 1936 lit->set_try_full_codegen(true); |
1937 } | 1937 } |
1938 { PreserveStatementPositionScope scope(masm()->positions_recorder()); | 1938 { PreservePositionScope scope(masm()->positions_recorder()); |
1939 VisitForStackValue(fun); | 1939 VisitForStackValue(fun); |
1940 } | 1940 } |
1941 // Load global receiver object. | 1941 // Load global receiver object. |
1942 __ movq(rbx, GlobalObjectOperand()); | 1942 __ movq(rbx, GlobalObjectOperand()); |
1943 __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); | 1943 __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); |
1944 // Emit function call. | 1944 // Emit function call. |
1945 EmitCallWithStub(expr); | 1945 EmitCallWithStub(expr); |
1946 } | 1946 } |
1947 } | 1947 } |
1948 | 1948 |
(...skipping 1520 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3469 __ ret(0); | 3469 __ ret(0); |
3470 } | 3470 } |
3471 | 3471 |
3472 | 3472 |
3473 #undef __ | 3473 #undef __ |
3474 | 3474 |
3475 | 3475 |
3476 } } // namespace v8::internal | 3476 } } // namespace v8::internal |
3477 | 3477 |
3478 #endif // V8_TARGET_ARCH_X64 | 3478 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |