| 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 |