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 1699 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1710 context()->Plug(rax); | 1710 context()->Plug(rax); |
1711 } | 1711 } |
1712 | 1712 |
1713 | 1713 |
1714 void FullCodeGenerator::EmitCallWithIC(Call* expr, | 1714 void FullCodeGenerator::EmitCallWithIC(Call* expr, |
1715 Handle<Object> name, | 1715 Handle<Object> name, |
1716 RelocInfo::Mode mode) { | 1716 RelocInfo::Mode mode) { |
1717 // Code common for calls using the IC. | 1717 // Code common for calls using the IC. |
1718 ZoneList<Expression*>* args = expr->arguments(); | 1718 ZoneList<Expression*>* args = expr->arguments(); |
1719 int arg_count = args->length(); | 1719 int arg_count = args->length(); |
1720 for (int i = 0; i < arg_count; i++) { | 1720 { PreserveStatementPositionScope scope(masm()->positions_recorder()); |
1721 VisitForStackValue(args->at(i)); | 1721 for (int i = 0; i < arg_count; i++) { |
| 1722 VisitForStackValue(args->at(i)); |
| 1723 } |
| 1724 __ Move(rcx, name); |
1722 } | 1725 } |
1723 __ Move(rcx, name); | |
1724 // Record source position for debugger. | 1726 // Record source position for debugger. |
1725 SetSourcePosition(expr->position()); | 1727 SetSourcePosition(expr->position(), FORCED_POSITION); |
1726 // Call the IC initialization code. | 1728 // Call the IC initialization code. |
1727 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 1729 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
1728 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, | 1730 Handle<Code> ic = CodeGenerator::ComputeCallInitialize(arg_count, |
1729 in_loop); | 1731 in_loop); |
1730 EmitCallIC(ic, mode); | 1732 EmitCallIC(ic, mode); |
1731 // Restore context register. | 1733 // Restore context register. |
1732 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 1734 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
1733 context()->Plug(rax); | 1735 context()->Plug(rax); |
1734 } | 1736 } |
1735 | 1737 |
1736 | 1738 |
1737 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, | 1739 void FullCodeGenerator::EmitKeyedCallWithIC(Call* expr, |
1738 Expression* key, | 1740 Expression* key, |
1739 RelocInfo::Mode mode) { | 1741 RelocInfo::Mode mode) { |
1740 // Code common for calls using the IC. | 1742 // Code common for calls using the IC. |
1741 ZoneList<Expression*>* args = expr->arguments(); | 1743 ZoneList<Expression*>* args = expr->arguments(); |
1742 int arg_count = args->length(); | 1744 int arg_count = args->length(); |
1743 for (int i = 0; i < arg_count; i++) { | 1745 { PreserveStatementPositionScope scope(masm()->positions_recorder()); |
1744 VisitForStackValue(args->at(i)); | 1746 for (int i = 0; i < arg_count; i++) { |
| 1747 VisitForStackValue(args->at(i)); |
| 1748 } |
| 1749 VisitForAccumulatorValue(key); |
| 1750 __ movq(rcx, rax); |
1745 } | 1751 } |
1746 VisitForAccumulatorValue(key); | |
1747 __ movq(rcx, rax); | |
1748 // Record source position for debugger. | 1752 // Record source position for debugger. |
1749 SetSourcePosition(expr->position()); | 1753 SetSourcePosition(expr->position(), FORCED_POSITION); |
1750 // Call the IC initialization code. | 1754 // Call the IC initialization code. |
1751 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 1755 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
1752 Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize(arg_count, | 1756 Handle<Code> ic = CodeGenerator::ComputeKeyedCallInitialize(arg_count, |
1753 in_loop); | 1757 in_loop); |
1754 EmitCallIC(ic, mode); | 1758 EmitCallIC(ic, mode); |
1755 // Restore context register. | 1759 // Restore context register. |
1756 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 1760 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
1757 context()->Plug(rax); | 1761 context()->Plug(rax); |
1758 } | 1762 } |
1759 | 1763 |
1760 | 1764 |
1761 void FullCodeGenerator::EmitCallWithStub(Call* expr) { | 1765 void FullCodeGenerator::EmitCallWithStub(Call* expr) { |
1762 // Code common for calls using the call stub. | 1766 // Code common for calls using the call stub. |
1763 ZoneList<Expression*>* args = expr->arguments(); | 1767 ZoneList<Expression*>* args = expr->arguments(); |
1764 int arg_count = args->length(); | 1768 int arg_count = args->length(); |
1765 for (int i = 0; i < arg_count; i++) { | 1769 { PreserveStatementPositionScope scope(masm()->positions_recorder()); |
1766 VisitForStackValue(args->at(i)); | 1770 for (int i = 0; i < arg_count; i++) { |
| 1771 VisitForStackValue(args->at(i)); |
| 1772 } |
1767 } | 1773 } |
1768 // Record source position for debugger. | 1774 // Record source position for debugger. |
1769 SetSourcePosition(expr->position()); | 1775 SetSourcePosition(expr->position(), FORCED_POSITION); |
1770 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 1776 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
1771 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); | 1777 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); |
1772 __ CallStub(&stub); | 1778 __ CallStub(&stub); |
1773 // Restore context register. | 1779 // Restore context register. |
1774 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 1780 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
1775 // Discard the function left on TOS. | 1781 // Discard the function left on TOS. |
1776 context()->DropAndPlug(1, rax); | 1782 context()->DropAndPlug(1, rax); |
1777 } | 1783 } |
1778 | 1784 |
1779 | 1785 |
1780 void FullCodeGenerator::VisitCall(Call* expr) { | 1786 void FullCodeGenerator::VisitCall(Call* expr) { |
1781 Comment cmnt(masm_, "[ Call"); | 1787 Comment cmnt(masm_, "[ Call"); |
1782 Expression* fun = expr->expression(); | 1788 Expression* fun = expr->expression(); |
1783 Variable* var = fun->AsVariableProxy()->AsVariable(); | 1789 Variable* var = fun->AsVariableProxy()->AsVariable(); |
1784 | 1790 |
1785 if (var != NULL && var->is_possibly_eval()) { | 1791 if (var != NULL && var->is_possibly_eval()) { |
1786 // In a call to eval, we first call %ResolvePossiblyDirectEval to | 1792 // In a call to eval, we first call %ResolvePossiblyDirectEval to |
1787 // resolve the function we need to call and the receiver of the | 1793 // resolve the function we need to call and the receiver of the |
1788 // call. The we call the resolved function using the given | 1794 // call. The we call the resolved function using the given |
1789 // arguments. | 1795 // arguments. |
1790 VisitForStackValue(fun); | |
1791 __ PushRoot(Heap::kUndefinedValueRootIndex); // Reserved receiver slot. | |
1792 | |
1793 // Push the arguments. | |
1794 ZoneList<Expression*>* args = expr->arguments(); | 1796 ZoneList<Expression*>* args = expr->arguments(); |
1795 int arg_count = args->length(); | 1797 int arg_count = args->length(); |
1796 for (int i = 0; i < arg_count; i++) { | 1798 { PreserveStatementPositionScope pos_scope(masm()->positions_recorder()); |
1797 VisitForStackValue(args->at(i)); | 1799 |
| 1800 VisitForStackValue(fun); |
| 1801 __ PushRoot(Heap::kUndefinedValueRootIndex); // Reserved receiver slot. |
| 1802 |
| 1803 // Push the arguments. |
| 1804 for (int i = 0; i < arg_count; i++) { |
| 1805 VisitForStackValue(args->at(i)); |
| 1806 } |
| 1807 |
| 1808 // Push copy of the function - found below the arguments. |
| 1809 __ push(Operand(rsp, (arg_count + 1) * kPointerSize)); |
| 1810 |
| 1811 // Push copy of the first argument or undefined if it doesn't exist. |
| 1812 if (arg_count > 0) { |
| 1813 __ push(Operand(rsp, arg_count * kPointerSize)); |
| 1814 } else { |
| 1815 __ PushRoot(Heap::kUndefinedValueRootIndex); |
| 1816 } |
| 1817 |
| 1818 // Push the receiver of the enclosing function and do runtime call. |
| 1819 __ push(Operand(rbp, (2 + scope()->num_parameters()) * kPointerSize)); |
| 1820 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3); |
| 1821 |
| 1822 // The runtime call returns a pair of values in rax (function) and |
| 1823 // rdx (receiver). Touch up the stack with the right values. |
| 1824 __ movq(Operand(rsp, (arg_count + 0) * kPointerSize), rdx); |
| 1825 __ movq(Operand(rsp, (arg_count + 1) * kPointerSize), rax); |
1798 } | 1826 } |
1799 | |
1800 // Push copy of the function - found below the arguments. | |
1801 __ push(Operand(rsp, (arg_count + 1) * kPointerSize)); | |
1802 | |
1803 // Push copy of the first argument or undefined if it doesn't exist. | |
1804 if (arg_count > 0) { | |
1805 __ push(Operand(rsp, arg_count * kPointerSize)); | |
1806 } else { | |
1807 __ PushRoot(Heap::kUndefinedValueRootIndex); | |
1808 } | |
1809 | |
1810 // Push the receiver of the enclosing function and do runtime call. | |
1811 __ push(Operand(rbp, (2 + scope()->num_parameters()) * kPointerSize)); | |
1812 __ CallRuntime(Runtime::kResolvePossiblyDirectEval, 3); | |
1813 | |
1814 // The runtime call returns a pair of values in rax (function) and | |
1815 // rdx (receiver). Touch up the stack with the right values. | |
1816 __ movq(Operand(rsp, (arg_count + 0) * kPointerSize), rdx); | |
1817 __ movq(Operand(rsp, (arg_count + 1) * kPointerSize), rax); | |
1818 | |
1819 // Record source position for debugger. | 1827 // Record source position for debugger. |
1820 SetSourcePosition(expr->position()); | 1828 SetSourcePosition(expr->position(), FORCED_POSITION); |
1821 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; | 1829 InLoopFlag in_loop = (loop_depth() > 0) ? IN_LOOP : NOT_IN_LOOP; |
1822 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); | 1830 CallFunctionStub stub(arg_count, in_loop, RECEIVER_MIGHT_BE_VALUE); |
1823 __ CallStub(&stub); | 1831 __ CallStub(&stub); |
1824 // Restore context register. | 1832 // Restore context register. |
1825 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | 1833 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); |
1826 context()->DropAndPlug(1, rax); | 1834 context()->DropAndPlug(1, rax); |
1827 } else if (var != NULL && !var->is_this() && var->is_global()) { | 1835 } else if (var != NULL && !var->is_this() && var->is_global()) { |
1828 // Call to a global variable. | 1836 // Call to a global variable. |
1829 // Push global object as receiver for the call IC lookup. | 1837 // Push global object as receiver for the call IC lookup. |
1830 __ push(CodeGenerator::GlobalObject()); | 1838 __ push(CodeGenerator::GlobalObject()); |
1831 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); | 1839 EmitCallWithIC(expr, var->name(), RelocInfo::CODE_TARGET_CONTEXT); |
1832 } else if (var != NULL && var->AsSlot() != NULL && | 1840 } else if (var != NULL && var->AsSlot() != NULL && |
1833 var->AsSlot()->type() == Slot::LOOKUP) { | 1841 var->AsSlot()->type() == Slot::LOOKUP) { |
1834 // Call to a lookup slot (dynamically introduced variable). | 1842 // Call to a lookup slot (dynamically introduced variable). |
1835 Label slow, done; | 1843 Label slow, done; |
1836 | 1844 |
1837 // Generate code for loading from variables potentially shadowed | 1845 { PreserveStatementPositionScope scope(masm()->positions_recorder()); |
1838 // by eval-introduced variables. | 1846 // Generate code for loading from variables potentially shadowed |
1839 EmitDynamicLoadFromSlotFastCase(var->AsSlot(), | 1847 // by eval-introduced variables. |
1840 NOT_INSIDE_TYPEOF, | 1848 EmitDynamicLoadFromSlotFastCase(var->AsSlot(), |
1841 &slow, | 1849 NOT_INSIDE_TYPEOF, |
1842 &done); | 1850 &slow, |
| 1851 &done); |
1843 | 1852 |
1844 __ bind(&slow); | 1853 __ bind(&slow); |
1845 // Call the runtime to find the function to call (returned in rax) | 1854 // Call the runtime to find the function to call (returned in rax) |
1846 // and the object holding it (returned in rdx). | 1855 // and the object holding it (returned in rdx). |
1847 __ push(context_register()); | 1856 __ push(context_register()); |
1848 __ Push(var->name()); | 1857 __ Push(var->name()); |
1849 __ CallRuntime(Runtime::kLoadContextSlot, 2); | 1858 __ CallRuntime(Runtime::kLoadContextSlot, 2); |
1850 __ push(rax); // Function. | 1859 __ push(rax); // Function. |
1851 __ push(rdx); // Receiver. | 1860 __ push(rdx); // Receiver. |
1852 | 1861 |
1853 // If fast case code has been generated, emit code to push the | 1862 // If fast case code has been generated, emit code to push the |
1854 // function and receiver and have the slow path jump around this | 1863 // function and receiver and have the slow path jump around this |
1855 // code. | 1864 // code. |
1856 if (done.is_linked()) { | 1865 if (done.is_linked()) { |
1857 NearLabel call; | 1866 NearLabel call; |
1858 __ jmp(&call); | 1867 __ jmp(&call); |
1859 __ bind(&done); | 1868 __ bind(&done); |
1860 // Push function. | 1869 // Push function. |
1861 __ push(rax); | 1870 __ push(rax); |
1862 // Push global receiver. | 1871 // Push global receiver. |
1863 __ movq(rbx, CodeGenerator::GlobalObject()); | 1872 __ movq(rbx, CodeGenerator::GlobalObject()); |
1864 __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); | 1873 __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); |
1865 __ bind(&call); | 1874 __ bind(&call); |
| 1875 } |
1866 } | 1876 } |
1867 | 1877 |
1868 EmitCallWithStub(expr); | 1878 EmitCallWithStub(expr); |
1869 | 1879 |
1870 } else if (fun->AsProperty() != NULL) { | 1880 } else if (fun->AsProperty() != NULL) { |
1871 // Call to an object property. | 1881 // Call to an object property. |
1872 Property* prop = fun->AsProperty(); | 1882 Property* prop = fun->AsProperty(); |
1873 Literal* key = prop->key()->AsLiteral(); | 1883 Literal* key = prop->key()->AsLiteral(); |
1874 if (key != NULL && key->handle()->IsSymbol()) { | 1884 if (key != NULL && key->handle()->IsSymbol()) { |
1875 // Call to a named property, use call IC. | 1885 // Call to a named property, use call IC. |
1876 VisitForStackValue(prop->obj()); | 1886 { PreserveStatementPositionScope scope(masm()->positions_recorder()); |
| 1887 VisitForStackValue(prop->obj()); |
| 1888 } |
1877 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); | 1889 EmitCallWithIC(expr, key->handle(), RelocInfo::CODE_TARGET); |
1878 } else { | 1890 } else { |
1879 // Call to a keyed property. | 1891 // Call to a keyed property. |
1880 // For a synthetic property use keyed load IC followed by function call, | 1892 // For a synthetic property use keyed load IC followed by function call, |
1881 // for a regular property use KeyedCallIC. | 1893 // for a regular property use KeyedCallIC. |
1882 VisitForStackValue(prop->obj()); | 1894 { PreserveStatementPositionScope scope(masm()->positions_recorder()); |
| 1895 VisitForStackValue(prop->obj()); |
| 1896 } |
1883 if (prop->is_synthetic()) { | 1897 if (prop->is_synthetic()) { |
1884 VisitForAccumulatorValue(prop->key()); | 1898 { PreserveStatementPositionScope scope(masm()->positions_recorder()); |
1885 __ movq(rdx, Operand(rsp, 0)); | 1899 VisitForAccumulatorValue(prop->key()); |
| 1900 __ movq(rdx, Operand(rsp, 0)); |
| 1901 } |
1886 // Record source code position for IC call. | 1902 // Record source code position for IC call. |
1887 SetSourcePosition(prop->position()); | 1903 SetSourcePosition(prop->position(), FORCED_POSITION); |
1888 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); | 1904 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); |
1889 EmitCallIC(ic, RelocInfo::CODE_TARGET); | 1905 EmitCallIC(ic, RelocInfo::CODE_TARGET); |
1890 // Pop receiver. | 1906 // Pop receiver. |
1891 __ pop(rbx); | 1907 __ pop(rbx); |
1892 // Push result (function). | 1908 // Push result (function). |
1893 __ push(rax); | 1909 __ push(rax); |
1894 // Push receiver object on stack. | 1910 // Push receiver object on stack. |
1895 __ movq(rcx, CodeGenerator::GlobalObject()); | 1911 __ movq(rcx, CodeGenerator::GlobalObject()); |
1896 __ push(FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset)); | 1912 __ push(FieldOperand(rcx, GlobalObject::kGlobalReceiverOffset)); |
1897 EmitCallWithStub(expr); | 1913 EmitCallWithStub(expr); |
1898 } else { | 1914 } else { |
1899 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); | 1915 EmitKeyedCallWithIC(expr, prop->key(), RelocInfo::CODE_TARGET); |
1900 } | 1916 } |
1901 } | 1917 } |
1902 } else { | 1918 } else { |
1903 // Call to some other expression. If the expression is an anonymous | 1919 // Call to some other expression. If the expression is an anonymous |
1904 // function literal not called in a loop, mark it as one that should | 1920 // function literal not called in a loop, mark it as one that should |
1905 // also use the fast code generator. | 1921 // also use the fast code generator. |
1906 FunctionLiteral* lit = fun->AsFunctionLiteral(); | 1922 FunctionLiteral* lit = fun->AsFunctionLiteral(); |
1907 if (lit != NULL && | 1923 if (lit != NULL && |
1908 lit->name()->Equals(Heap::empty_string()) && | 1924 lit->name()->Equals(Heap::empty_string()) && |
1909 loop_depth() == 0) { | 1925 loop_depth() == 0) { |
1910 lit->set_try_full_codegen(true); | 1926 lit->set_try_full_codegen(true); |
1911 } | 1927 } |
1912 VisitForStackValue(fun); | 1928 { PreserveStatementPositionScope scope(masm()->positions_recorder()); |
| 1929 VisitForStackValue(fun); |
| 1930 } |
1913 // Load global receiver object. | 1931 // Load global receiver object. |
1914 __ movq(rbx, CodeGenerator::GlobalObject()); | 1932 __ movq(rbx, CodeGenerator::GlobalObject()); |
1915 __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); | 1933 __ push(FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset)); |
1916 // Emit function call. | 1934 // Emit function call. |
1917 EmitCallWithStub(expr); | 1935 EmitCallWithStub(expr); |
1918 } | 1936 } |
1919 } | 1937 } |
1920 | 1938 |
1921 | 1939 |
1922 void FullCodeGenerator::VisitCallNew(CallNew* expr) { | 1940 void FullCodeGenerator::VisitCallNew(CallNew* expr) { |
(...skipping 1513 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3436 __ ret(0); | 3454 __ ret(0); |
3437 } | 3455 } |
3438 | 3456 |
3439 | 3457 |
3440 #undef __ | 3458 #undef __ |
3441 | 3459 |
3442 | 3460 |
3443 } } // namespace v8::internal | 3461 } } // namespace v8::internal |
3444 | 3462 |
3445 #endif // V8_TARGET_ARCH_X64 | 3463 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |