| OLD | NEW |
| 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 #if V8_TARGET_ARCH_MIPS | 5 #if V8_TARGET_ARCH_MIPS |
| 6 | 6 |
| 7 #include "src/codegen.h" | 7 #include "src/codegen.h" |
| 8 #include "src/debug/debug.h" | 8 #include "src/debug/debug.h" |
| 9 #include "src/deoptimizer.h" | 9 #include "src/deoptimizer.h" |
| 10 #include "src/full-codegen/full-codegen.h" | 10 #include "src/full-codegen/full-codegen.h" |
| 11 #include "src/runtime/runtime.h" | 11 #include "src/runtime/runtime.h" |
| 12 | 12 |
| 13 | 13 |
| 14 namespace v8 { | 14 namespace v8 { |
| 15 namespace internal { | 15 namespace internal { |
| 16 | 16 |
| 17 | 17 |
| 18 #define __ ACCESS_MASM(masm) | 18 #define __ ACCESS_MASM(masm) |
| 19 | 19 |
| 20 | 20 |
| 21 void Builtins::Generate_Adaptor(MacroAssembler* masm, | 21 void Builtins::Generate_Adaptor(MacroAssembler* masm, |
| 22 CFunctionId id, | 22 CFunctionId id, |
| 23 BuiltinExtraArguments extra_args) { | 23 BuiltinExtraArguments extra_args) { |
| 24 // ----------- S t a t e ------------- | 24 // ----------- S t a t e ------------- |
| 25 // -- a0 : number of arguments excluding receiver | 25 // -- a0 : number of arguments excluding receiver |
| 26 // -- a1 : called function (only guaranteed when | 26 // -- a1 : called function (only guaranteed when |
| 27 // -- extra_args requires it) | 27 // -- extra_args requires it) |
| 28 // -- cp : context | |
| 29 // -- sp[0] : last argument | 28 // -- sp[0] : last argument |
| 30 // -- ... | 29 // -- ... |
| 31 // -- sp[4 * (argc - 1)] : first argument | 30 // -- sp[4 * (argc - 1)] : first argument |
| 32 // -- sp[4 * agrc] : receiver | 31 // -- sp[4 * agrc] : receiver |
| 33 // ----------------------------------- | 32 // ----------------------------------- |
| 33 __ AssertFunction(a1); |
| 34 |
| 35 // Make sure we operate in the context of the called function (for example |
| 36 // ConstructStubs implemented in C++ will be run in the context of the caller |
| 37 // instead of the callee, due to the way that [[Construct]] is defined for |
| 38 // ordinary functions). |
| 39 // TODO(bmeurer): Can we make this more robust? |
| 40 __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); |
| 34 | 41 |
| 35 // Insert extra arguments. | 42 // Insert extra arguments. |
| 36 int num_extra_args = 0; | 43 int num_extra_args = 0; |
| 37 if (extra_args == NEEDS_CALLED_FUNCTION) { | 44 if (extra_args == NEEDS_CALLED_FUNCTION) { |
| 38 num_extra_args = 1; | 45 num_extra_args = 1; |
| 39 __ push(a1); | 46 __ push(a1); |
| 40 } else { | 47 } else { |
| 41 DCHECK(extra_args == NO_EXTRA_ARGUMENTS); | 48 DCHECK(extra_args == NO_EXTRA_ARGUMENTS); |
| 42 } | 49 } |
| 43 | 50 |
| (...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 724 | 731 |
| 725 __ bind(&okay); | 732 __ bind(&okay); |
| 726 } | 733 } |
| 727 | 734 |
| 728 | 735 |
| 729 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, | 736 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, |
| 730 bool is_construct) { | 737 bool is_construct) { |
| 731 // Called from JSEntryStub::GenerateBody | 738 // Called from JSEntryStub::GenerateBody |
| 732 | 739 |
| 733 // ----------- S t a t e ------------- | 740 // ----------- S t a t e ------------- |
| 734 // -- a0: code entry | 741 // -- a0: new.target |
| 735 // -- a1: function | 742 // -- a1: function |
| 736 // -- a2: receiver_pointer | 743 // -- a2: receiver_pointer |
| 737 // -- a3: argc | 744 // -- a3: argc |
| 738 // -- s0: argv | 745 // -- s0: argv |
| 739 // ----------------------------------- | 746 // ----------------------------------- |
| 740 ProfileEntryHookStub::MaybeCallEntryHook(masm); | 747 ProfileEntryHookStub::MaybeCallEntryHook(masm); |
| 741 | 748 |
| 742 // Clear the context before we push it when entering the JS frame. | 749 // Clear the context before we push it when entering the JS frame. |
| 743 __ mov(cp, zero_reg); | 750 __ mov(cp, zero_reg); |
| 744 | 751 |
| 745 // Enter an internal frame. | 752 // Enter an internal frame. |
| 746 { | 753 { |
| 747 FrameScope scope(masm, StackFrame::INTERNAL); | 754 FrameScope scope(masm, StackFrame::INTERNAL); |
| 748 | 755 |
| 749 // Set up the context from the function argument. | 756 // Setup the context (we need to use the caller context from the isolate). |
| 750 __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); | 757 ExternalReference context_address(Isolate::kContextAddress, |
| 758 masm->isolate()); |
| 759 __ li(cp, Operand(context_address)); |
| 760 __ lw(cp, MemOperand(cp)); |
| 751 | 761 |
| 752 // Push the function and the receiver onto the stack. | 762 // Push the function and the receiver onto the stack. |
| 753 __ Push(a1, a2); | 763 __ Push(a1, a2); |
| 754 | 764 |
| 755 // Check if we have enough stack space to push all arguments. | 765 // Check if we have enough stack space to push all arguments. |
| 756 // The function is the first thing that was pushed above after entering | 766 // The function is the first thing that was pushed above after entering |
| 757 // the internal frame. | 767 // the internal frame. |
| 758 const int kFunctionOffset = | 768 const int kFunctionOffset = |
| 759 InternalFrameConstants::kCodeOffset - kPointerSize; | 769 InternalFrameConstants::kCodeOffset - kPointerSize; |
| 760 // Clobbers a2. | 770 // Clobbers a2. |
| 761 Generate_CheckStackOverflow(masm, kFunctionOffset, a3, kArgcIsUntaggedInt); | 771 Generate_CheckStackOverflow(masm, kFunctionOffset, a3, kArgcIsUntaggedInt); |
| 762 | 772 |
| 773 // Remember new.target. |
| 774 __ mov(t1, a0); |
| 775 |
| 763 // Copy arguments to the stack in a loop. | 776 // Copy arguments to the stack in a loop. |
| 764 // a3: argc | 777 // a3: argc |
| 765 // s0: argv, i.e. points to first arg | 778 // s0: argv, i.e. points to first arg |
| 766 Label loop, entry; | 779 Label loop, entry; |
| 767 __ sll(t0, a3, kPointerSizeLog2); | 780 __ sll(t0, a3, kPointerSizeLog2); |
| 768 __ addu(t2, s0, t0); | 781 __ addu(t2, s0, t0); |
| 769 __ b(&entry); | 782 __ b(&entry); |
| 770 __ nop(); // Branch delay slot nop. | 783 __ nop(); // Branch delay slot nop. |
| 771 // t2 points past last arg. | 784 // t2 points past last arg. |
| 772 __ bind(&loop); | 785 __ bind(&loop); |
| 773 __ lw(t0, MemOperand(s0)); // Read next parameter. | 786 __ lw(t0, MemOperand(s0)); // Read next parameter. |
| 774 __ addiu(s0, s0, kPointerSize); | 787 __ addiu(s0, s0, kPointerSize); |
| 775 __ lw(t0, MemOperand(t0)); // Dereference handle. | 788 __ lw(t0, MemOperand(t0)); // Dereference handle. |
| 776 __ push(t0); // Push parameter. | 789 __ push(t0); // Push parameter. |
| 777 __ bind(&entry); | 790 __ bind(&entry); |
| 778 __ Branch(&loop, ne, s0, Operand(t2)); | 791 __ Branch(&loop, ne, s0, Operand(t2)); |
| 779 | 792 |
| 793 // Setup new.target and argc. |
| 794 __ mov(a0, a3); |
| 795 __ mov(a3, t1); |
| 796 |
| 780 // Initialize all JavaScript callee-saved registers, since they will be seen | 797 // Initialize all JavaScript callee-saved registers, since they will be seen |
| 781 // by the garbage collector as part of handlers. | 798 // by the garbage collector as part of handlers. |
| 782 __ LoadRoot(t0, Heap::kUndefinedValueRootIndex); | 799 __ LoadRoot(t0, Heap::kUndefinedValueRootIndex); |
| 783 __ mov(s1, t0); | 800 __ mov(s1, t0); |
| 784 __ mov(s2, t0); | 801 __ mov(s2, t0); |
| 785 __ mov(s3, t0); | 802 __ mov(s3, t0); |
| 786 __ mov(s4, t0); | 803 __ mov(s4, t0); |
| 787 __ mov(s5, t0); | 804 __ mov(s5, t0); |
| 788 // s6 holds the root address. Do not clobber. | 805 // s6 holds the root address. Do not clobber. |
| 789 // s7 is cp. Do not init. | 806 // s7 is cp. Do not init. |
| 790 | 807 |
| 791 // Invoke the code and pass argc as a0. | 808 // Invoke the code. |
| 792 __ mov(a0, a3); | 809 Handle<Code> builtin = is_construct |
| 793 if (is_construct) { | 810 ? masm->isolate()->builtins()->Construct() |
| 794 // No type feedback cell is available | 811 : masm->isolate()->builtins()->Call(); |
| 795 __ LoadRoot(a2, Heap::kUndefinedValueRootIndex); | 812 __ Call(builtin, RelocInfo::CODE_TARGET); |
| 796 CallConstructStub stub(masm->isolate(), NO_CALL_CONSTRUCTOR_FLAGS); | |
| 797 __ CallStub(&stub); | |
| 798 } else { | |
| 799 __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | |
| 800 } | |
| 801 | 813 |
| 802 // Leave internal frame. | 814 // Leave internal frame. |
| 803 } | 815 } |
| 804 | 816 |
| 805 __ Jump(ra); | 817 __ Jump(ra); |
| 806 } | 818 } |
| 807 | 819 |
| 808 | 820 |
| 809 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { | 821 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { |
| 810 Generate_JSEntryTrampolineHelper(masm, false); | 822 Generate_JSEntryTrampolineHelper(masm, false); |
| (...skipping 811 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1622 __ Pop(a0); | 1634 __ Pop(a0); |
| 1623 __ sra(a0, a0, kSmiTagSize); // Un-tag. | 1635 __ sra(a0, a0, kSmiTagSize); // Un-tag. |
| 1624 } | 1636 } |
| 1625 // The delegate is always a regular function. | 1637 // The delegate is always a regular function. |
| 1626 __ AssertFunction(a1); | 1638 __ AssertFunction(a1); |
| 1627 __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET); | 1639 __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET); |
| 1628 } | 1640 } |
| 1629 | 1641 |
| 1630 | 1642 |
| 1631 // static | 1643 // static |
| 1644 void Builtins::Generate_ConstructFunction(MacroAssembler* masm) { |
| 1645 // ----------- S t a t e ------------- |
| 1646 // -- a0 : the number of arguments (not including the receiver) |
| 1647 // -- a1 : the constructor to call (checked to be a JSFunction) |
| 1648 // -- a3 : the original constructor (checked to be a JSFunction) |
| 1649 // ----------------------------------- |
| 1650 __ AssertFunction(a1); |
| 1651 __ AssertFunction(a3); |
| 1652 |
| 1653 // Calling convention for function specific ConstructStubs require |
| 1654 // a2 to contain either an AllocationSite or undefined. |
| 1655 __ LoadRoot(a2, Heap::kUndefinedValueRootIndex); |
| 1656 |
| 1657 // Tail call to the function-specific construct stub (still in the caller |
| 1658 // context at this point). |
| 1659 __ lw(t0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); |
| 1660 __ lw(t0, FieldMemOperand(t0, SharedFunctionInfo::kConstructStubOffset)); |
| 1661 __ Addu(at, t0, Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 1662 __ Jump(at); |
| 1663 } |
| 1664 |
| 1665 |
| 1666 // static |
| 1667 void Builtins::Generate_Construct(MacroAssembler* masm) { |
| 1668 // ----------- S t a t e ------------- |
| 1669 // -- a0 : the number of arguments (not including the receiver) |
| 1670 // -- a1 : the constructor to call (can be any Object) |
| 1671 // -- a3 : the original constructor (either the same as the constructor or |
| 1672 // the JSFunction on which new was invoked initially) |
| 1673 // ----------------------------------- |
| 1674 |
| 1675 Label slow; |
| 1676 __ JumpIfSmi(a1, &slow); |
| 1677 __ GetObjectType(a1, t1, t1); |
| 1678 __ Jump(masm->isolate()->builtins()->ConstructFunction(), |
| 1679 RelocInfo::CODE_TARGET, eq, t1, Operand(JS_FUNCTION_TYPE)); |
| 1680 __ Branch(&slow, ne, t1, Operand(JS_FUNCTION_PROXY_TYPE)); |
| 1681 |
| 1682 // TODO(neis): This doesn't match the ES6 spec for [[Construct]] on proxies. |
| 1683 __ lw(a1, FieldMemOperand(a1, JSFunctionProxy::kConstructTrapOffset)); |
| 1684 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
| 1685 |
| 1686 __ bind(&slow); |
| 1687 { |
| 1688 // Determine the delegate for the target (if any). |
| 1689 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1690 __ SmiTag(a0); |
| 1691 __ Push(a0, a1); |
| 1692 __ CallRuntime(Runtime::kGetConstructorDelegate, 1); |
| 1693 __ mov(a1, v0); |
| 1694 __ Pop(a0); |
| 1695 __ SmiUntag(a0); |
| 1696 } |
| 1697 // The delegate is always a regular function. |
| 1698 __ AssertFunction(a1); |
| 1699 __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET); |
| 1700 } |
| 1701 |
| 1702 |
| 1703 // static |
| 1632 void Builtins::Generate_PushArgsAndCall(MacroAssembler* masm) { | 1704 void Builtins::Generate_PushArgsAndCall(MacroAssembler* masm) { |
| 1633 // ----------- S t a t e ------------- | 1705 // ----------- S t a t e ------------- |
| 1634 // -- a0 : the number of arguments (not including the receiver) | 1706 // -- a0 : the number of arguments (not including the receiver) |
| 1635 // -- a2 : the address of the first argument to be pushed. Subsequent | 1707 // -- a2 : the address of the first argument to be pushed. Subsequent |
| 1636 // arguments should be consecutive above this, in the same order as | 1708 // arguments should be consecutive above this, in the same order as |
| 1637 // they are to be pushed onto the stack. | 1709 // they are to be pushed onto the stack. |
| 1638 // -- a1 : the target to call (can be any Object). | 1710 // -- a1 : the target to call (can be any Object). |
| 1639 | 1711 |
| 1640 // Find the address of the last argument. | 1712 // Find the address of the last argument. |
| 1641 __ Addu(a3, a0, Operand(1)); // Add one for receiver. | 1713 __ Addu(a3, a0, Operand(1)); // Add one for receiver. |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1809 } | 1881 } |
| 1810 } | 1882 } |
| 1811 | 1883 |
| 1812 | 1884 |
| 1813 #undef __ | 1885 #undef __ |
| 1814 | 1886 |
| 1815 } // namespace internal | 1887 } // namespace internal |
| 1816 } // namespace v8 | 1888 } // namespace v8 |
| 1817 | 1889 |
| 1818 #endif // V8_TARGET_ARCH_MIPS | 1890 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |