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