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_ARM | 5 #if V8_TARGET_ARCH_ARM |
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 namespace v8 { | 13 namespace v8 { |
14 namespace internal { | 14 namespace internal { |
15 | 15 |
16 | 16 |
17 #define __ ACCESS_MASM(masm) | 17 #define __ ACCESS_MASM(masm) |
18 | 18 |
19 | 19 |
20 void Builtins::Generate_Adaptor(MacroAssembler* masm, | 20 void Builtins::Generate_Adaptor(MacroAssembler* masm, |
21 CFunctionId id, | 21 CFunctionId id, |
22 BuiltinExtraArguments extra_args) { | 22 BuiltinExtraArguments extra_args) { |
23 // ----------- S t a t e ------------- | 23 // ----------- S t a t e ------------- |
24 // -- r0 : number of arguments excluding receiver | 24 // -- r0 : number of arguments excluding receiver |
25 // -- r1 : called function (only guaranteed when | 25 // -- r1 : called function (only guaranteed when |
26 // extra_args requires it) | 26 // extra_args requires it) |
27 // -- cp : context | |
28 // -- sp[0] : last argument | 27 // -- sp[0] : last argument |
29 // -- ... | 28 // -- ... |
30 // -- sp[4 * (argc - 1)] : first argument (argc == r0) | 29 // -- sp[4 * (argc - 1)] : first argument (argc == r0) |
31 // -- sp[4 * argc] : receiver | 30 // -- sp[4 * argc] : receiver |
32 // ----------------------------------- | 31 // ----------------------------------- |
| 32 __ AssertFunction(r1); |
| 33 |
| 34 // Make sure we operate in the context of the called function (for example |
| 35 // ConstructStubs implemented in C++ will be run in the context of the caller |
| 36 // instead of the callee, due to the way that [[Construct]] is defined for |
| 37 // ordinary functions). |
| 38 // TODO(bmeurer): Can we make this more robust? |
| 39 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
33 | 40 |
34 // Insert extra arguments. | 41 // Insert extra arguments. |
35 int num_extra_args = 0; | 42 int num_extra_args = 0; |
36 if (extra_args == NEEDS_CALLED_FUNCTION) { | 43 if (extra_args == NEEDS_CALLED_FUNCTION) { |
37 num_extra_args = 1; | 44 num_extra_args = 1; |
38 __ push(r1); | 45 __ push(r1); |
39 } else { | 46 } else { |
40 DCHECK(extra_args == NO_EXTRA_ARGUMENTS); | 47 DCHECK(extra_args == NO_EXTRA_ARGUMENTS); |
41 } | 48 } |
42 | 49 |
(...skipping 680 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
723 __ Push(r1, argc); | 730 __ Push(r1, argc); |
724 __ CallRuntime(Runtime::kThrowStackOverflow, 0); | 731 __ CallRuntime(Runtime::kThrowStackOverflow, 0); |
725 | 732 |
726 __ bind(&okay); | 733 __ bind(&okay); |
727 } | 734 } |
728 | 735 |
729 | 736 |
730 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, | 737 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, |
731 bool is_construct) { | 738 bool is_construct) { |
732 // Called from Generate_JS_Entry | 739 // Called from Generate_JS_Entry |
733 // r0: code entry | 740 // r0: new.target |
734 // r1: function | 741 // r1: function |
735 // r2: receiver | 742 // r2: receiver |
736 // r3: argc | 743 // r3: argc |
737 // r4: argv | 744 // r4: argv |
738 // r5-r6, r8 (if !FLAG_enable_embedded_constant_pool) and cp may be clobbered | 745 // r5-r6, r8 (if !FLAG_enable_embedded_constant_pool) and cp may be clobbered |
739 ProfileEntryHookStub::MaybeCallEntryHook(masm); | 746 ProfileEntryHookStub::MaybeCallEntryHook(masm); |
740 | 747 |
741 // Clear the context before we push it when entering the internal frame. | 748 // Clear the context before we push it when entering the internal frame. |
742 __ mov(cp, Operand::Zero()); | 749 __ mov(cp, Operand::Zero()); |
743 | 750 |
744 // Enter an internal frame. | 751 // Enter an internal frame. |
745 { | 752 { |
746 FrameScope scope(masm, StackFrame::INTERNAL); | 753 FrameScope scope(masm, StackFrame::INTERNAL); |
747 | 754 |
748 // Set up the context from the function argument. | 755 // Setup the context (we need to use the caller context from the isolate). |
749 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | 756 ExternalReference context_address(Isolate::kContextAddress, |
| 757 masm->isolate()); |
| 758 __ mov(cp, Operand(context_address)); |
| 759 __ ldr(cp, MemOperand(cp)); |
750 | 760 |
751 __ InitializeRootRegister(); | 761 __ InitializeRootRegister(); |
752 | 762 |
753 // Push the function and the receiver onto the stack. | 763 // Push the function and the receiver onto the stack. |
754 __ push(r1); | 764 __ Push(r1, r2); |
755 __ push(r2); | |
756 | 765 |
757 // Check if we have enough stack space to push all arguments. | 766 // Check if we have enough stack space to push all arguments. |
758 // The function is the first thing that was pushed above after entering | 767 // The function is the first thing that was pushed above after entering |
759 // the internal frame. | 768 // the internal frame. |
760 const int kFunctionOffset = | 769 const int kFunctionOffset = |
761 InternalFrameConstants::kCodeOffset - kPointerSize; | 770 InternalFrameConstants::kCodeOffset - kPointerSize; |
762 // Clobbers r2. | 771 // Clobbers r2. |
763 Generate_CheckStackOverflow(masm, kFunctionOffset, r3, kArgcIsUntaggedInt); | 772 Generate_CheckStackOverflow(masm, kFunctionOffset, r3, kArgcIsUntaggedInt); |
764 | 773 |
| 774 // Remember new.target. |
| 775 __ mov(r5, r0); |
| 776 |
765 // Copy arguments to the stack in a loop. | 777 // Copy arguments to the stack in a loop. |
766 // r1: function | 778 // r1: function |
767 // r3: argc | 779 // r3: argc |
768 // r4: argv, i.e. points to first arg | 780 // r4: argv, i.e. points to first arg |
769 Label loop, entry; | 781 Label loop, entry; |
770 __ add(r2, r4, Operand(r3, LSL, kPointerSizeLog2)); | 782 __ add(r2, r4, Operand(r3, LSL, kPointerSizeLog2)); |
771 // r2 points past last arg. | 783 // r2 points past last arg. |
772 __ b(&entry); | 784 __ b(&entry); |
773 __ bind(&loop); | 785 __ bind(&loop); |
774 __ ldr(r0, MemOperand(r4, kPointerSize, PostIndex)); // read next parameter | 786 __ ldr(r0, MemOperand(r4, kPointerSize, PostIndex)); // read next parameter |
775 __ ldr(r0, MemOperand(r0)); // dereference handle | 787 __ ldr(r0, MemOperand(r0)); // dereference handle |
776 __ push(r0); // push parameter | 788 __ push(r0); // push parameter |
777 __ bind(&entry); | 789 __ bind(&entry); |
778 __ cmp(r4, r2); | 790 __ cmp(r4, r2); |
779 __ b(ne, &loop); | 791 __ b(ne, &loop); |
780 | 792 |
| 793 // Setup new.target and argc. |
| 794 __ mov(r0, Operand(r3)); |
| 795 __ mov(r3, Operand(r5)); |
| 796 |
781 // Initialize all JavaScript callee-saved registers, since they will be seen | 797 // Initialize all JavaScript callee-saved registers, since they will be seen |
782 // by the garbage collector as part of handlers. | 798 // by the garbage collector as part of handlers. |
783 __ LoadRoot(r4, Heap::kUndefinedValueRootIndex); | 799 __ LoadRoot(r4, Heap::kUndefinedValueRootIndex); |
784 __ mov(r5, Operand(r4)); | 800 __ mov(r5, Operand(r4)); |
785 __ mov(r6, Operand(r4)); | 801 __ mov(r6, Operand(r4)); |
786 if (!FLAG_enable_embedded_constant_pool) { | 802 if (!FLAG_enable_embedded_constant_pool) { |
787 __ mov(r8, Operand(r4)); | 803 __ mov(r8, Operand(r4)); |
788 } | 804 } |
789 if (kR9Available == 1) { | 805 if (kR9Available == 1) { |
790 __ mov(r9, Operand(r4)); | 806 __ mov(r9, Operand(r4)); |
791 } | 807 } |
792 | 808 |
793 // Invoke the code and pass argc as r0. | 809 // Invoke the code. |
794 __ mov(r0, Operand(r3)); | 810 Handle<Code> builtin = is_construct |
795 if (is_construct) { | 811 ? masm->isolate()->builtins()->Construct() |
796 // No type feedback cell is available | 812 : masm->isolate()->builtins()->Call(); |
797 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); | 813 __ Call(builtin, RelocInfo::CODE_TARGET); |
798 CallConstructStub stub(masm->isolate(), NO_CALL_CONSTRUCTOR_FLAGS); | 814 |
799 __ CallStub(&stub); | |
800 } else { | |
801 __ Call(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); | |
802 } | |
803 // Exit the JS frame and remove the parameters (except function), and | 815 // Exit the JS frame and remove the parameters (except function), and |
804 // return. | 816 // return. |
805 // Respect ABI stack constraint. | 817 // Respect ABI stack constraint. |
806 } | 818 } |
807 __ Jump(lr); | 819 __ Jump(lr); |
808 | 820 |
809 // r0: result | 821 // r0: result |
810 } | 822 } |
811 | 823 |
812 | 824 |
(...skipping 796 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1609 __ Pop(r0); | 1621 __ Pop(r0); |
1610 __ SmiUntag(r0); | 1622 __ SmiUntag(r0); |
1611 } | 1623 } |
1612 // The delegate is always a regular function. | 1624 // The delegate is always a regular function. |
1613 __ AssertFunction(r1); | 1625 __ AssertFunction(r1); |
1614 __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET); | 1626 __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET); |
1615 } | 1627 } |
1616 | 1628 |
1617 | 1629 |
1618 // static | 1630 // static |
| 1631 void Builtins::Generate_ConstructFunction(MacroAssembler* masm) { |
| 1632 // ----------- S t a t e ------------- |
| 1633 // -- r0 : the number of arguments (not including the receiver) |
| 1634 // -- r1 : the constructor to call (checked to be a JSFunction) |
| 1635 // -- r3 : the original constructor (checked to be a JSFunction) |
| 1636 // ----------------------------------- |
| 1637 __ AssertFunction(r1); |
| 1638 __ AssertFunction(r3); |
| 1639 |
| 1640 // Calling convention for function specific ConstructStubs require |
| 1641 // r2 to contain either an AllocationSite or undefined. |
| 1642 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); |
| 1643 |
| 1644 // Tail call to the function-specific construct stub (still in the caller |
| 1645 // context at this point). |
| 1646 __ ldr(r4, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
| 1647 __ ldr(r4, FieldMemOperand(r4, SharedFunctionInfo::kConstructStubOffset)); |
| 1648 __ add(pc, r4, Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 1649 } |
| 1650 |
| 1651 |
| 1652 // static |
| 1653 void Builtins::Generate_Construct(MacroAssembler* masm) { |
| 1654 // ----------- S t a t e ------------- |
| 1655 // -- r0 : the number of arguments (not including the receiver) |
| 1656 // -- r1 : the constructor to call (can be any Object) |
| 1657 // -- r3 : the original constructor (either the same as the constructor or |
| 1658 // the JSFunction on which new was invoked initially) |
| 1659 // ----------------------------------- |
| 1660 |
| 1661 Label slow; |
| 1662 __ JumpIfSmi(r1, &slow); |
| 1663 __ CompareObjectType(r1, r5, r5, JS_FUNCTION_TYPE); |
| 1664 __ Jump(masm->isolate()->builtins()->ConstructFunction(), |
| 1665 RelocInfo::CODE_TARGET, eq); |
| 1666 __ cmp(r5, Operand(JS_FUNCTION_PROXY_TYPE)); |
| 1667 __ b(ne, &slow); |
| 1668 |
| 1669 // TODO(neis): This doesn't match the ES6 spec for [[Construct]] on proxies. |
| 1670 __ ldr(r1, FieldMemOperand(r1, JSFunctionProxy::kConstructTrapOffset)); |
| 1671 __ Jump(masm->isolate()->builtins()->Call(), RelocInfo::CODE_TARGET); |
| 1672 |
| 1673 __ bind(&slow); |
| 1674 { |
| 1675 // Determine the delegate for the target (if any). |
| 1676 FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL); |
| 1677 __ SmiTag(r0); |
| 1678 __ Push(r0, r1); |
| 1679 __ CallRuntime(Runtime::kGetConstructorDelegate, 1); |
| 1680 __ mov(r1, r0); |
| 1681 __ Pop(r0); |
| 1682 __ SmiUntag(r0); |
| 1683 } |
| 1684 // The delegate is always a regular function. |
| 1685 __ AssertFunction(r1); |
| 1686 __ Jump(masm->isolate()->builtins()->CallFunction(), RelocInfo::CODE_TARGET); |
| 1687 } |
| 1688 |
| 1689 |
| 1690 // static |
1619 void Builtins::Generate_PushArgsAndCall(MacroAssembler* masm) { | 1691 void Builtins::Generate_PushArgsAndCall(MacroAssembler* masm) { |
1620 // ----------- S t a t e ------------- | 1692 // ----------- S t a t e ------------- |
1621 // -- r0 : the number of arguments (not including the receiver) | 1693 // -- r0 : the number of arguments (not including the receiver) |
1622 // -- r2 : the address of the first argument to be pushed. Subsequent | 1694 // -- r2 : the address of the first argument to be pushed. Subsequent |
1623 // arguments should be consecutive above this, in the same order as | 1695 // arguments should be consecutive above this, in the same order as |
1624 // they are to be pushed onto the stack. | 1696 // they are to be pushed onto the stack. |
1625 // -- r1 : the target to call (can be any Object). | 1697 // -- r1 : the target to call (can be any Object). |
1626 | 1698 |
1627 // Find the address of the last argument. | 1699 // Find the address of the last argument. |
1628 __ add(r3, r0, Operand(1)); // Add one for receiver. | 1700 __ add(r3, r0, Operand(1)); // Add one for receiver. |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1787 } | 1859 } |
1788 } | 1860 } |
1789 | 1861 |
1790 | 1862 |
1791 #undef __ | 1863 #undef __ |
1792 | 1864 |
1793 } // namespace internal | 1865 } // namespace internal |
1794 } // namespace v8 | 1866 } // namespace v8 |
1795 | 1867 |
1796 #endif // V8_TARGET_ARCH_ARM | 1868 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |