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 |