Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 3637 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3648 // Slow-case: Handle non-smi or out-of-bounds access to arguments | 3648 // Slow-case: Handle non-smi or out-of-bounds access to arguments |
| 3649 // by calling the runtime system. | 3649 // by calling the runtime system. |
| 3650 __ bind(&slow); | 3650 __ bind(&slow); |
| 3651 __ pop(ebx); // Return address. | 3651 __ pop(ebx); // Return address. |
| 3652 __ push(edx); | 3652 __ push(edx); |
| 3653 __ push(ebx); | 3653 __ push(ebx); |
| 3654 __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1); | 3654 __ TailCallRuntime(Runtime::kGetArgumentsProperty, 1, 1); |
| 3655 } | 3655 } |
| 3656 | 3656 |
| 3657 | 3657 |
| 3658 void ArgumentsAccessStub::GenerateNewObject(MacroAssembler* masm) { | 3658 void ArgumentsAccessStub::GenerateNewNonStrictSlow(MacroAssembler* masm) { |
| 3659 // esp[0] : return address | 3659 // esp[0] : return address |
| 3660 // esp[4] : number of parameters | 3660 // esp[4] : number of parameters |
| 3661 // esp[8] : receiver displacement | 3661 // esp[8] : receiver displacement |
| 3662 // esp[12] : function | 3662 // esp[12] : function |
| 3663 | 3663 |
| 3664 // The displacement is used for skipping the return address and the | 3664 // The displacement is used for skipping the return address and the |
| 3665 // frame pointer on the stack. It is the offset of the last | 3665 // frame pointer on the stack. It is the offset of the last |
| 3666 // parameter (if any) relative to the frame pointer. | 3666 // parameter (if any) relative to the frame pointer. |
| 3667 static const int kDisplacement = 2 * kPointerSize; | 3667 static const int kDisplacement = 2 * kPointerSize; |
| 3668 | 3668 |
| 3669 // Check if the calling frame is an arguments adaptor frame. | 3669 // Check if the calling frame is an arguments adaptor frame. |
| 3670 NearLabel runtime; | |
| 3671 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | |
|
Kevin Millikin (Chromium)
2011/04/27 11:49:28
I think some bit of this code is shared by all thr
rossberg
2011/04/27 23:18:00
Put in a TODO.
| |
| 3672 __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset)); | |
| 3673 __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | |
| 3674 __ j(not_equal, &runtime); | |
| 3675 | |
| 3676 // Patch the arguments.length and the parameters pointer. | |
| 3677 __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | |
| 3678 __ mov(Operand(esp, 1 * kPointerSize), ecx); | |
| 3679 __ lea(edx, Operand(edx, ecx, times_2, kDisplacement)); | |
| 3680 __ mov(Operand(esp, 2 * kPointerSize), edx); | |
| 3681 | |
| 3682 // Try the new space allocation. Start out with computing the size of | |
| 3683 // the arguments object and the elements array. | |
| 3684 __ bind(&runtime); | |
| 3685 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1); | |
| 3686 } | |
| 3687 | |
| 3688 | |
| 3689 void ArgumentsAccessStub::GenerateNewNonStrictFast(MacroAssembler* masm) { | |
| 3690 // esp[0] : return address | |
| 3691 // esp[4] : number of parameters (tagged) | |
| 3692 // esp[8] : receiver displacement | |
| 3693 // esp[12] : function | |
| 3694 | |
| 3695 // The displacement is used for skipping the return address and the | |
| 3696 // frame pointer on the stack. It is the offset of the last | |
| 3697 // parameter (if any) relative to the frame pointer. | |
| 3698 static const int kDisplacement = 2 * kPointerSize; | |
|
Kevin Millikin (Chromium)
2011/04/27 11:49:28
It strikes me that kDisplacement is really just St
rossberg
2011/04/27 23:18:00
Done.
| |
| 3699 | |
| 3700 // ebx = parameter count (tagged) | |
| 3701 __ mov(ebx, Operand(esp, 1 * kPointerSize)); | |
|
Kevin Millikin (Chromium)
2011/04/27 11:49:28
We have just pushed this before the call. We coul
rossberg
2011/04/27 23:18:00
Does it matter much?
| |
| 3702 | |
| 3703 // Check if the calling frame is an arguments adaptor frame. | |
| 3704 Label runtime; | |
| 3705 NearLabel adaptor_frame, try_allocate; | |
| 3706 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | |
| 3707 __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset)); | |
| 3708 __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | |
| 3709 __ j(equal, &adaptor_frame); | |
| 3710 | |
| 3711 // No adaptor, parameter count = argument count. | |
| 3712 __ mov(ecx, ebx); | |
| 3713 __ jmp(&try_allocate); | |
| 3714 | |
| 3715 // We have an adaptor frame. Patch the parameters pointer. | |
| 3716 __ bind(&adaptor_frame); | |
| 3717 __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | |
|
Kevin Millikin (Chromium)
2011/04/27 11:49:28
Also, instead of computing the non-adaptor receive
rossberg
2011/04/27 23:18:00
True. I leave that for later.
| |
| 3718 __ lea(edx, Operand(edx, ecx, times_2, kDisplacement)); | |
| 3719 __ mov(Operand(esp, 2 * kPointerSize), edx); | |
| 3720 | |
| 3721 // ebx = parameter count (tagged) | |
| 3722 // ecx = argument count (tagged) | |
| 3723 // esp[4] = parameter count (tagged) | |
| 3724 // esp[8] = address of receiver argument | |
| 3725 // Compute the mapped parameter count = min(ebx, ecx) in ebx. | |
| 3726 __ cmp(ebx, Operand(ecx)); | |
| 3727 __ j(less_equal, &try_allocate); | |
| 3728 __ mov(ebx, ecx); | |
| 3729 | |
| 3730 __ bind(&try_allocate); | |
| 3731 | |
| 3732 // Save mapped parameter count. | |
| 3733 __ push(ebx); | |
| 3734 | |
| 3735 // Compute the sizes of backing store, parameter map, and arguments object. | |
| 3736 // 1. Parameter map, has 2 extra words containing context and backing store. | |
| 3737 const int kParameterMapHeaderSize = | |
| 3738 FixedArray::kHeaderSize + 2 * kPointerSize; | |
| 3739 NearLabel no_parameter_map; | |
| 3740 __ test(ebx, Operand(ebx)); | |
| 3741 __ j(zero, &no_parameter_map); | |
| 3742 __ lea(ebx, Operand(ebx, times_2, kParameterMapHeaderSize)); | |
| 3743 __ bind(&no_parameter_map); | |
| 3744 | |
| 3745 // 2. Backing store. | |
| 3746 __ lea(ebx, Operand(ebx, ecx, times_2, FixedArray::kHeaderSize)); | |
| 3747 | |
| 3748 // 3. Arguments object. | |
| 3749 __ add(Operand(ebx), Immediate(GetArgumentsObjectSize())); | |
|
Kevin Millikin (Chromium)
2011/04/27 11:49:28
I think the size is a constant here.
rossberg
2011/04/27 23:18:00
Done (here and elsewhere).
| |
| 3750 | |
| 3751 // Do the allocation of all three objects in one go. | |
| 3752 __ AllocateInNewSpace(ebx, eax, edx, edi, &runtime, TAG_OBJECT); | |
| 3753 | |
| 3754 // eax = address of new object(s) (tagged) | |
| 3755 // ecx = argument count (tagged) | |
| 3756 // esp[0] = mapped parameter count (tagged) | |
| 3757 // esp[8] = parameter count (tagged) | |
| 3758 // esp[12] = address of receiver argument | |
| 3759 // Get the arguments boilerplate from the current (global) context into edi. | |
| 3760 NearLabel has_mapped_parameters, copy; | |
| 3761 __ mov(edi, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); | |
| 3762 __ mov(edi, FieldOperand(edi, GlobalObject::kGlobalContextOffset)); | |
| 3763 __ mov(ebx, Operand(esp, 0 * kPointerSize)); | |
| 3764 __ test(ebx, Operand(ebx)); | |
| 3765 __ j(not_zero, &has_mapped_parameters); | |
| 3766 __ mov(edi, Operand(edi, | |
| 3767 Context::SlotOffset(Context::ARGUMENTS_BOILERPLATE_INDEX))); | |
| 3768 __ jmp(©); | |
| 3769 | |
| 3770 __ bind(&has_mapped_parameters); | |
| 3771 __ mov(edi, Operand(edi, | |
| 3772 Context::SlotOffset(Context::ALIASED_ARGUMENTS_BOILERPLATE_INDEX))); | |
| 3773 __ bind(©); | |
| 3774 | |
| 3775 // eax = address of new object (tagged) | |
| 3776 // ebx = mapped parameter count (tagged) | |
| 3777 // ecx = argument count (tagged) | |
| 3778 // edi = address of boilerplate object (tagged) | |
| 3779 // esp[0] = mapped parameter count (tagged) | |
| 3780 // esp[8] = parameter count (tagged) | |
| 3781 // esp[12] = address of receiver argument | |
| 3782 // Copy the JS object part. | |
| 3783 for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) { | |
| 3784 __ mov(edx, FieldOperand(edi, i)); | |
| 3785 __ mov(FieldOperand(eax, i), edx); | |
| 3786 } | |
| 3787 | |
| 3788 // Setup the callee in-object property. | |
| 3789 STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); | |
| 3790 __ mov(edx, Operand(esp, 4 * kPointerSize)); | |
| 3791 __ mov(FieldOperand(eax, JSObject::kHeaderSize + | |
| 3792 Heap::kArgumentsCalleeIndex * kPointerSize), | |
| 3793 edx); | |
| 3794 | |
| 3795 // Use the length (smi tagged) and set that as an in-object property too. | |
| 3796 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); | |
| 3797 __ mov(FieldOperand(eax, JSObject::kHeaderSize + | |
| 3798 Heap::kArgumentsLengthIndex * kPointerSize), | |
| 3799 ecx); | |
| 3800 | |
| 3801 // Setup the elements pointer in the allocated arguments object. | |
| 3802 // If we allocated a parameter map, edi will point there, otherwise to the | |
| 3803 // backing store. | |
| 3804 __ lea(edi, Operand(eax, GetArgumentsObjectSize())); | |
| 3805 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); | |
| 3806 | |
| 3807 // eax = address of new object (tagged) | |
| 3808 // ebx = mapped parameter count (tagged) | |
| 3809 // ecx = argument count (tagged) | |
| 3810 // edi = address of parameter map or backing store (tagged) | |
| 3811 // esp[0] = mapped parameter count (tagged) | |
| 3812 // esp[8] = parameter count (tagged) | |
| 3813 // esp[12] = address of receiver argument | |
| 3814 // Free a register. | |
| 3815 __ push(eax); | |
| 3816 | |
| 3817 // Initialize parameter map. If there are no mapped arguments, we're done. | |
| 3818 Label skip_parameter_map; | |
| 3819 __ test(ebx, Operand(ebx)); | |
| 3820 __ j(zero, &skip_parameter_map); | |
| 3821 | |
| 3822 __ mov(FieldOperand(edi, FixedArray::kMapOffset), | |
| 3823 Immediate(FACTORY->non_strict_arguments_elements_map())); | |
| 3824 __ lea(eax, Operand(ebx, reinterpret_cast<intptr_t>(Smi::FromInt(2)))); | |
| 3825 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), eax); | |
| 3826 __ mov(FieldOperand(edi, FixedArray::kHeaderSize + 0 * kPointerSize), esi); | |
| 3827 __ lea(eax, Operand(edi, ebx, times_2, kParameterMapHeaderSize)); | |
| 3828 __ mov(FieldOperand(edi, FixedArray::kHeaderSize + 1 * kPointerSize), eax); | |
| 3829 | |
| 3830 // Copy the parameter slots and the holes in the arguments. | |
| 3831 // We need to fill in mapped_parameter_count slots. The index the context, | |
| 3832 // where parameters are stored in reverse order, at | |
| 3833 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1 | |
| 3834 // The mapped parameter thus need to get indices | |
| 3835 // MIN_CONTEXT_SLOTS+parameter_count-1 .. | |
| 3836 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count | |
| 3837 // We loop from right to left. | |
| 3838 NearLabel parameters_loop, parameters_test; | |
| 3839 __ push(ecx); | |
|
Kevin Millikin (Chromium)
2011/04/27 11:49:28
It's unfortunate that the parameters are in the re
rossberg
2011/04/27 23:18:00
Yes, I felt that clarity was more important here.
| |
| 3840 __ mov(eax, Operand(esp, 2 * kPointerSize)); | |
| 3841 __ mov(ebx, Immediate(Smi::FromInt(Context::MIN_CONTEXT_SLOTS))); | |
| 3842 __ add(ebx, Operand(esp, 4 * kPointerSize)); | |
| 3843 __ sub(ebx, Operand(eax)); | |
| 3844 __ mov(ecx, FACTORY->the_hole_value()); | |
| 3845 __ mov(edx, edi); | |
| 3846 __ lea(edi, Operand(edi, eax, times_2, kParameterMapHeaderSize)); | |
| 3847 // eax = loop variable (tagged) | |
| 3848 // ebx = mapping index (tagged) | |
| 3849 // ecx = the hole value | |
| 3850 // edx = address of parameter map (tagged) | |
| 3851 // edi = address of backing store (tagged) | |
| 3852 // esp[0] = argument count (tagged) | |
| 3853 // esp[4] = address of new object (tagged) | |
| 3854 // esp[8] = mapped parameter count (tagged) | |
| 3855 // esp[16] = parameter count (tagged) | |
| 3856 // esp[20] = address of receiver argument | |
| 3857 __ jmp(¶meters_test); | |
| 3858 | |
| 3859 __ bind(¶meters_loop); | |
| 3860 __ sub(Operand(eax), Immediate(Smi::FromInt(1))); | |
| 3861 __ mov(FieldOperand(edx, eax, times_2, kParameterMapHeaderSize), ebx); | |
| 3862 __ mov(FieldOperand(edi, eax, times_2, FixedArray::kHeaderSize), ecx); | |
| 3863 __ add(Operand(ebx), Immediate(Smi::FromInt(1))); | |
| 3864 __ bind(¶meters_test); | |
| 3865 __ test(eax, Operand(eax)); | |
| 3866 __ j(not_zero, ¶meters_loop); | |
| 3867 __ pop(ecx); | |
| 3868 | |
| 3869 __ bind(&skip_parameter_map); | |
| 3870 | |
| 3871 // ecx = argument count (tagged) | |
| 3872 // edi = address of backing store (tagged) | |
| 3873 // esp[0] = address of new object (tagged) | |
| 3874 // esp[4] = mapped parameter count (tagged) | |
| 3875 // esp[12] = parameter count (tagged) | |
| 3876 // esp[16] = address of receiver argument | |
| 3877 // Copy arguments header and remaining slots (if there are any). | |
| 3878 __ mov(FieldOperand(edi, FixedArray::kMapOffset), | |
| 3879 Immediate(FACTORY->fixed_array_map())); | |
| 3880 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx); | |
| 3881 | |
| 3882 NearLabel arguments_loop, arguments_test; | |
| 3883 __ mov(ebx, Operand(esp, 1 * kPointerSize)); | |
| 3884 __ mov(edx, Operand(esp, 4 * kPointerSize)); | |
| 3885 __ sub(Operand(edx), ebx); // Is there a smarter way to do negative scaling? | |
| 3886 __ sub(Operand(edx), ebx); | |
| 3887 __ jmp(&arguments_test); | |
| 3888 __ bind(&arguments_loop); | |
| 3889 __ sub(Operand(edx), Immediate(kPointerSize)); | |
| 3890 __ mov(eax, Operand(edx, 0)); | |
| 3891 __ mov(FieldOperand(edi, ebx, times_2, FixedArray::kHeaderSize), eax); | |
| 3892 __ add(Operand(ebx), Immediate(Smi::FromInt(1))); | |
| 3893 __ bind(&arguments_test); | |
| 3894 __ cmp(ebx, Operand(ecx)); | |
| 3895 __ j(less, &arguments_loop); | |
| 3896 | |
| 3897 // Restore. | |
| 3898 __ pop(eax); // Address of arguments object. | |
| 3899 __ pop(ebx); // Parameter count. | |
| 3900 | |
| 3901 // Return and remove the on-stack parameters. | |
| 3902 __ ret(3 * kPointerSize); | |
| 3903 | |
| 3904 // Do the runtime call to allocate the arguments object. | |
| 3905 __ bind(&runtime); | |
| 3906 __ pop(eax); // Remove saved parameter count. | |
| 3907 __ mov(Operand(esp, 1 * kPointerSize), ecx); // Patch argument count. | |
| 3908 __ TailCallRuntime(Runtime::kNewStrictArgumentsFast, 3, 1); | |
| 3909 } | |
| 3910 | |
| 3911 | |
| 3912 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { | |
| 3913 // esp[0] : return address | |
| 3914 // esp[4] : number of parameters | |
| 3915 // esp[8] : receiver displacement | |
| 3916 // esp[12] : function | |
| 3917 | |
| 3918 // The displacement is used for skipping the return address and the | |
| 3919 // frame pointer on the stack. It is the offset of the last | |
| 3920 // parameter (if any) relative to the frame pointer. | |
| 3921 static const int kDisplacement = 2 * kPointerSize; | |
| 3922 | |
| 3923 // Check if the calling frame is an arguments adaptor frame. | |
| 3670 Label adaptor_frame, try_allocate, runtime; | 3924 Label adaptor_frame, try_allocate, runtime; |
| 3671 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | 3925 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
| 3672 __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset)); | 3926 __ mov(ecx, Operand(edx, StandardFrameConstants::kContextOffset)); |
| 3673 __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 3927 __ cmp(Operand(ecx), Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 3674 __ j(equal, &adaptor_frame); | 3928 __ j(equal, &adaptor_frame); |
| 3675 | 3929 |
| 3676 // Get the length from the frame. | 3930 // Get the length from the frame. |
| 3677 __ mov(ecx, Operand(esp, 1 * kPointerSize)); | 3931 __ mov(ecx, Operand(esp, 1 * kPointerSize)); |
| 3678 __ jmp(&try_allocate); | 3932 __ jmp(&try_allocate); |
| 3679 | 3933 |
| 3680 // Patch the arguments.length and the parameters pointer. | 3934 // Patch the arguments.length and the parameters pointer. |
| 3681 __ bind(&adaptor_frame); | 3935 __ bind(&adaptor_frame); |
| 3682 __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 3936 __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 3683 __ mov(Operand(esp, 1 * kPointerSize), ecx); | 3937 __ mov(Operand(esp, 1 * kPointerSize), ecx); |
| 3684 __ lea(edx, Operand(edx, ecx, times_2, kDisplacement)); | 3938 __ lea(edx, Operand(edx, ecx, times_2, kDisplacement)); |
| 3685 __ mov(Operand(esp, 2 * kPointerSize), edx); | 3939 __ mov(Operand(esp, 2 * kPointerSize), edx); |
| 3686 | 3940 |
| 3687 // Try the new space allocation. Start out with computing the size of | 3941 // Try the new space allocation. Start out with computing the size of |
| 3688 // the arguments object and the elements array. | 3942 // the arguments object and the elements array. |
| 3689 NearLabel add_arguments_object; | 3943 NearLabel add_arguments_object; |
| 3690 __ bind(&try_allocate); | 3944 __ bind(&try_allocate); |
| 3691 if (type_ == NEW_NON_STRICT) { | 3945 __ test(ecx, Operand(ecx)); |
| 3692 __ TailCallRuntime(Runtime::kNewArgumentsFast, 3, 1); | 3946 __ j(zero, &add_arguments_object); |
| 3693 } else { | 3947 __ lea(ecx, Operand(ecx, times_2, FixedArray::kHeaderSize)); |
| 3694 __ test(ecx, Operand(ecx)); | 3948 __ bind(&add_arguments_object); |
| 3695 __ j(zero, &add_arguments_object); | 3949 __ add(Operand(ecx), Immediate(GetArgumentsObjectSize())); |
| 3696 __ lea(ecx, Operand(ecx, times_2, FixedArray::kHeaderSize)); | |
| 3697 __ bind(&add_arguments_object); | |
| 3698 __ add(Operand(ecx), Immediate(GetArgumentsObjectSize())); | |
| 3699 | 3950 |
| 3700 // Do the allocation of both objects in one go. | 3951 // Do the allocation of both objects in one go. |
| 3701 __ AllocateInNewSpace(ecx, eax, edx, ebx, &runtime, TAG_OBJECT); | 3952 __ AllocateInNewSpace(ecx, eax, edx, ebx, &runtime, TAG_OBJECT); |
| 3702 | 3953 |
| 3703 // Get the arguments boilerplate from the current (global) context. | 3954 // Get the arguments boilerplate from the current (global) context. |
| 3704 __ mov(edi, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); | 3955 __ mov(edi, Operand(esi, Context::SlotOffset(Context::GLOBAL_INDEX))); |
| 3705 __ mov(edi, FieldOperand(edi, GlobalObject::kGlobalContextOffset)); | 3956 __ mov(edi, FieldOperand(edi, GlobalObject::kGlobalContextOffset)); |
| 3706 __ mov(edi, Operand(edi, | 3957 const int offset = |
| 3707 Context::SlotOffset(GetArgumentsBoilerplateIndex()))); | 3958 Context::SlotOffset(Context::STRICT_MODE_ARGUMENTS_BOILERPLATE_INDEX); |
| 3959 __ mov(edi, Operand(edi, offset)); | |
| 3708 | 3960 |
| 3709 // Copy the JS object part. | 3961 // Copy the JS object part. |
| 3710 for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) { | 3962 for (int i = 0; i < JSObject::kHeaderSize; i += kPointerSize) { |
| 3711 __ mov(ebx, FieldOperand(edi, i)); | 3963 __ mov(ebx, FieldOperand(edi, i)); |
| 3712 __ mov(FieldOperand(eax, i), ebx); | 3964 __ mov(FieldOperand(eax, i), ebx); |
| 3713 } | 3965 } |
| 3714 | 3966 |
| 3715 if (type_ == NEW_NON_STRICT) { | 3967 // Get the length (smi tagged) and set that as an in-object property too. |
| 3716 // Setup the callee in-object property. | 3968 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); |
| 3717 STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); | 3969 __ mov(ecx, Operand(esp, 1 * kPointerSize)); |
| 3718 __ mov(ebx, Operand(esp, 3 * kPointerSize)); | 3970 __ mov(FieldOperand(eax, JSObject::kHeaderSize + |
| 3719 __ mov(FieldOperand(eax, JSObject::kHeaderSize + | 3971 Heap::kArgumentsLengthIndex * kPointerSize), |
| 3720 Heap::kArgumentsCalleeIndex * kPointerSize), | 3972 ecx); |
| 3721 ebx); | |
| 3722 } | |
| 3723 | 3973 |
| 3724 // Get the length (smi tagged) and set that as an in-object property too. | 3974 // If there are no actual arguments, we're done. |
| 3725 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); | 3975 Label done; |
| 3726 __ mov(ecx, Operand(esp, 1 * kPointerSize)); | 3976 __ test(ecx, Operand(ecx)); |
| 3727 __ mov(FieldOperand(eax, JSObject::kHeaderSize + | 3977 __ j(zero, &done); |
| 3728 Heap::kArgumentsLengthIndex * kPointerSize), | |
| 3729 ecx); | |
| 3730 | 3978 |
| 3731 // If there are no actual arguments, we're done. | 3979 // Get the parameters pointer from the stack. |
| 3732 Label done; | 3980 __ mov(edx, Operand(esp, 2 * kPointerSize)); |
| 3733 __ test(ecx, Operand(ecx)); | |
| 3734 __ j(zero, &done); | |
| 3735 | 3981 |
| 3736 // Get the parameters pointer from the stack. | 3982 // Setup the elements pointer in the allocated arguments object and |
| 3737 __ mov(edx, Operand(esp, 2 * kPointerSize)); | 3983 // initialize the header in the elements fixed array. |
| 3984 __ lea(edi, Operand(eax, GetArgumentsObjectSize())); | |
| 3985 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); | |
| 3986 __ mov(FieldOperand(edi, FixedArray::kMapOffset), | |
| 3987 Immediate(FACTORY->fixed_array_map())); | |
| 3738 | 3988 |
| 3739 // Setup the elements pointer in the allocated arguments object and | 3989 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx); |
| 3740 // initialize the header in the elements fixed array. | 3990 // Untag the length for the loop below. |
| 3741 __ lea(edi, Operand(eax, GetArgumentsObjectSize())); | 3991 __ SmiUntag(ecx); |
| 3742 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); | |
| 3743 __ mov(FieldOperand(edi, FixedArray::kMapOffset), | |
| 3744 Immediate(FACTORY->fixed_array_map())); | |
| 3745 | 3992 |
| 3746 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx); | 3993 // Copy the fixed array slots. |
| 3747 // Untag the length for the loop below. | 3994 NearLabel loop; |
| 3748 __ SmiUntag(ecx); | 3995 __ bind(&loop); |
| 3996 __ mov(ebx, Operand(edx, -1 * kPointerSize)); // Skip receiver. | |
| 3997 __ mov(FieldOperand(edi, FixedArray::kHeaderSize), ebx); | |
| 3998 __ add(Operand(edi), Immediate(kPointerSize)); | |
| 3999 __ sub(Operand(edx), Immediate(kPointerSize)); | |
| 4000 __ dec(ecx); | |
| 4001 __ j(not_zero, &loop); | |
| 3749 | 4002 |
| 3750 // Copy the fixed array slots. | 4003 // Return and remove the on-stack parameters. |
| 3751 NearLabel loop; | 4004 __ bind(&done); |
| 3752 __ bind(&loop); | 4005 __ ret(3 * kPointerSize); |
| 3753 __ mov(ebx, Operand(edx, -1 * kPointerSize)); // Skip receiver. | |
| 3754 __ mov(FieldOperand(edi, FixedArray::kHeaderSize), ebx); | |
| 3755 __ add(Operand(edi), Immediate(kPointerSize)); | |
| 3756 __ sub(Operand(edx), Immediate(kPointerSize)); | |
| 3757 __ dec(ecx); | |
| 3758 __ j(not_zero, &loop); | |
| 3759 | 4006 |
| 3760 // Return and remove the on-stack parameters. | 4007 // Do the runtime call to allocate the arguments object. |
| 3761 __ bind(&done); | 4008 __ bind(&runtime); |
| 3762 __ ret(3 * kPointerSize); | 4009 __ TailCallRuntime(Runtime::kNewStrictArgumentsFast, 3, 1); |
| 3763 | |
| 3764 // Do the runtime call to allocate the arguments object. | |
| 3765 __ bind(&runtime); | |
| 3766 __ TailCallRuntime(Runtime::kNewStrictArgumentsFast, 3, 1); | |
| 3767 } | |
| 3768 } | 4010 } |
| 3769 | 4011 |
| 3770 | 4012 |
| 3771 void RegExpExecStub::Generate(MacroAssembler* masm) { | 4013 void RegExpExecStub::Generate(MacroAssembler* masm) { |
| 3772 // Just jump directly to runtime if native RegExp is not selected at compile | 4014 // Just jump directly to runtime if native RegExp is not selected at compile |
| 3773 // time or if regexp entry in generated code is turned off runtime switch or | 4015 // time or if regexp entry in generated code is turned off runtime switch or |
| 3774 // at compilation. | 4016 // at compilation. |
| 3775 #ifdef V8_INTERPRETED_REGEXP | 4017 #ifdef V8_INTERPRETED_REGEXP |
| 3776 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); | 4018 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); |
| 3777 #else // V8_INTERPRETED_REGEXP | 4019 #else // V8_INTERPRETED_REGEXP |
| (...skipping 2766 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6544 // Do a tail call to the rewritten stub. | 6786 // Do a tail call to the rewritten stub. |
| 6545 __ jmp(Operand(edi)); | 6787 __ jmp(Operand(edi)); |
| 6546 } | 6788 } |
| 6547 | 6789 |
| 6548 | 6790 |
| 6549 #undef __ | 6791 #undef __ |
| 6550 | 6792 |
| 6551 } } // namespace v8::internal | 6793 } } // namespace v8::internal |
| 6552 | 6794 |
| 6553 #endif // V8_TARGET_ARCH_IA32 | 6795 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |