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/code-stubs.h" | 7 #include "src/code-stubs.h" |
8 #include "src/api-arguments.h" | 8 #include "src/api-arguments.h" |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 3476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3487 } | 3487 } |
3488 | 3488 |
3489 Label fast_elements_case; | 3489 Label fast_elements_case; |
3490 __ Branch(&fast_elements_case, eq, a3, Operand(FAST_ELEMENTS)); | 3490 __ Branch(&fast_elements_case, eq, a3, Operand(FAST_ELEMENTS)); |
3491 GenerateCase(masm, FAST_HOLEY_ELEMENTS); | 3491 GenerateCase(masm, FAST_HOLEY_ELEMENTS); |
3492 | 3492 |
3493 __ bind(&fast_elements_case); | 3493 __ bind(&fast_elements_case); |
3494 GenerateCase(masm, FAST_ELEMENTS); | 3494 GenerateCase(masm, FAST_ELEMENTS); |
3495 } | 3495 } |
3496 | 3496 |
3497 void FastNewRestParameterStub::Generate(MacroAssembler* masm) { | |
3498 // ----------- S t a t e ------------- | |
3499 // -- a1 : function | |
3500 // -- cp : context | |
3501 // -- fp : frame pointer | |
3502 // -- ra : return address | |
3503 // ----------------------------------- | |
3504 __ AssertFunction(a1); | |
3505 | |
3506 // Make a2 point to the JavaScript frame. | |
3507 __ mov(a2, fp); | |
3508 if (skip_stub_frame()) { | |
3509 // For Ignition we need to skip the handler/stub frame to reach the | |
3510 // JavaScript frame for the function. | |
3511 __ lw(a2, MemOperand(a2, StandardFrameConstants::kCallerFPOffset)); | |
3512 } | |
3513 if (FLAG_debug_code) { | |
3514 Label ok; | |
3515 __ lw(a3, MemOperand(a2, StandardFrameConstants::kFunctionOffset)); | |
3516 __ Branch(&ok, eq, a1, Operand(a3)); | |
3517 __ Abort(kInvalidFrameForFastNewRestArgumentsStub); | |
3518 __ bind(&ok); | |
3519 } | |
3520 | |
3521 // Check if we have rest parameters (only possible if we have an | |
3522 // arguments adaptor frame below the function frame). | |
3523 Label no_rest_parameters; | |
3524 __ lw(a2, MemOperand(a2, StandardFrameConstants::kCallerFPOffset)); | |
3525 __ lw(a3, MemOperand(a2, CommonFrameConstants::kContextOrFrameTypeOffset)); | |
3526 __ Branch(&no_rest_parameters, ne, a3, | |
3527 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | |
3528 | |
3529 // Check if the arguments adaptor frame contains more arguments than | |
3530 // specified by the function's internal formal parameter count. | |
3531 Label rest_parameters; | |
3532 __ lw(a0, MemOperand(a2, ArgumentsAdaptorFrameConstants::kLengthOffset)); | |
3533 __ lw(a3, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); | |
3534 __ lw(a3, | |
3535 FieldMemOperand(a3, SharedFunctionInfo::kFormalParameterCountOffset)); | |
3536 __ Subu(a0, a0, Operand(a3)); | |
3537 __ Branch(&rest_parameters, gt, a0, Operand(zero_reg)); | |
3538 | |
3539 // Return an empty rest parameter array. | |
3540 __ bind(&no_rest_parameters); | |
3541 { | |
3542 // ----------- S t a t e ------------- | |
3543 // -- cp : context | |
3544 // -- ra : return address | |
3545 // ----------------------------------- | |
3546 | |
3547 // Allocate an empty rest parameter array. | |
3548 Label allocate, done_allocate; | |
3549 __ Allocate(JSArray::kSize, v0, a0, a1, &allocate, NO_ALLOCATION_FLAGS); | |
3550 __ bind(&done_allocate); | |
3551 | |
3552 // Setup the rest parameter array in v0. | |
3553 __ LoadNativeContextSlot(Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX, a1); | |
3554 __ sw(a1, FieldMemOperand(v0, JSArray::kMapOffset)); | |
3555 __ LoadRoot(a1, Heap::kEmptyFixedArrayRootIndex); | |
3556 __ sw(a1, FieldMemOperand(v0, JSArray::kPropertiesOffset)); | |
3557 __ sw(a1, FieldMemOperand(v0, JSArray::kElementsOffset)); | |
3558 __ Move(a1, Smi::kZero); | |
3559 __ Ret(USE_DELAY_SLOT); | |
3560 __ sw(a1, FieldMemOperand(v0, JSArray::kLengthOffset)); // In delay slot | |
3561 STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize); | |
3562 | |
3563 // Fall back to %AllocateInNewSpace. | |
3564 __ bind(&allocate); | |
3565 { | |
3566 FrameScope scope(masm, StackFrame::INTERNAL); | |
3567 __ Push(Smi::FromInt(JSArray::kSize)); | |
3568 __ CallRuntime(Runtime::kAllocateInNewSpace); | |
3569 } | |
3570 __ jmp(&done_allocate); | |
3571 } | |
3572 | |
3573 __ bind(&rest_parameters); | |
3574 { | |
3575 // Compute the pointer to the first rest parameter (skippping the receiver). | |
3576 __ Lsa(a2, a2, a0, kPointerSizeLog2 - 1); | |
3577 __ Addu(a2, a2, Operand(StandardFrameConstants::kCallerSPOffset - | |
3578 1 * kPointerSize)); | |
3579 | |
3580 // ----------- S t a t e ------------- | |
3581 // -- cp : context | |
3582 // -- a0 : number of rest parameters (tagged) | |
3583 // -- a1 : function | |
3584 // -- a2 : pointer to first rest parameters | |
3585 // -- ra : return address | |
3586 // ----------------------------------- | |
3587 | |
3588 // Allocate space for the rest parameter array plus the backing store. | |
3589 Label allocate, done_allocate; | |
3590 __ li(t0, Operand(JSArray::kSize + FixedArray::kHeaderSize)); | |
3591 __ Lsa(t0, t0, a0, kPointerSizeLog2 - 1); | |
3592 __ Allocate(t0, v0, a3, t1, &allocate, NO_ALLOCATION_FLAGS); | |
3593 __ bind(&done_allocate); | |
3594 | |
3595 // Setup the elements array in v0. | |
3596 __ LoadRoot(at, Heap::kFixedArrayMapRootIndex); | |
3597 __ sw(at, FieldMemOperand(v0, FixedArray::kMapOffset)); | |
3598 __ sw(a0, FieldMemOperand(v0, FixedArray::kLengthOffset)); | |
3599 __ Addu(a3, v0, Operand(FixedArray::kHeaderSize)); | |
3600 { | |
3601 Label loop, done_loop; | |
3602 __ sll(at, a0, kPointerSizeLog2 - 1); | |
3603 __ Addu(a1, a3, at); | |
3604 __ bind(&loop); | |
3605 __ Branch(&done_loop, eq, a1, Operand(a3)); | |
3606 __ lw(at, MemOperand(a2, 0 * kPointerSize)); | |
3607 __ sw(at, FieldMemOperand(a3, 0 * kPointerSize)); | |
3608 __ Subu(a2, a2, Operand(1 * kPointerSize)); | |
3609 __ Addu(a3, a3, Operand(1 * kPointerSize)); | |
3610 __ jmp(&loop); | |
3611 __ bind(&done_loop); | |
3612 } | |
3613 | |
3614 // Setup the rest parameter array in a3. | |
3615 __ LoadNativeContextSlot(Context::JS_ARRAY_FAST_ELEMENTS_MAP_INDEX, at); | |
3616 __ sw(at, FieldMemOperand(a3, JSArray::kMapOffset)); | |
3617 __ LoadRoot(at, Heap::kEmptyFixedArrayRootIndex); | |
3618 __ sw(at, FieldMemOperand(a3, JSArray::kPropertiesOffset)); | |
3619 __ sw(v0, FieldMemOperand(a3, JSArray::kElementsOffset)); | |
3620 __ sw(a0, FieldMemOperand(a3, JSArray::kLengthOffset)); | |
3621 STATIC_ASSERT(JSArray::kSize == 4 * kPointerSize); | |
3622 __ Ret(USE_DELAY_SLOT); | |
3623 __ mov(v0, a3); // In delay slot | |
3624 | |
3625 // Fall back to %AllocateInNewSpace (if not too big). | |
3626 Label too_big_for_new_space; | |
3627 __ bind(&allocate); | |
3628 __ Branch(&too_big_for_new_space, gt, t0, | |
3629 Operand(kMaxRegularHeapObjectSize)); | |
3630 { | |
3631 FrameScope scope(masm, StackFrame::INTERNAL); | |
3632 __ SmiTag(t0); | |
3633 __ Push(a0, a2, t0); | |
3634 __ CallRuntime(Runtime::kAllocateInNewSpace); | |
3635 __ Pop(a0, a2); | |
3636 } | |
3637 __ jmp(&done_allocate); | |
3638 | |
3639 // Fall back to %NewStrictArguments. | |
3640 __ bind(&too_big_for_new_space); | |
3641 __ Push(a1); | |
3642 __ TailCallRuntime(Runtime::kNewStrictArguments); | |
3643 } | |
3644 } | |
3645 | |
3646 | |
3647 void FastNewSloppyArgumentsStub::Generate(MacroAssembler* masm) { | |
3648 // ----------- S t a t e ------------- | |
3649 // -- a1 : function | |
3650 // -- cp : context | |
3651 // -- fp : frame pointer | |
3652 // -- ra : return address | |
3653 // ----------------------------------- | |
3654 __ AssertFunction(a1); | |
3655 | |
3656 // Make t0 point to the JavaScript frame. | |
3657 __ mov(t0, fp); | |
3658 if (skip_stub_frame()) { | |
3659 // For Ignition we need to skip the handler/stub frame to reach the | |
3660 // JavaScript frame for the function. | |
3661 __ lw(t0, MemOperand(t0, StandardFrameConstants::kCallerFPOffset)); | |
3662 } | |
3663 if (FLAG_debug_code) { | |
3664 Label ok; | |
3665 __ lw(a3, MemOperand(t0, StandardFrameConstants::kFunctionOffset)); | |
3666 __ Branch(&ok, eq, a1, Operand(a3)); | |
3667 __ Abort(kInvalidFrameForFastNewRestArgumentsStub); | |
3668 __ bind(&ok); | |
3669 } | |
3670 | |
3671 // TODO(bmeurer): Cleanup to match the FastNewStrictArgumentsStub. | |
3672 __ lw(a2, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); | |
3673 __ lw(a2, | |
3674 FieldMemOperand(a2, SharedFunctionInfo::kFormalParameterCountOffset)); | |
3675 __ Lsa(a3, t0, a2, kPointerSizeLog2 - 1); | |
3676 __ Addu(a3, a3, Operand(StandardFrameConstants::kCallerSPOffset)); | |
3677 | |
3678 // a1 : function | |
3679 // a2 : number of parameters (tagged) | |
3680 // a3 : parameters pointer | |
3681 // t0 : Javascript frame pointer | |
3682 // Registers used over whole function: | |
3683 // t1 : arguments count (tagged) | |
3684 // t2 : mapped parameter count (tagged) | |
3685 | |
3686 // Check if the calling frame is an arguments adaptor frame. | |
3687 Label adaptor_frame, try_allocate, runtime; | |
3688 __ lw(t0, MemOperand(t0, StandardFrameConstants::kCallerFPOffset)); | |
3689 __ lw(a0, MemOperand(t0, CommonFrameConstants::kContextOrFrameTypeOffset)); | |
3690 __ Branch(&adaptor_frame, eq, a0, | |
3691 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | |
3692 | |
3693 // No adaptor, parameter count = argument count. | |
3694 __ mov(t1, a2); | |
3695 __ Branch(USE_DELAY_SLOT, &try_allocate); | |
3696 __ mov(t2, a2); // In delay slot. | |
3697 | |
3698 // We have an adaptor frame. Patch the parameters pointer. | |
3699 __ bind(&adaptor_frame); | |
3700 __ lw(t1, MemOperand(t0, ArgumentsAdaptorFrameConstants::kLengthOffset)); | |
3701 __ Lsa(t0, t0, t1, 1); | |
3702 __ Addu(a3, t0, Operand(StandardFrameConstants::kCallerSPOffset)); | |
3703 | |
3704 // t1 = argument count (tagged) | |
3705 // t2 = parameter count (tagged) | |
3706 // Compute the mapped parameter count = min(t2, t1) in t2. | |
3707 __ mov(t2, a2); | |
3708 __ Branch(&try_allocate, le, t2, Operand(t1)); | |
3709 __ mov(t2, t1); | |
3710 | |
3711 __ bind(&try_allocate); | |
3712 | |
3713 // Compute the sizes of backing store, parameter map, and arguments object. | |
3714 // 1. Parameter map, has 2 extra words containing context and backing store. | |
3715 const int kParameterMapHeaderSize = | |
3716 FixedArray::kHeaderSize + 2 * kPointerSize; | |
3717 // If there are no mapped parameters, we do not need the parameter_map. | |
3718 Label param_map_size; | |
3719 DCHECK_EQ(static_cast<Smi*>(0), Smi::kZero); | |
3720 __ Branch(USE_DELAY_SLOT, ¶m_map_size, eq, t2, Operand(zero_reg)); | |
3721 __ mov(t5, zero_reg); // In delay slot: param map size = 0 when t2 == 0. | |
3722 __ sll(t5, t2, 1); | |
3723 __ addiu(t5, t5, kParameterMapHeaderSize); | |
3724 __ bind(¶m_map_size); | |
3725 | |
3726 // 2. Backing store. | |
3727 __ Lsa(t5, t5, t1, 1); | |
3728 __ Addu(t5, t5, Operand(FixedArray::kHeaderSize)); | |
3729 | |
3730 // 3. Arguments object. | |
3731 __ Addu(t5, t5, Operand(JSSloppyArgumentsObject::kSize)); | |
3732 | |
3733 // Do the allocation of all three objects in one go. | |
3734 __ Allocate(t5, v0, t5, t0, &runtime, NO_ALLOCATION_FLAGS); | |
3735 | |
3736 // v0 = address of new object(s) (tagged) | |
3737 // a2 = argument count (smi-tagged) | |
3738 // Get the arguments boilerplate from the current native context into t0. | |
3739 const int kNormalOffset = | |
3740 Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX); | |
3741 const int kAliasedOffset = | |
3742 Context::SlotOffset(Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX); | |
3743 | |
3744 __ lw(t0, NativeContextMemOperand()); | |
3745 Label skip2_ne, skip2_eq; | |
3746 __ Branch(&skip2_ne, ne, t2, Operand(zero_reg)); | |
3747 __ lw(t0, MemOperand(t0, kNormalOffset)); | |
3748 __ bind(&skip2_ne); | |
3749 | |
3750 __ Branch(&skip2_eq, eq, t2, Operand(zero_reg)); | |
3751 __ lw(t0, MemOperand(t0, kAliasedOffset)); | |
3752 __ bind(&skip2_eq); | |
3753 | |
3754 // v0 = address of new object (tagged) | |
3755 // a2 = argument count (smi-tagged) | |
3756 // t0 = address of arguments map (tagged) | |
3757 // t2 = mapped parameter count (tagged) | |
3758 __ sw(t0, FieldMemOperand(v0, JSObject::kMapOffset)); | |
3759 __ LoadRoot(t5, Heap::kEmptyFixedArrayRootIndex); | |
3760 __ sw(t5, FieldMemOperand(v0, JSObject::kPropertiesOffset)); | |
3761 __ sw(t5, FieldMemOperand(v0, JSObject::kElementsOffset)); | |
3762 | |
3763 // Set up the callee in-object property. | |
3764 __ AssertNotSmi(a1); | |
3765 __ sw(a1, FieldMemOperand(v0, JSSloppyArgumentsObject::kCalleeOffset)); | |
3766 | |
3767 // Use the length (smi tagged) and set that as an in-object property too. | |
3768 __ AssertSmi(t1); | |
3769 __ sw(t1, FieldMemOperand(v0, JSSloppyArgumentsObject::kLengthOffset)); | |
3770 | |
3771 // Set up the elements pointer in the allocated arguments object. | |
3772 // If we allocated a parameter map, t0 will point there, otherwise | |
3773 // it will point to the backing store. | |
3774 __ Addu(t0, v0, Operand(JSSloppyArgumentsObject::kSize)); | |
3775 __ sw(t0, FieldMemOperand(v0, JSObject::kElementsOffset)); | |
3776 | |
3777 // v0 = address of new object (tagged) | |
3778 // a2 = argument count (tagged) | |
3779 // t0 = address of parameter map or backing store (tagged) | |
3780 // t2 = mapped parameter count (tagged) | |
3781 // Initialize parameter map. If there are no mapped arguments, we're done. | |
3782 Label skip_parameter_map; | |
3783 Label skip3; | |
3784 __ Branch(&skip3, ne, t2, Operand(Smi::kZero)); | |
3785 // Move backing store address to a1, because it is | |
3786 // expected there when filling in the unmapped arguments. | |
3787 __ mov(a1, t0); | |
3788 __ bind(&skip3); | |
3789 | |
3790 __ Branch(&skip_parameter_map, eq, t2, Operand(Smi::kZero)); | |
3791 | |
3792 __ LoadRoot(t1, Heap::kSloppyArgumentsElementsMapRootIndex); | |
3793 __ sw(t1, FieldMemOperand(t0, FixedArray::kMapOffset)); | |
3794 __ Addu(t1, t2, Operand(Smi::FromInt(2))); | |
3795 __ sw(t1, FieldMemOperand(t0, FixedArray::kLengthOffset)); | |
3796 __ sw(cp, FieldMemOperand(t0, FixedArray::kHeaderSize + 0 * kPointerSize)); | |
3797 __ Lsa(t1, t0, t2, 1); | |
3798 __ Addu(t1, t1, Operand(kParameterMapHeaderSize)); | |
3799 __ sw(t1, FieldMemOperand(t0, FixedArray::kHeaderSize + 1 * kPointerSize)); | |
3800 | |
3801 // Copy the parameter slots and the holes in the arguments. | |
3802 // We need to fill in mapped_parameter_count slots. They index the context, | |
3803 // where parameters are stored in reverse order, at | |
3804 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1 | |
3805 // The mapped parameter thus need to get indices | |
3806 // MIN_CONTEXT_SLOTS+parameter_count-1 .. | |
3807 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count | |
3808 // We loop from right to left. | |
3809 Label parameters_loop, parameters_test; | |
3810 __ mov(t1, t2); | |
3811 __ Addu(t5, a2, Operand(Smi::FromInt(Context::MIN_CONTEXT_SLOTS))); | |
3812 __ Subu(t5, t5, Operand(t2)); | |
3813 __ LoadRoot(t3, Heap::kTheHoleValueRootIndex); | |
3814 __ Lsa(a1, t0, t1, 1); | |
3815 __ Addu(a1, a1, Operand(kParameterMapHeaderSize)); | |
3816 | |
3817 // a1 = address of backing store (tagged) | |
3818 // t0 = address of parameter map (tagged) | |
3819 // a0 = temporary scratch (a.o., for address calculation) | |
3820 // t1 = loop variable (tagged) | |
3821 // t3 = the hole value | |
3822 __ jmp(¶meters_test); | |
3823 | |
3824 __ bind(¶meters_loop); | |
3825 __ Subu(t1, t1, Operand(Smi::FromInt(1))); | |
3826 __ sll(a0, t1, 1); | |
3827 __ Addu(a0, a0, Operand(kParameterMapHeaderSize - kHeapObjectTag)); | |
3828 __ Addu(t6, t0, a0); | |
3829 __ sw(t5, MemOperand(t6)); | |
3830 __ Subu(a0, a0, Operand(kParameterMapHeaderSize - FixedArray::kHeaderSize)); | |
3831 __ Addu(t6, a1, a0); | |
3832 __ sw(t3, MemOperand(t6)); | |
3833 __ Addu(t5, t5, Operand(Smi::FromInt(1))); | |
3834 __ bind(¶meters_test); | |
3835 __ Branch(¶meters_loop, ne, t1, Operand(Smi::kZero)); | |
3836 | |
3837 // t1 = argument count (tagged). | |
3838 __ lw(t1, FieldMemOperand(v0, JSSloppyArgumentsObject::kLengthOffset)); | |
3839 | |
3840 __ bind(&skip_parameter_map); | |
3841 // v0 = address of new object (tagged) | |
3842 // a1 = address of backing store (tagged) | |
3843 // t1 = argument count (tagged) | |
3844 // t2 = mapped parameter count (tagged) | |
3845 // t5 = scratch | |
3846 // Copy arguments header and remaining slots (if there are any). | |
3847 __ LoadRoot(t5, Heap::kFixedArrayMapRootIndex); | |
3848 __ sw(t5, FieldMemOperand(a1, FixedArray::kMapOffset)); | |
3849 __ sw(t1, FieldMemOperand(a1, FixedArray::kLengthOffset)); | |
3850 | |
3851 Label arguments_loop, arguments_test; | |
3852 __ sll(t6, t2, 1); | |
3853 __ Subu(a3, a3, Operand(t6)); | |
3854 __ jmp(&arguments_test); | |
3855 | |
3856 __ bind(&arguments_loop); | |
3857 __ Subu(a3, a3, Operand(kPointerSize)); | |
3858 __ lw(t0, MemOperand(a3, 0)); | |
3859 __ Lsa(t5, a1, t2, 1); | |
3860 __ sw(t0, FieldMemOperand(t5, FixedArray::kHeaderSize)); | |
3861 __ Addu(t2, t2, Operand(Smi::FromInt(1))); | |
3862 | |
3863 __ bind(&arguments_test); | |
3864 __ Branch(&arguments_loop, lt, t2, Operand(t1)); | |
3865 | |
3866 // Return. | |
3867 __ Ret(); | |
3868 | |
3869 // Do the runtime call to allocate the arguments object. | |
3870 // t1 = argument count (tagged) | |
3871 __ bind(&runtime); | |
3872 __ Push(a1, a3, t1); | |
3873 __ TailCallRuntime(Runtime::kNewSloppyArguments); | |
3874 } | |
3875 | |
3876 | |
3877 void FastNewStrictArgumentsStub::Generate(MacroAssembler* masm) { | |
3878 // ----------- S t a t e ------------- | |
3879 // -- a1 : function | |
3880 // -- cp : context | |
3881 // -- fp : frame pointer | |
3882 // -- ra : return address | |
3883 // ----------------------------------- | |
3884 __ AssertFunction(a1); | |
3885 | |
3886 // Make a2 point to the JavaScript frame. | |
3887 __ mov(a2, fp); | |
3888 if (skip_stub_frame()) { | |
3889 // For Ignition we need to skip the handler/stub frame to reach the | |
3890 // JavaScript frame for the function. | |
3891 __ lw(a2, MemOperand(a2, StandardFrameConstants::kCallerFPOffset)); | |
3892 } | |
3893 if (FLAG_debug_code) { | |
3894 Label ok; | |
3895 __ lw(a3, MemOperand(a2, StandardFrameConstants::kFunctionOffset)); | |
3896 __ Branch(&ok, eq, a1, Operand(a3)); | |
3897 __ Abort(kInvalidFrameForFastNewRestArgumentsStub); | |
3898 __ bind(&ok); | |
3899 } | |
3900 | |
3901 // Check if we have an arguments adaptor frame below the function frame. | |
3902 Label arguments_adaptor, arguments_done; | |
3903 __ lw(a3, MemOperand(a2, StandardFrameConstants::kCallerFPOffset)); | |
3904 __ lw(a0, MemOperand(a3, CommonFrameConstants::kContextOrFrameTypeOffset)); | |
3905 __ Branch(&arguments_adaptor, eq, a0, | |
3906 Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | |
3907 { | |
3908 __ lw(t0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); | |
3909 __ lw(a0, | |
3910 FieldMemOperand(t0, SharedFunctionInfo::kFormalParameterCountOffset)); | |
3911 __ Lsa(a2, a2, a0, kPointerSizeLog2 - 1); | |
3912 __ Addu(a2, a2, Operand(StandardFrameConstants::kCallerSPOffset - | |
3913 1 * kPointerSize)); | |
3914 } | |
3915 __ Branch(&arguments_done); | |
3916 __ bind(&arguments_adaptor); | |
3917 { | |
3918 __ lw(a0, MemOperand(a3, ArgumentsAdaptorFrameConstants::kLengthOffset)); | |
3919 __ Lsa(a2, a3, a0, kPointerSizeLog2 - 1); | |
3920 __ Addu(a2, a2, Operand(StandardFrameConstants::kCallerSPOffset - | |
3921 1 * kPointerSize)); | |
3922 } | |
3923 __ bind(&arguments_done); | |
3924 | |
3925 // ----------- S t a t e ------------- | |
3926 // -- cp : context | |
3927 // -- a0 : number of rest parameters (tagged) | |
3928 // -- a1 : function | |
3929 // -- a2 : pointer to first rest parameters | |
3930 // -- ra : return address | |
3931 // ----------------------------------- | |
3932 | |
3933 // Allocate space for the strict arguments object plus the backing store. | |
3934 Label allocate, done_allocate; | |
3935 __ li(t0, Operand(JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize)); | |
3936 __ Lsa(t0, t0, a0, kPointerSizeLog2 - 1); | |
3937 __ Allocate(t0, v0, a3, t1, &allocate, NO_ALLOCATION_FLAGS); | |
3938 __ bind(&done_allocate); | |
3939 | |
3940 // Setup the elements array in v0. | |
3941 __ LoadRoot(at, Heap::kFixedArrayMapRootIndex); | |
3942 __ sw(at, FieldMemOperand(v0, FixedArray::kMapOffset)); | |
3943 __ sw(a0, FieldMemOperand(v0, FixedArray::kLengthOffset)); | |
3944 __ Addu(a3, v0, Operand(FixedArray::kHeaderSize)); | |
3945 { | |
3946 Label loop, done_loop; | |
3947 __ sll(at, a0, kPointerSizeLog2 - 1); | |
3948 __ Addu(a1, a3, at); | |
3949 __ bind(&loop); | |
3950 __ Branch(&done_loop, eq, a1, Operand(a3)); | |
3951 __ lw(at, MemOperand(a2, 0 * kPointerSize)); | |
3952 __ sw(at, FieldMemOperand(a3, 0 * kPointerSize)); | |
3953 __ Subu(a2, a2, Operand(1 * kPointerSize)); | |
3954 __ Addu(a3, a3, Operand(1 * kPointerSize)); | |
3955 __ Branch(&loop); | |
3956 __ bind(&done_loop); | |
3957 } | |
3958 | |
3959 // Setup the strict arguments object in a3. | |
3960 __ LoadNativeContextSlot(Context::STRICT_ARGUMENTS_MAP_INDEX, at); | |
3961 __ sw(at, FieldMemOperand(a3, JSStrictArgumentsObject::kMapOffset)); | |
3962 __ LoadRoot(at, Heap::kEmptyFixedArrayRootIndex); | |
3963 __ sw(at, FieldMemOperand(a3, JSStrictArgumentsObject::kPropertiesOffset)); | |
3964 __ sw(v0, FieldMemOperand(a3, JSStrictArgumentsObject::kElementsOffset)); | |
3965 __ sw(a0, FieldMemOperand(a3, JSStrictArgumentsObject::kLengthOffset)); | |
3966 STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize); | |
3967 __ Ret(USE_DELAY_SLOT); | |
3968 __ mov(v0, a3); // In delay slot | |
3969 | |
3970 // Fall back to %AllocateInNewSpace (if not too big). | |
3971 Label too_big_for_new_space; | |
3972 __ bind(&allocate); | |
3973 __ Branch(&too_big_for_new_space, gt, t0, Operand(kMaxRegularHeapObjectSize)); | |
3974 { | |
3975 FrameScope scope(masm, StackFrame::INTERNAL); | |
3976 __ SmiTag(t0); | |
3977 __ Push(a0, a2, t0); | |
3978 __ CallRuntime(Runtime::kAllocateInNewSpace); | |
3979 __ Pop(a0, a2); | |
3980 } | |
3981 __ jmp(&done_allocate); | |
3982 | |
3983 // Fall back to %NewStrictArguments. | |
3984 __ bind(&too_big_for_new_space); | |
3985 __ Push(a1); | |
3986 __ TailCallRuntime(Runtime::kNewStrictArguments); | |
3987 } | |
3988 | |
3989 | |
3990 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { | 3497 static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { |
3991 return ref0.address() - ref1.address(); | 3498 return ref0.address() - ref1.address(); |
3992 } | 3499 } |
3993 | 3500 |
3994 | 3501 |
3995 // Calls an API function. Allocates HandleScope, extracts returned value | 3502 // Calls an API function. Allocates HandleScope, extracts returned value |
3996 // from handle and propagates exceptions. Restores context. stack_space | 3503 // from handle and propagates exceptions. Restores context. stack_space |
3997 // - space to be unwound on exit (includes the call JS arguments space and | 3504 // - space to be unwound on exit (includes the call JS arguments space and |
3998 // the additional space allocated for the fast call). | 3505 // the additional space allocated for the fast call). |
3999 static void CallApiFunctionAndReturn( | 3506 static void CallApiFunctionAndReturn( |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4292 kStackUnwindSpace, kInvalidStackOffset, | 3799 kStackUnwindSpace, kInvalidStackOffset, |
4293 return_value_operand, NULL); | 3800 return_value_operand, NULL); |
4294 } | 3801 } |
4295 | 3802 |
4296 #undef __ | 3803 #undef __ |
4297 | 3804 |
4298 } // namespace internal | 3805 } // namespace internal |
4299 } // namespace v8 | 3806 } // namespace v8 |
4300 | 3807 |
4301 #endif // V8_TARGET_ARCH_MIPS | 3808 #endif // V8_TARGET_ARCH_MIPS |
OLD | NEW |