OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 1576 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1587 bind(&done); | 1587 bind(&done); |
1588 } | 1588 } |
1589 | 1589 |
1590 | 1590 |
1591 void MacroAssembler::CallStub(CodeStub* stub, unsigned ast_id) { | 1591 void MacroAssembler::CallStub(CodeStub* stub, unsigned ast_id) { |
1592 ASSERT(AllowThisStubCall(stub)); // Calls are not allowed in some stubs. | 1592 ASSERT(AllowThisStubCall(stub)); // Calls are not allowed in some stubs. |
1593 call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id); | 1593 call(stub->GetCode(), RelocInfo::CODE_TARGET, ast_id); |
1594 } | 1594 } |
1595 | 1595 |
1596 | 1596 |
1597 MaybeObject* MacroAssembler::TryCallStub(CodeStub* stub) { | |
1598 ASSERT(AllowThisStubCall(stub)); // Calls are not allowed in some stubs. | |
1599 Object* result; | |
1600 { MaybeObject* maybe_result = stub->TryGetCode(); | |
1601 if (!maybe_result->ToObject(&result)) return maybe_result; | |
1602 } | |
1603 call(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET); | |
1604 return result; | |
1605 } | |
1606 | |
1607 | |
1608 void MacroAssembler::TailCallStub(CodeStub* stub) { | 1597 void MacroAssembler::TailCallStub(CodeStub* stub) { |
1609 ASSERT(allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe()); | 1598 ASSERT(allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe()); |
1610 jmp(stub->GetCode(), RelocInfo::CODE_TARGET); | 1599 jmp(stub->GetCode(), RelocInfo::CODE_TARGET); |
1611 } | 1600 } |
1612 | 1601 |
1613 | 1602 |
1614 MaybeObject* MacroAssembler::TryTailCallStub(CodeStub* stub) { | |
1615 Object* result; | |
1616 { MaybeObject* maybe_result = stub->TryGetCode(); | |
1617 if (!maybe_result->ToObject(&result)) return maybe_result; | |
1618 } | |
1619 jmp(Handle<Code>(Code::cast(result)), RelocInfo::CODE_TARGET); | |
1620 return result; | |
1621 } | |
1622 | |
1623 | |
1624 void MacroAssembler::StubReturn(int argc) { | 1603 void MacroAssembler::StubReturn(int argc) { |
1625 ASSERT(argc >= 1 && generating_stub()); | 1604 ASSERT(argc >= 1 && generating_stub()); |
1626 ret((argc - 1) * kPointerSize); | 1605 ret((argc - 1) * kPointerSize); |
1627 } | 1606 } |
1628 | 1607 |
1629 | 1608 |
1630 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) { | 1609 bool MacroAssembler::AllowThisStubCall(CodeStub* stub) { |
1631 if (!has_frame_ && stub->SometimesSetsUpAFrame()) return false; | 1610 if (!has_frame_ && stub->SometimesSetsUpAFrame()) return false; |
1632 return allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe(); | 1611 return allow_stub_calls_ || stub->CompilingCallsToThisStubIsGCSafe(); |
1633 } | 1612 } |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1667 | 1646 |
1668 void MacroAssembler::CallRuntimeSaveDoubles(Runtime::FunctionId id) { | 1647 void MacroAssembler::CallRuntimeSaveDoubles(Runtime::FunctionId id) { |
1669 const Runtime::Function* function = Runtime::FunctionForId(id); | 1648 const Runtime::Function* function = Runtime::FunctionForId(id); |
1670 Set(eax, Immediate(function->nargs)); | 1649 Set(eax, Immediate(function->nargs)); |
1671 mov(ebx, Immediate(ExternalReference(function, isolate()))); | 1650 mov(ebx, Immediate(ExternalReference(function, isolate()))); |
1672 CEntryStub ces(1, kSaveFPRegs); | 1651 CEntryStub ces(1, kSaveFPRegs); |
1673 CallStub(&ces); | 1652 CallStub(&ces); |
1674 } | 1653 } |
1675 | 1654 |
1676 | 1655 |
1677 MaybeObject* MacroAssembler::TryCallRuntime(Runtime::FunctionId id, | |
1678 int num_arguments) { | |
1679 return TryCallRuntime(Runtime::FunctionForId(id), num_arguments); | |
1680 } | |
1681 | |
1682 | |
1683 void MacroAssembler::CallRuntime(const Runtime::Function* f, | 1656 void MacroAssembler::CallRuntime(const Runtime::Function* f, |
1684 int num_arguments) { | 1657 int num_arguments) { |
1685 // If the expected number of arguments of the runtime function is | 1658 // If the expected number of arguments of the runtime function is |
1686 // constant, we check that the actual number of arguments match the | 1659 // constant, we check that the actual number of arguments match the |
1687 // expectation. | 1660 // expectation. |
1688 if (f->nargs >= 0 && f->nargs != num_arguments) { | 1661 if (f->nargs >= 0 && f->nargs != num_arguments) { |
1689 IllegalOperation(num_arguments); | 1662 IllegalOperation(num_arguments); |
1690 return; | 1663 return; |
1691 } | 1664 } |
1692 | 1665 |
1693 // TODO(1236192): Most runtime routines don't need the number of | 1666 // TODO(1236192): Most runtime routines don't need the number of |
1694 // arguments passed in because it is constant. At some point we | 1667 // arguments passed in because it is constant. At some point we |
1695 // should remove this need and make the runtime routine entry code | 1668 // should remove this need and make the runtime routine entry code |
1696 // smarter. | 1669 // smarter. |
1697 Set(eax, Immediate(num_arguments)); | 1670 Set(eax, Immediate(num_arguments)); |
1698 mov(ebx, Immediate(ExternalReference(f, isolate()))); | 1671 mov(ebx, Immediate(ExternalReference(f, isolate()))); |
1699 CEntryStub ces(1); | 1672 CEntryStub ces(1); |
1700 CallStub(&ces); | 1673 CallStub(&ces); |
1701 } | 1674 } |
1702 | 1675 |
1703 | 1676 |
1704 MaybeObject* MacroAssembler::TryCallRuntime(const Runtime::Function* f, | |
1705 int num_arguments) { | |
1706 if (f->nargs >= 0 && f->nargs != num_arguments) { | |
1707 IllegalOperation(num_arguments); | |
1708 // Since we did not call the stub, there was no allocation failure. | |
1709 // Return some non-failure object. | |
1710 return isolate()->heap()->undefined_value(); | |
1711 } | |
1712 | |
1713 // TODO(1236192): Most runtime routines don't need the number of | |
1714 // arguments passed in because it is constant. At some point we | |
1715 // should remove this need and make the runtime routine entry code | |
1716 // smarter. | |
1717 Set(eax, Immediate(num_arguments)); | |
1718 mov(ebx, Immediate(ExternalReference(f, isolate()))); | |
1719 CEntryStub ces(1); | |
1720 return TryCallStub(&ces); | |
1721 } | |
1722 | |
1723 | |
1724 void MacroAssembler::CallExternalReference(ExternalReference ref, | 1677 void MacroAssembler::CallExternalReference(ExternalReference ref, |
1725 int num_arguments) { | 1678 int num_arguments) { |
1726 mov(eax, Immediate(num_arguments)); | 1679 mov(eax, Immediate(num_arguments)); |
1727 mov(ebx, Immediate(ref)); | 1680 mov(ebx, Immediate(ref)); |
1728 | 1681 |
1729 CEntryStub stub(1); | 1682 CEntryStub stub(1); |
1730 CallStub(&stub); | 1683 CallStub(&stub); |
1731 } | 1684 } |
1732 | 1685 |
1733 | 1686 |
1734 void MacroAssembler::TailCallExternalReference(const ExternalReference& ext, | 1687 void MacroAssembler::TailCallExternalReference(const ExternalReference& ext, |
1735 int num_arguments, | 1688 int num_arguments, |
1736 int result_size) { | 1689 int result_size) { |
1737 // TODO(1236192): Most runtime routines don't need the number of | 1690 // TODO(1236192): Most runtime routines don't need the number of |
1738 // arguments passed in because it is constant. At some point we | 1691 // arguments passed in because it is constant. At some point we |
1739 // should remove this need and make the runtime routine entry code | 1692 // should remove this need and make the runtime routine entry code |
1740 // smarter. | 1693 // smarter. |
1741 Set(eax, Immediate(num_arguments)); | 1694 Set(eax, Immediate(num_arguments)); |
1742 JumpToExternalReference(ext); | 1695 JumpToExternalReference(ext); |
1743 } | 1696 } |
1744 | 1697 |
1745 | 1698 |
1746 MaybeObject* MacroAssembler::TryTailCallExternalReference( | |
1747 const ExternalReference& ext, int num_arguments, int result_size) { | |
1748 // TODO(1236192): Most runtime routines don't need the number of | |
1749 // arguments passed in because it is constant. At some point we | |
1750 // should remove this need and make the runtime routine entry code | |
1751 // smarter. | |
1752 Set(eax, Immediate(num_arguments)); | |
1753 return TryJumpToExternalReference(ext); | |
1754 } | |
1755 | |
1756 | |
1757 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid, | 1699 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid, |
1758 int num_arguments, | 1700 int num_arguments, |
1759 int result_size) { | 1701 int result_size) { |
1760 TailCallExternalReference(ExternalReference(fid, isolate()), | 1702 TailCallExternalReference(ExternalReference(fid, isolate()), |
1761 num_arguments, | 1703 num_arguments, |
1762 result_size); | 1704 result_size); |
1763 } | 1705 } |
1764 | 1706 |
1765 | 1707 |
1766 MaybeObject* MacroAssembler::TryTailCallRuntime(Runtime::FunctionId fid, | |
1767 int num_arguments, | |
1768 int result_size) { | |
1769 return TryTailCallExternalReference( | |
1770 ExternalReference(fid, isolate()), num_arguments, result_size); | |
1771 } | |
1772 | |
1773 | |
1774 // If true, a Handle<T> returned by value from a function with cdecl calling | 1708 // If true, a Handle<T> returned by value from a function with cdecl calling |
1775 // convention will be returned directly as a value of location_ field in a | 1709 // convention will be returned directly as a value of location_ field in a |
1776 // register eax. | 1710 // register eax. |
1777 // If false, it is returned as a pointer to a preallocated by caller memory | 1711 // If false, it is returned as a pointer to a preallocated by caller memory |
1778 // region. Pointer to this region should be passed to a function as an | 1712 // region. Pointer to this region should be passed to a function as an |
1779 // implicit first argument. | 1713 // implicit first argument. |
1780 #if defined(USING_BSD_ABI) || defined(__MINGW32__) || defined(__CYGWIN__) | 1714 #if defined(USING_BSD_ABI) || defined(__MINGW32__) || defined(__CYGWIN__) |
1781 static const bool kReturnHandlesDirectly = true; | 1715 static const bool kReturnHandlesDirectly = true; |
1782 #else | 1716 #else |
1783 static const bool kReturnHandlesDirectly = false; | 1717 static const bool kReturnHandlesDirectly = false; |
(...skipping 28 matching lines...) Expand all Loading... |
1812 | 1746 |
1813 lea(esi, Operand(esp, (argc + 1) * kPointerSize)); | 1747 lea(esi, Operand(esp, (argc + 1) * kPointerSize)); |
1814 mov(Operand(esp, 0 * kPointerSize), esi); | 1748 mov(Operand(esp, 0 * kPointerSize), esi); |
1815 if (emit_debug_code()) { | 1749 if (emit_debug_code()) { |
1816 mov(Operand(esi, 0), Immediate(0)); | 1750 mov(Operand(esi, 0), Immediate(0)); |
1817 } | 1751 } |
1818 } | 1752 } |
1819 } | 1753 } |
1820 | 1754 |
1821 | 1755 |
1822 MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(ApiFunction* function, | 1756 void MacroAssembler::CallApiFunctionAndReturn(Address function_address, |
1823 int stack_space) { | 1757 int stack_space) { |
1824 ExternalReference next_address = | 1758 ExternalReference next_address = |
1825 ExternalReference::handle_scope_next_address(); | 1759 ExternalReference::handle_scope_next_address(); |
1826 ExternalReference limit_address = | 1760 ExternalReference limit_address = |
1827 ExternalReference::handle_scope_limit_address(); | 1761 ExternalReference::handle_scope_limit_address(); |
1828 ExternalReference level_address = | 1762 ExternalReference level_address = |
1829 ExternalReference::handle_scope_level_address(); | 1763 ExternalReference::handle_scope_level_address(); |
1830 | 1764 |
1831 // Allocate HandleScope in callee-save registers. | 1765 // Allocate HandleScope in callee-save registers. |
1832 mov(ebx, Operand::StaticVariable(next_address)); | 1766 mov(ebx, Operand::StaticVariable(next_address)); |
1833 mov(edi, Operand::StaticVariable(limit_address)); | 1767 mov(edi, Operand::StaticVariable(limit_address)); |
1834 add(Operand::StaticVariable(level_address), Immediate(1)); | 1768 add(Operand::StaticVariable(level_address), Immediate(1)); |
1835 | 1769 |
1836 // Call the api function! | 1770 // Call the api function. |
1837 call(function->address(), RelocInfo::RUNTIME_ENTRY); | 1771 call(function_address, RelocInfo::RUNTIME_ENTRY); |
1838 | 1772 |
1839 if (!kReturnHandlesDirectly) { | 1773 if (!kReturnHandlesDirectly) { |
1840 // PrepareCallApiFunction saved pointer to the output slot into | 1774 // PrepareCallApiFunction saved pointer to the output slot into |
1841 // callee-save register esi. | 1775 // callee-save register esi. |
1842 mov(eax, Operand(esi, 0)); | 1776 mov(eax, Operand(esi, 0)); |
1843 } | 1777 } |
1844 | 1778 |
1845 Label empty_handle; | 1779 Label empty_handle; |
1846 Label prologue; | 1780 Label prologue; |
1847 Label promote_scheduled_exception; | 1781 Label promote_scheduled_exception; |
(...skipping 17 matching lines...) Expand all Loading... |
1865 | 1799 |
1866 // Check if the function scheduled an exception. | 1800 // Check if the function scheduled an exception. |
1867 ExternalReference scheduled_exception_address = | 1801 ExternalReference scheduled_exception_address = |
1868 ExternalReference::scheduled_exception_address(isolate()); | 1802 ExternalReference::scheduled_exception_address(isolate()); |
1869 cmp(Operand::StaticVariable(scheduled_exception_address), | 1803 cmp(Operand::StaticVariable(scheduled_exception_address), |
1870 Immediate(isolate()->factory()->the_hole_value())); | 1804 Immediate(isolate()->factory()->the_hole_value())); |
1871 j(not_equal, &promote_scheduled_exception); | 1805 j(not_equal, &promote_scheduled_exception); |
1872 LeaveApiExitFrame(); | 1806 LeaveApiExitFrame(); |
1873 ret(stack_space * kPointerSize); | 1807 ret(stack_space * kPointerSize); |
1874 bind(&promote_scheduled_exception); | 1808 bind(&promote_scheduled_exception); |
1875 MaybeObject* result = | 1809 TailCallRuntime(Runtime::kPromoteScheduledException, 0, 1); |
1876 TryTailCallRuntime(Runtime::kPromoteScheduledException, 0, 1); | 1810 |
1877 if (result->IsFailure()) { | |
1878 return result; | |
1879 } | |
1880 bind(&empty_handle); | 1811 bind(&empty_handle); |
1881 // It was zero; the result is undefined. | 1812 // It was zero; the result is undefined. |
1882 mov(eax, isolate()->factory()->undefined_value()); | 1813 mov(eax, isolate()->factory()->undefined_value()); |
1883 jmp(&prologue); | 1814 jmp(&prologue); |
1884 | 1815 |
1885 // HandleScope limit has changed. Delete allocated extensions. | 1816 // HandleScope limit has changed. Delete allocated extensions. |
1886 ExternalReference delete_extensions = | 1817 ExternalReference delete_extensions = |
1887 ExternalReference::delete_handle_scope_extensions(isolate()); | 1818 ExternalReference::delete_handle_scope_extensions(isolate()); |
1888 bind(&delete_allocated_handles); | 1819 bind(&delete_allocated_handles); |
1889 mov(Operand::StaticVariable(limit_address), edi); | 1820 mov(Operand::StaticVariable(limit_address), edi); |
1890 mov(edi, eax); | 1821 mov(edi, eax); |
1891 mov(Operand(esp, 0), Immediate(ExternalReference::isolate_address())); | 1822 mov(Operand(esp, 0), Immediate(ExternalReference::isolate_address())); |
1892 mov(eax, Immediate(delete_extensions)); | 1823 mov(eax, Immediate(delete_extensions)); |
1893 call(eax); | 1824 call(eax); |
1894 mov(eax, edi); | 1825 mov(eax, edi); |
1895 jmp(&leave_exit_frame); | 1826 jmp(&leave_exit_frame); |
1896 | |
1897 return result; | |
1898 } | 1827 } |
1899 | 1828 |
1900 | 1829 |
1901 void MacroAssembler::JumpToExternalReference(const ExternalReference& ext) { | 1830 void MacroAssembler::JumpToExternalReference(const ExternalReference& ext) { |
1902 // Set the entry point and jump to the C entry runtime stub. | 1831 // Set the entry point and jump to the C entry runtime stub. |
1903 mov(ebx, Immediate(ext)); | 1832 mov(ebx, Immediate(ext)); |
1904 CEntryStub ces(1); | 1833 CEntryStub ces(1); |
1905 jmp(ces.GetCode(), RelocInfo::CODE_TARGET); | 1834 jmp(ces.GetCode(), RelocInfo::CODE_TARGET); |
1906 } | 1835 } |
1907 | 1836 |
1908 | 1837 |
1909 MaybeObject* MacroAssembler::TryJumpToExternalReference( | |
1910 const ExternalReference& ext) { | |
1911 // Set the entry point and jump to the C entry runtime stub. | |
1912 mov(ebx, Immediate(ext)); | |
1913 CEntryStub ces(1); | |
1914 return TryTailCallStub(&ces); | |
1915 } | |
1916 | |
1917 | |
1918 void MacroAssembler::SetCallKind(Register dst, CallKind call_kind) { | 1838 void MacroAssembler::SetCallKind(Register dst, CallKind call_kind) { |
1919 // This macro takes the dst register to make the code more readable | 1839 // This macro takes the dst register to make the code more readable |
1920 // at the call sites. However, the dst register has to be ecx to | 1840 // at the call sites. However, the dst register has to be ecx to |
1921 // follow the calling convention which requires the call type to be | 1841 // follow the calling convention which requires the call type to be |
1922 // in ecx. | 1842 // in ecx. |
1923 ASSERT(dst.is(ecx)); | 1843 ASSERT(dst.is(ecx)); |
1924 if (call_kind == CALL_AS_FUNCTION) { | 1844 if (call_kind == CALL_AS_FUNCTION) { |
1925 // Set to some non-zero smi by updating the least significant | 1845 // Set to some non-zero smi by updating the least significant |
1926 // byte. | 1846 // byte. |
1927 mov_b(dst, 1 << kSmiTagSize); | 1847 mov_b(dst, 1 << kSmiTagSize); |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2072 mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 1992 mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
2073 mov(ebx, FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset)); | 1993 mov(ebx, FieldOperand(edx, SharedFunctionInfo::kFormalParameterCountOffset)); |
2074 SmiUntag(ebx); | 1994 SmiUntag(ebx); |
2075 | 1995 |
2076 ParameterCount expected(ebx); | 1996 ParameterCount expected(ebx); |
2077 InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), | 1997 InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), |
2078 expected, actual, flag, call_wrapper, call_kind); | 1998 expected, actual, flag, call_wrapper, call_kind); |
2079 } | 1999 } |
2080 | 2000 |
2081 | 2001 |
2082 void MacroAssembler::InvokeFunction(JSFunction* function, | 2002 void MacroAssembler::InvokeFunction(Handle<JSFunction> function, |
2083 const ParameterCount& actual, | 2003 const ParameterCount& actual, |
2084 InvokeFlag flag, | 2004 InvokeFlag flag, |
2085 const CallWrapper& call_wrapper, | 2005 const CallWrapper& call_wrapper, |
2086 CallKind call_kind) { | 2006 CallKind call_kind) { |
2087 // You can't call a function without a valid frame. | 2007 // You can't call a function without a valid frame. |
2088 ASSERT(flag == JUMP_FUNCTION || has_frame()); | 2008 ASSERT(flag == JUMP_FUNCTION || has_frame()); |
2089 | 2009 |
2090 // Get the function and setup the context. | 2010 // Get the function and setup the context. |
2091 mov(edi, Immediate(Handle<JSFunction>(function))); | 2011 mov(edi, Immediate(function)); |
2092 mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); | 2012 mov(esi, FieldOperand(edi, JSFunction::kContextOffset)); |
2093 | 2013 |
2094 ParameterCount expected(function->shared()->formal_parameter_count()); | 2014 ParameterCount expected(function->shared()->formal_parameter_count()); |
2095 // We call indirectly through the code field in the function to | 2015 // We call indirectly through the code field in the function to |
2096 // allow recompilation to take effect without changing any of the | 2016 // allow recompilation to take effect without changing any of the |
2097 // call sites. | 2017 // call sites. |
2098 InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), | 2018 InvokeCode(FieldOperand(edi, JSFunction::kCodeEntryOffset), |
2099 expected, actual, flag, call_wrapper, call_kind); | 2019 expected, actual, flag, call_wrapper, call_kind); |
2100 } | 2020 } |
2101 | 2021 |
(...skipping 625 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2727 cmp(length, Operand(bitmap_scratch, MemoryChunk::kSizeOffset)); | 2647 cmp(length, Operand(bitmap_scratch, MemoryChunk::kSizeOffset)); |
2728 Check(less_equal, "Live Bytes Count overflow chunk size"); | 2648 Check(less_equal, "Live Bytes Count overflow chunk size"); |
2729 } | 2649 } |
2730 | 2650 |
2731 bind(&done); | 2651 bind(&done); |
2732 } | 2652 } |
2733 | 2653 |
2734 } } // namespace v8::internal | 2654 } } // namespace v8::internal |
2735 | 2655 |
2736 #endif // V8_TARGET_ARCH_IA32 | 2656 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |