OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 1592 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1603 isolate->set_fp_stubs_generated(true); | 1603 isolate->set_fp_stubs_generated(true); |
1604 } | 1604 } |
1605 | 1605 |
1606 | 1606 |
1607 void CEntryStub::GenerateAheadOfTime(Isolate* isolate) { | 1607 void CEntryStub::GenerateAheadOfTime(Isolate* isolate) { |
1608 CEntryStub stub(1, kDontSaveFPRegs); | 1608 CEntryStub stub(1, kDontSaveFPRegs); |
1609 stub.GetCode(isolate); | 1609 stub.GetCode(isolate); |
1610 } | 1610 } |
1611 | 1611 |
1612 | 1612 |
1613 void CEntryStub::GenerateCore(MacroAssembler* masm, | 1613 void CEntryStub::Generate(MacroAssembler* masm) { |
1614 Label* throw_normal_exception, | 1614 // Called from JavaScript; parameters are on stack as if calling JS function |
1615 Label* throw_termination_exception, | 1615 // s0: number of arguments including receiver |
1616 bool do_gc, | 1616 // s1: size of arguments excluding receiver |
1617 bool always_allocate) { | 1617 // s2: pointer to builtin function |
1618 // v0: result parameter for PerformGC, if any | 1618 // fp: frame pointer (restored after C call) |
1619 // s0: number of arguments including receiver (C callee-saved) | 1619 // sp: stack pointer (restored as callee's sp after C call) |
1620 // s1: pointer to the first argument (C callee-saved) | 1620 // cp: current context (C callee-saved) |
1621 // s2: pointer to builtin function (C callee-saved) | 1621 |
| 1622 ProfileEntryHookStub::MaybeCallEntryHook(masm); |
| 1623 |
| 1624 // NOTE: s0-s2 hold the arguments of this function instead of a0-a2. |
| 1625 // The reason for this is that these arguments would need to be saved anyway |
| 1626 // so it's faster to set them up directly. |
| 1627 // See MacroAssembler::PrepareCEntryArgs and PrepareCEntryFunction. |
| 1628 |
| 1629 // Compute the argv pointer in a callee-saved register. |
| 1630 __ Addu(s1, sp, s1); |
| 1631 |
| 1632 // Enter the exit frame that transitions from JavaScript to C++. |
| 1633 FrameScope scope(masm, StackFrame::MANUAL); |
| 1634 __ EnterExitFrame(save_doubles_); |
| 1635 |
| 1636 // s0: number of arguments including receiver (C callee-saved) |
| 1637 // s1: pointer to first argument (C callee-saved) |
| 1638 // s2: pointer to builtin function (C callee-saved) |
1622 | 1639 |
1623 Isolate* isolate = masm->isolate(); | 1640 Isolate* isolate = masm->isolate(); |
1624 | 1641 |
1625 if (do_gc) { | |
1626 // Move result passed in v0 into a0 to call PerformGC. | |
1627 __ mov(a0, v0); | |
1628 __ PrepareCallCFunction(2, 0, a1); | |
1629 __ li(a1, Operand(ExternalReference::isolate_address(masm->isolate()))); | |
1630 __ CallCFunction(ExternalReference::perform_gc_function(isolate), 2, 0); | |
1631 } | |
1632 | |
1633 ExternalReference scope_depth = | |
1634 ExternalReference::heap_always_allocate_scope_depth(isolate); | |
1635 if (always_allocate) { | |
1636 __ li(a0, Operand(scope_depth)); | |
1637 __ lw(a1, MemOperand(a0)); | |
1638 __ Addu(a1, a1, Operand(1)); | |
1639 __ sw(a1, MemOperand(a0)); | |
1640 } | |
1641 | |
1642 // Prepare arguments for C routine. | 1642 // Prepare arguments for C routine. |
1643 // a0 = argc | 1643 // a0 = argc |
1644 __ mov(a0, s0); | 1644 __ mov(a0, s0); |
1645 // a1 = argv (set in the delay slot after find_ra below). | 1645 // a1 = argv (set in the delay slot after find_ra below). |
1646 | 1646 |
1647 // We are calling compiled C/C++ code. a0 and a1 hold our two arguments. We | 1647 // We are calling compiled C/C++ code. a0 and a1 hold our two arguments. We |
1648 // also need to reserve the 4 argument slots on the stack. | 1648 // also need to reserve the 4 argument slots on the stack. |
1649 | 1649 |
1650 __ AssertStackIsAligned(); | 1650 __ AssertStackIsAligned(); |
1651 | 1651 |
(...skipping 25 matching lines...) Expand all Loading... |
1677 // Call the C routine. | 1677 // Call the C routine. |
1678 masm->mov(t9, s2); // Function pointer to t9 to conform to ABI for PIC. | 1678 masm->mov(t9, s2); // Function pointer to t9 to conform to ABI for PIC. |
1679 masm->jalr(t9); | 1679 masm->jalr(t9); |
1680 // Set up sp in the delay slot. | 1680 // Set up sp in the delay slot. |
1681 masm->addiu(sp, sp, -kCArgsSlotsSize); | 1681 masm->addiu(sp, sp, -kCArgsSlotsSize); |
1682 // Make sure the stored 'ra' points to this position. | 1682 // Make sure the stored 'ra' points to this position. |
1683 ASSERT_EQ(kNumInstructionsToJump, | 1683 ASSERT_EQ(kNumInstructionsToJump, |
1684 masm->InstructionsGeneratedSince(&find_ra)); | 1684 masm->InstructionsGeneratedSince(&find_ra)); |
1685 } | 1685 } |
1686 | 1686 |
1687 if (always_allocate) { | 1687 |
1688 // It's okay to clobber a2 and a3 here. v0 & v1 contain result. | 1688 // Runtime functions should not return 'the hole'. Allowing it to escape may |
1689 __ li(a2, Operand(scope_depth)); | 1689 // lead to crashes in the IC code later. |
1690 __ lw(a3, MemOperand(a2)); | 1690 if (FLAG_debug_code) { |
1691 __ Subu(a3, a3, Operand(1)); | 1691 Label okay; |
1692 __ sw(a3, MemOperand(a2)); | 1692 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); |
| 1693 __ Branch(&okay, ne, v0, Operand(t0)); |
| 1694 __ stop("The hole escaped"); |
| 1695 __ bind(&okay); |
1693 } | 1696 } |
1694 | 1697 |
1695 // Check for failure result. | 1698 // Check result for exception sentinel. |
1696 Label failure_returned; | 1699 Label exception_returned; |
1697 STATIC_ASSERT(((kFailureTag + 1) & kFailureTagMask) == 0); | 1700 __ LoadRoot(t0, Heap::kExceptionRootIndex); |
1698 __ addiu(a2, v0, 1); | 1701 __ Branch(&exception_returned, eq, t0, Operand(v0)); |
1699 __ andi(t0, a2, kFailureTagMask); | |
1700 __ Branch(USE_DELAY_SLOT, &failure_returned, eq, t0, Operand(zero_reg)); | |
1701 // Restore stack (remove arg slots) in branch delay slot. | |
1702 __ addiu(sp, sp, kCArgsSlotsSize); | |
1703 | 1702 |
| 1703 ExternalReference pending_exception_address( |
| 1704 Isolate::kPendingExceptionAddress, isolate); |
| 1705 |
| 1706 // Check that there is no pending exception, otherwise we |
| 1707 // should have returned the exception sentinel. |
| 1708 if (FLAG_debug_code) { |
| 1709 Label okay; |
| 1710 __ li(a2, Operand(pending_exception_address)); |
| 1711 __ lw(a2, MemOperand(a2)); |
| 1712 __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); |
| 1713 // Cannot use check here as it attempts to generate call into runtime. |
| 1714 __ Branch(&okay, eq, t0, Operand(a2)); |
| 1715 __ stop("Unexpected pending exception"); |
| 1716 __ bind(&okay); |
| 1717 } |
1704 | 1718 |
1705 // Exit C frame and return. | 1719 // Exit C frame and return. |
1706 // v0:v1: result | 1720 // v0:v1: result |
1707 // sp: stack pointer | 1721 // sp: stack pointer |
1708 // fp: frame pointer | 1722 // fp: frame pointer |
| 1723 // s0: still holds argc (callee-saved). |
1709 __ LeaveExitFrame(save_doubles_, s0, true, EMIT_RETURN); | 1724 __ LeaveExitFrame(save_doubles_, s0, true, EMIT_RETURN); |
1710 | 1725 |
1711 // Check if we should retry or throw exception. | 1726 // Handling of exception. |
1712 Label retry; | 1727 __ bind(&exception_returned); |
1713 __ bind(&failure_returned); | |
1714 STATIC_ASSERT(Failure::RETRY_AFTER_GC == 0); | |
1715 __ andi(t0, v0, ((1 << kFailureTypeTagSize) - 1) << kFailureTagSize); | |
1716 __ Branch(&retry, eq, t0, Operand(zero_reg)); | |
1717 | 1728 |
1718 // Retrieve the pending exception. | 1729 // Retrieve the pending exception. |
1719 __ li(t0, Operand(ExternalReference(Isolate::kPendingExceptionAddress, | 1730 __ li(a2, Operand(pending_exception_address)); |
1720 isolate))); | 1731 __ lw(v0, MemOperand(a2)); |
1721 __ lw(v0, MemOperand(t0)); | |
1722 | 1732 |
1723 // Clear the pending exception. | 1733 // Clear the pending exception. |
1724 __ li(a3, Operand(isolate->factory()->the_hole_value())); | 1734 __ li(a3, Operand(isolate->factory()->the_hole_value())); |
1725 __ li(t0, Operand(ExternalReference(Isolate::kPendingExceptionAddress, | 1735 __ sw(a3, MemOperand(a2)); |
1726 isolate))); | |
1727 __ sw(a3, MemOperand(t0)); | |
1728 | 1736 |
1729 // Special handling of termination exceptions which are uncatchable | 1737 // Special handling of termination exceptions which are uncatchable |
1730 // by javascript code. | 1738 // by javascript code. |
| 1739 Label throw_termination_exception; |
1731 __ LoadRoot(t0, Heap::kTerminationExceptionRootIndex); | 1740 __ LoadRoot(t0, Heap::kTerminationExceptionRootIndex); |
1732 __ Branch(throw_termination_exception, eq, v0, Operand(t0)); | 1741 __ Branch(&throw_termination_exception, eq, v0, Operand(t0)); |
1733 | 1742 |
1734 // Handle normal exception. | 1743 // Handle normal exception. |
1735 __ jmp(throw_normal_exception); | 1744 __ Throw(v0); |
1736 | 1745 |
1737 __ bind(&retry); | 1746 __ bind(&throw_termination_exception); |
1738 // Last failure (v0) will be moved to (a0) for parameter when retrying. | 1747 __ ThrowUncatchable(v0); |
1739 } | 1748 } |
1740 | 1749 |
1741 | 1750 |
1742 void CEntryStub::Generate(MacroAssembler* masm) { | |
1743 // Called from JavaScript; parameters are on stack as if calling JS function | |
1744 // s0: number of arguments including receiver | |
1745 // s1: size of arguments excluding receiver | |
1746 // s2: pointer to builtin function | |
1747 // fp: frame pointer (restored after C call) | |
1748 // sp: stack pointer (restored as callee's sp after C call) | |
1749 // cp: current context (C callee-saved) | |
1750 | |
1751 ProfileEntryHookStub::MaybeCallEntryHook(masm); | |
1752 | |
1753 // NOTE: Invocations of builtins may return failure objects | |
1754 // instead of a proper result. The builtin entry handles | |
1755 // this by performing a garbage collection and retrying the | |
1756 // builtin once. | |
1757 | |
1758 // NOTE: s0-s2 hold the arguments of this function instead of a0-a2. | |
1759 // The reason for this is that these arguments would need to be saved anyway | |
1760 // so it's faster to set them up directly. | |
1761 // See MacroAssembler::PrepareCEntryArgs and PrepareCEntryFunction. | |
1762 | |
1763 // Compute the argv pointer in a callee-saved register. | |
1764 __ Addu(s1, sp, s1); | |
1765 | |
1766 // Enter the exit frame that transitions from JavaScript to C++. | |
1767 FrameScope scope(masm, StackFrame::MANUAL); | |
1768 __ EnterExitFrame(save_doubles_); | |
1769 | |
1770 // s0: number of arguments (C callee-saved) | |
1771 // s1: pointer to first argument (C callee-saved) | |
1772 // s2: pointer to builtin function (C callee-saved) | |
1773 | |
1774 Label throw_normal_exception; | |
1775 Label throw_termination_exception; | |
1776 | |
1777 // Call into the runtime system. | |
1778 GenerateCore(masm, | |
1779 &throw_normal_exception, | |
1780 &throw_termination_exception, | |
1781 false, | |
1782 false); | |
1783 | |
1784 // Do space-specific GC and retry runtime call. | |
1785 GenerateCore(masm, | |
1786 &throw_normal_exception, | |
1787 &throw_termination_exception, | |
1788 true, | |
1789 false); | |
1790 | |
1791 // Do full GC and retry runtime call one final time. | |
1792 Failure* failure = Failure::InternalError(); | |
1793 __ li(v0, Operand(reinterpret_cast<int32_t>(failure))); | |
1794 GenerateCore(masm, | |
1795 &throw_normal_exception, | |
1796 &throw_termination_exception, | |
1797 true, | |
1798 true); | |
1799 | |
1800 { FrameScope scope(masm, StackFrame::MANUAL); | |
1801 __ PrepareCallCFunction(0, v0); | |
1802 __ CallCFunction( | |
1803 ExternalReference::out_of_memory_function(masm->isolate()), 0); | |
1804 } | |
1805 | |
1806 __ bind(&throw_termination_exception); | |
1807 __ ThrowUncatchable(v0); | |
1808 | |
1809 __ bind(&throw_normal_exception); | |
1810 __ Throw(v0); | |
1811 } | |
1812 | |
1813 | |
1814 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { | 1751 void JSEntryStub::GenerateBody(MacroAssembler* masm, bool is_construct) { |
1815 Label invoke, handler_entry, exit; | 1752 Label invoke, handler_entry, exit; |
1816 Isolate* isolate = masm->isolate(); | 1753 Isolate* isolate = masm->isolate(); |
1817 | 1754 |
1818 // Registers: | 1755 // Registers: |
1819 // a0: entry address | 1756 // a0: entry address |
1820 // a1: function | 1757 // a1: function |
1821 // a2: receiver | 1758 // a2: receiver |
1822 // a3: argc | 1759 // a3: argc |
1823 // | 1760 // |
(...skipping 3629 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5453 MemOperand(fp, 6 * kPointerSize), | 5390 MemOperand(fp, 6 * kPointerSize), |
5454 NULL); | 5391 NULL); |
5455 } | 5392 } |
5456 | 5393 |
5457 | 5394 |
5458 #undef __ | 5395 #undef __ |
5459 | 5396 |
5460 } } // namespace v8::internal | 5397 } } // namespace v8::internal |
5461 | 5398 |
5462 #endif // V8_TARGET_ARCH_MIPS | 5399 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |