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_IA32 | 5 #if V8_TARGET_ARCH_IA32 |
6 | 6 |
7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
8 #include "src/bootstrapper.h" | 8 #include "src/bootstrapper.h" |
9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 709 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
720 | 720 |
721 StubRuntimeCallHelper call_helper; | 721 StubRuntimeCallHelper call_helper; |
722 char_at_generator.GenerateSlow(masm, PART_OF_IC_HANDLER, call_helper); | 722 char_at_generator.GenerateSlow(masm, PART_OF_IC_HANDLER, call_helper); |
723 | 723 |
724 __ bind(&miss); | 724 __ bind(&miss); |
725 PropertyAccessCompiler::TailCallBuiltin( | 725 PropertyAccessCompiler::TailCallBuiltin( |
726 masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC)); | 726 masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC)); |
727 } | 727 } |
728 | 728 |
729 | 729 |
730 void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) { | |
731 // ecx : number of parameters (tagged) | |
732 // edx : parameters pointer | |
733 // edi : function | |
734 // esp[0] : return address | |
735 | |
736 DCHECK(edi.is(ArgumentsAccessNewDescriptor::function())); | |
737 DCHECK(ecx.is(ArgumentsAccessNewDescriptor::parameter_count())); | |
738 DCHECK(edx.is(ArgumentsAccessNewDescriptor::parameter_pointer())); | |
739 | |
740 // Check if the calling frame is an arguments adaptor frame. | |
741 Label runtime; | |
742 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | |
743 __ mov(eax, Operand(ebx, StandardFrameConstants::kContextOffset)); | |
744 __ cmp(eax, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | |
745 __ j(not_equal, &runtime, Label::kNear); | |
746 | |
747 // Patch the arguments.length and the parameters pointer. | |
748 __ mov(ecx, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | |
749 __ lea(edx, | |
750 Operand(ebx, ecx, times_2, StandardFrameConstants::kCallerSPOffset)); | |
751 | |
752 __ bind(&runtime); | |
753 __ pop(eax); // Pop return address. | |
754 __ push(edi); // Push function. | |
755 __ push(edx); // Push parameters pointer. | |
756 __ push(ecx); // Push parameter count. | |
757 __ push(eax); // Push return address. | |
758 __ TailCallRuntime(Runtime::kNewSloppyArguments); | |
759 } | |
760 | |
761 | |
762 void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { | |
763 // ecx : number of parameters (tagged) | |
764 // edx : parameters pointer | |
765 // edi : function | |
766 // esp[0] : return address | |
767 | |
768 DCHECK(edi.is(ArgumentsAccessNewDescriptor::function())); | |
769 DCHECK(ecx.is(ArgumentsAccessNewDescriptor::parameter_count())); | |
770 DCHECK(edx.is(ArgumentsAccessNewDescriptor::parameter_pointer())); | |
771 | |
772 // Check if the calling frame is an arguments adaptor frame. | |
773 Label adaptor_frame, try_allocate, runtime; | |
774 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | |
775 __ mov(eax, Operand(ebx, StandardFrameConstants::kContextOffset)); | |
776 __ cmp(eax, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | |
777 __ j(equal, &adaptor_frame, Label::kNear); | |
778 | |
779 // No adaptor, parameter count = argument count. | |
780 __ mov(ebx, ecx); | |
781 __ push(ecx); | |
782 __ jmp(&try_allocate, Label::kNear); | |
783 | |
784 // We have an adaptor frame. Patch the parameters pointer. | |
785 __ bind(&adaptor_frame); | |
786 __ mov(ebx, ecx); | |
787 __ push(ecx); | |
788 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | |
789 __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | |
790 __ lea(edx, Operand(edx, ecx, times_2, | |
791 StandardFrameConstants::kCallerSPOffset)); | |
792 | |
793 // ebx = parameter count (tagged) | |
794 // ecx = argument count (smi-tagged) | |
795 // Compute the mapped parameter count = min(ebx, ecx) in ebx. | |
796 __ cmp(ebx, ecx); | |
797 __ j(less_equal, &try_allocate, Label::kNear); | |
798 __ mov(ebx, ecx); | |
799 | |
800 // Save mapped parameter count and function. | |
801 __ bind(&try_allocate); | |
802 __ push(edi); | |
803 __ push(ebx); | |
804 | |
805 // Compute the sizes of backing store, parameter map, and arguments object. | |
806 // 1. Parameter map, has 2 extra words containing context and backing store. | |
807 const int kParameterMapHeaderSize = | |
808 FixedArray::kHeaderSize + 2 * kPointerSize; | |
809 Label no_parameter_map; | |
810 __ test(ebx, ebx); | |
811 __ j(zero, &no_parameter_map, Label::kNear); | |
812 __ lea(ebx, Operand(ebx, times_2, kParameterMapHeaderSize)); | |
813 __ bind(&no_parameter_map); | |
814 | |
815 // 2. Backing store. | |
816 __ lea(ebx, Operand(ebx, ecx, times_2, FixedArray::kHeaderSize)); | |
817 | |
818 // 3. Arguments object. | |
819 __ add(ebx, Immediate(JSSloppyArgumentsObject::kSize)); | |
820 | |
821 // Do the allocation of all three objects in one go. | |
822 __ Allocate(ebx, eax, edi, no_reg, &runtime, TAG_OBJECT); | |
823 | |
824 // eax = address of new object(s) (tagged) | |
825 // ecx = argument count (smi-tagged) | |
826 // esp[0] = mapped parameter count (tagged) | |
827 // esp[4] = function | |
828 // esp[8] = parameter count (tagged) | |
829 // Get the arguments map from the current native context into edi. | |
830 Label has_mapped_parameters, instantiate; | |
831 __ mov(edi, NativeContextOperand()); | |
832 __ mov(ebx, Operand(esp, 0 * kPointerSize)); | |
833 __ test(ebx, ebx); | |
834 __ j(not_zero, &has_mapped_parameters, Label::kNear); | |
835 __ mov( | |
836 edi, | |
837 Operand(edi, Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX))); | |
838 __ jmp(&instantiate, Label::kNear); | |
839 | |
840 __ bind(&has_mapped_parameters); | |
841 __ mov(edi, Operand(edi, Context::SlotOffset( | |
842 Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX))); | |
843 __ bind(&instantiate); | |
844 | |
845 // eax = address of new object (tagged) | |
846 // ebx = mapped parameter count (tagged) | |
847 // ecx = argument count (smi-tagged) | |
848 // edi = address of arguments map (tagged) | |
849 // esp[0] = mapped parameter count (tagged) | |
850 // esp[4] = function | |
851 // esp[8] = parameter count (tagged) | |
852 // Copy the JS object part. | |
853 __ mov(FieldOperand(eax, JSObject::kMapOffset), edi); | |
854 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), | |
855 masm->isolate()->factory()->empty_fixed_array()); | |
856 __ mov(FieldOperand(eax, JSObject::kElementsOffset), | |
857 masm->isolate()->factory()->empty_fixed_array()); | |
858 | |
859 // Set up the callee in-object property. | |
860 STATIC_ASSERT(JSSloppyArgumentsObject::kCalleeIndex == 1); | |
861 __ mov(edi, Operand(esp, 1 * kPointerSize)); | |
862 __ AssertNotSmi(edi); | |
863 __ mov(FieldOperand(eax, JSSloppyArgumentsObject::kCalleeOffset), edi); | |
864 | |
865 // Use the length (smi tagged) and set that as an in-object property too. | |
866 __ AssertSmi(ecx); | |
867 __ mov(FieldOperand(eax, JSSloppyArgumentsObject::kLengthOffset), ecx); | |
868 | |
869 // Set up the elements pointer in the allocated arguments object. | |
870 // If we allocated a parameter map, edi will point there, otherwise to the | |
871 // backing store. | |
872 __ lea(edi, Operand(eax, JSSloppyArgumentsObject::kSize)); | |
873 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); | |
874 | |
875 // eax = address of new object (tagged) | |
876 // ebx = mapped parameter count (tagged) | |
877 // ecx = argument count (tagged) | |
878 // edx = address of receiver argument | |
879 // edi = address of parameter map or backing store (tagged) | |
880 // esp[0] = mapped parameter count (tagged) | |
881 // esp[4] = function | |
882 // esp[8] = parameter count (tagged) | |
883 // Free two registers. | |
884 __ push(edx); | |
885 __ push(eax); | |
886 | |
887 // Initialize parameter map. If there are no mapped arguments, we're done. | |
888 Label skip_parameter_map; | |
889 __ test(ebx, ebx); | |
890 __ j(zero, &skip_parameter_map); | |
891 | |
892 __ mov(FieldOperand(edi, FixedArray::kMapOffset), | |
893 Immediate(isolate()->factory()->sloppy_arguments_elements_map())); | |
894 __ lea(eax, Operand(ebx, reinterpret_cast<intptr_t>(Smi::FromInt(2)))); | |
895 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), eax); | |
896 __ mov(FieldOperand(edi, FixedArray::kHeaderSize + 0 * kPointerSize), esi); | |
897 __ lea(eax, Operand(edi, ebx, times_2, kParameterMapHeaderSize)); | |
898 __ mov(FieldOperand(edi, FixedArray::kHeaderSize + 1 * kPointerSize), eax); | |
899 | |
900 // Copy the parameter slots and the holes in the arguments. | |
901 // We need to fill in mapped_parameter_count slots. They index the context, | |
902 // where parameters are stored in reverse order, at | |
903 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1 | |
904 // The mapped parameter thus need to get indices | |
905 // MIN_CONTEXT_SLOTS+parameter_count-1 .. | |
906 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count | |
907 // We loop from right to left. | |
908 Label parameters_loop, parameters_test; | |
909 __ push(ecx); | |
910 __ mov(eax, Operand(esp, 3 * kPointerSize)); | |
911 __ mov(ebx, Immediate(Smi::FromInt(Context::MIN_CONTEXT_SLOTS))); | |
912 __ add(ebx, Operand(esp, 5 * kPointerSize)); | |
913 __ sub(ebx, eax); | |
914 __ mov(ecx, isolate()->factory()->the_hole_value()); | |
915 __ mov(edx, edi); | |
916 __ lea(edi, Operand(edi, eax, times_2, kParameterMapHeaderSize)); | |
917 // eax = loop variable (tagged) | |
918 // ebx = mapping index (tagged) | |
919 // ecx = the hole value | |
920 // edx = address of parameter map (tagged) | |
921 // edi = address of backing store (tagged) | |
922 // esp[0] = argument count (tagged) | |
923 // esp[4] = address of new object (tagged) | |
924 // esp[8] = address of receiver argument | |
925 // esp[12] = mapped parameter count (tagged) | |
926 // esp[16] = function | |
927 // esp[20] = parameter count (tagged) | |
928 __ jmp(¶meters_test, Label::kNear); | |
929 | |
930 __ bind(¶meters_loop); | |
931 __ sub(eax, Immediate(Smi::FromInt(1))); | |
932 __ mov(FieldOperand(edx, eax, times_2, kParameterMapHeaderSize), ebx); | |
933 __ mov(FieldOperand(edi, eax, times_2, FixedArray::kHeaderSize), ecx); | |
934 __ add(ebx, Immediate(Smi::FromInt(1))); | |
935 __ bind(¶meters_test); | |
936 __ test(eax, eax); | |
937 __ j(not_zero, ¶meters_loop, Label::kNear); | |
938 __ pop(ecx); | |
939 | |
940 __ bind(&skip_parameter_map); | |
941 | |
942 // ecx = argument count (tagged) | |
943 // edi = address of backing store (tagged) | |
944 // esp[0] = address of new object (tagged) | |
945 // esp[4] = address of receiver argument | |
946 // esp[8] = mapped parameter count (tagged) | |
947 // esp[12] = function | |
948 // esp[16] = parameter count (tagged) | |
949 // Copy arguments header and remaining slots (if there are any). | |
950 __ mov(FieldOperand(edi, FixedArray::kMapOffset), | |
951 Immediate(isolate()->factory()->fixed_array_map())); | |
952 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx); | |
953 | |
954 Label arguments_loop, arguments_test; | |
955 __ mov(ebx, Operand(esp, 2 * kPointerSize)); | |
956 __ mov(edx, Operand(esp, 1 * kPointerSize)); | |
957 __ sub(edx, ebx); // Is there a smarter way to do negative scaling? | |
958 __ sub(edx, ebx); | |
959 __ jmp(&arguments_test, Label::kNear); | |
960 | |
961 __ bind(&arguments_loop); | |
962 __ sub(edx, Immediate(kPointerSize)); | |
963 __ mov(eax, Operand(edx, 0)); | |
964 __ mov(FieldOperand(edi, ebx, times_2, FixedArray::kHeaderSize), eax); | |
965 __ add(ebx, Immediate(Smi::FromInt(1))); | |
966 | |
967 __ bind(&arguments_test); | |
968 __ cmp(ebx, ecx); | |
969 __ j(less, &arguments_loop, Label::kNear); | |
970 | |
971 // Restore. | |
972 __ pop(eax); // Address of arguments object. | |
973 __ Drop(4); | |
974 | |
975 // Return. | |
976 __ ret(0); | |
977 | |
978 // Do the runtime call to allocate the arguments object. | |
979 __ bind(&runtime); | |
980 __ pop(eax); // Remove saved mapped parameter count. | |
981 __ pop(edi); // Pop saved function. | |
982 __ pop(eax); // Remove saved parameter count. | |
983 __ pop(eax); // Pop return address. | |
984 __ push(edi); // Push function. | |
985 __ push(edx); // Push parameters pointer. | |
986 __ push(ecx); // Push parameter count. | |
987 __ push(eax); // Push return address. | |
988 __ TailCallRuntime(Runtime::kNewSloppyArguments); | |
989 } | |
990 | |
991 | |
992 void RegExpExecStub::Generate(MacroAssembler* masm) { | 730 void RegExpExecStub::Generate(MacroAssembler* masm) { |
993 // Just jump directly to runtime if native RegExp is not selected at compile | 731 // Just jump directly to runtime if native RegExp is not selected at compile |
994 // time or if regexp entry in generated code is turned off runtime switch or | 732 // time or if regexp entry in generated code is turned off runtime switch or |
995 // at compilation. | 733 // at compilation. |
996 #ifdef V8_INTERPRETED_REGEXP | 734 #ifdef V8_INTERPRETED_REGEXP |
997 __ TailCallRuntime(Runtime::kRegExpExec); | 735 __ TailCallRuntime(Runtime::kRegExpExec); |
998 #else // V8_INTERPRETED_REGEXP | 736 #else // V8_INTERPRETED_REGEXP |
999 | 737 |
1000 // Stack frame on entry. | 738 // Stack frame on entry. |
1001 // esp[0]: return address | 739 // esp[0]: return address |
(...skipping 4148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5150 __ CallRuntime(Runtime::kAllocateInNewSpace); | 4888 __ CallRuntime(Runtime::kAllocateInNewSpace); |
5151 __ mov(edx, eax); | 4889 __ mov(edx, eax); |
5152 __ Pop(ebx); | 4890 __ Pop(ebx); |
5153 __ Pop(eax); | 4891 __ Pop(eax); |
5154 } | 4892 } |
5155 __ jmp(&done_allocate); | 4893 __ jmp(&done_allocate); |
5156 } | 4894 } |
5157 } | 4895 } |
5158 | 4896 |
5159 | 4897 |
| 4898 void FastNewSloppyArgumentsStub::Generate(MacroAssembler* masm) { |
| 4899 // ----------- S t a t e ------------- |
| 4900 // -- edi : function |
| 4901 // -- esi : context |
| 4902 // -- ebp : frame pointer |
| 4903 // -- esp[0] : return address |
| 4904 // ----------------------------------- |
| 4905 __ AssertFunction(edi); |
| 4906 |
| 4907 // TODO(bmeurer): Cleanup to match the FastNewStrictArgumentsStub. |
| 4908 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
| 4909 __ mov(ecx, |
| 4910 FieldOperand(ecx, SharedFunctionInfo::kFormalParameterCountOffset)); |
| 4911 __ lea(edx, Operand(ebp, ecx, times_half_pointer_size, |
| 4912 StandardFrameConstants::kCallerSPOffset)); |
| 4913 |
| 4914 // ecx : number of parameters (tagged) |
| 4915 // edx : parameters pointer |
| 4916 // edi : function |
| 4917 // esp[0] : return address |
| 4918 |
| 4919 // Check if the calling frame is an arguments adaptor frame. |
| 4920 Label adaptor_frame, try_allocate, runtime; |
| 4921 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
| 4922 __ mov(eax, Operand(ebx, StandardFrameConstants::kContextOffset)); |
| 4923 __ cmp(eax, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 4924 __ j(equal, &adaptor_frame, Label::kNear); |
| 4925 |
| 4926 // No adaptor, parameter count = argument count. |
| 4927 __ mov(ebx, ecx); |
| 4928 __ push(ecx); |
| 4929 __ jmp(&try_allocate, Label::kNear); |
| 4930 |
| 4931 // We have an adaptor frame. Patch the parameters pointer. |
| 4932 __ bind(&adaptor_frame); |
| 4933 __ mov(ebx, ecx); |
| 4934 __ push(ecx); |
| 4935 __ mov(edx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); |
| 4936 __ mov(ecx, Operand(edx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 4937 __ lea(edx, Operand(edx, ecx, times_2, |
| 4938 StandardFrameConstants::kCallerSPOffset)); |
| 4939 |
| 4940 // ebx = parameter count (tagged) |
| 4941 // ecx = argument count (smi-tagged) |
| 4942 // Compute the mapped parameter count = min(ebx, ecx) in ebx. |
| 4943 __ cmp(ebx, ecx); |
| 4944 __ j(less_equal, &try_allocate, Label::kNear); |
| 4945 __ mov(ebx, ecx); |
| 4946 |
| 4947 // Save mapped parameter count and function. |
| 4948 __ bind(&try_allocate); |
| 4949 __ push(edi); |
| 4950 __ push(ebx); |
| 4951 |
| 4952 // Compute the sizes of backing store, parameter map, and arguments object. |
| 4953 // 1. Parameter map, has 2 extra words containing context and backing store. |
| 4954 const int kParameterMapHeaderSize = |
| 4955 FixedArray::kHeaderSize + 2 * kPointerSize; |
| 4956 Label no_parameter_map; |
| 4957 __ test(ebx, ebx); |
| 4958 __ j(zero, &no_parameter_map, Label::kNear); |
| 4959 __ lea(ebx, Operand(ebx, times_2, kParameterMapHeaderSize)); |
| 4960 __ bind(&no_parameter_map); |
| 4961 |
| 4962 // 2. Backing store. |
| 4963 __ lea(ebx, Operand(ebx, ecx, times_2, FixedArray::kHeaderSize)); |
| 4964 |
| 4965 // 3. Arguments object. |
| 4966 __ add(ebx, Immediate(JSSloppyArgumentsObject::kSize)); |
| 4967 |
| 4968 // Do the allocation of all three objects in one go. |
| 4969 __ Allocate(ebx, eax, edi, no_reg, &runtime, TAG_OBJECT); |
| 4970 |
| 4971 // eax = address of new object(s) (tagged) |
| 4972 // ecx = argument count (smi-tagged) |
| 4973 // esp[0] = mapped parameter count (tagged) |
| 4974 // esp[4] = function |
| 4975 // esp[8] = parameter count (tagged) |
| 4976 // Get the arguments map from the current native context into edi. |
| 4977 Label has_mapped_parameters, instantiate; |
| 4978 __ mov(edi, NativeContextOperand()); |
| 4979 __ mov(ebx, Operand(esp, 0 * kPointerSize)); |
| 4980 __ test(ebx, ebx); |
| 4981 __ j(not_zero, &has_mapped_parameters, Label::kNear); |
| 4982 __ mov( |
| 4983 edi, |
| 4984 Operand(edi, Context::SlotOffset(Context::SLOPPY_ARGUMENTS_MAP_INDEX))); |
| 4985 __ jmp(&instantiate, Label::kNear); |
| 4986 |
| 4987 __ bind(&has_mapped_parameters); |
| 4988 __ mov(edi, Operand(edi, Context::SlotOffset( |
| 4989 Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX))); |
| 4990 __ bind(&instantiate); |
| 4991 |
| 4992 // eax = address of new object (tagged) |
| 4993 // ebx = mapped parameter count (tagged) |
| 4994 // ecx = argument count (smi-tagged) |
| 4995 // edi = address of arguments map (tagged) |
| 4996 // esp[0] = mapped parameter count (tagged) |
| 4997 // esp[4] = function |
| 4998 // esp[8] = parameter count (tagged) |
| 4999 // Copy the JS object part. |
| 5000 __ mov(FieldOperand(eax, JSObject::kMapOffset), edi); |
| 5001 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), |
| 5002 masm->isolate()->factory()->empty_fixed_array()); |
| 5003 __ mov(FieldOperand(eax, JSObject::kElementsOffset), |
| 5004 masm->isolate()->factory()->empty_fixed_array()); |
| 5005 |
| 5006 // Set up the callee in-object property. |
| 5007 STATIC_ASSERT(JSSloppyArgumentsObject::kCalleeIndex == 1); |
| 5008 __ mov(edi, Operand(esp, 1 * kPointerSize)); |
| 5009 __ AssertNotSmi(edi); |
| 5010 __ mov(FieldOperand(eax, JSSloppyArgumentsObject::kCalleeOffset), edi); |
| 5011 |
| 5012 // Use the length (smi tagged) and set that as an in-object property too. |
| 5013 __ AssertSmi(ecx); |
| 5014 __ mov(FieldOperand(eax, JSSloppyArgumentsObject::kLengthOffset), ecx); |
| 5015 |
| 5016 // Set up the elements pointer in the allocated arguments object. |
| 5017 // If we allocated a parameter map, edi will point there, otherwise to the |
| 5018 // backing store. |
| 5019 __ lea(edi, Operand(eax, JSSloppyArgumentsObject::kSize)); |
| 5020 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); |
| 5021 |
| 5022 // eax = address of new object (tagged) |
| 5023 // ebx = mapped parameter count (tagged) |
| 5024 // ecx = argument count (tagged) |
| 5025 // edx = address of receiver argument |
| 5026 // edi = address of parameter map or backing store (tagged) |
| 5027 // esp[0] = mapped parameter count (tagged) |
| 5028 // esp[4] = function |
| 5029 // esp[8] = parameter count (tagged) |
| 5030 // Free two registers. |
| 5031 __ push(edx); |
| 5032 __ push(eax); |
| 5033 |
| 5034 // Initialize parameter map. If there are no mapped arguments, we're done. |
| 5035 Label skip_parameter_map; |
| 5036 __ test(ebx, ebx); |
| 5037 __ j(zero, &skip_parameter_map); |
| 5038 |
| 5039 __ mov(FieldOperand(edi, FixedArray::kMapOffset), |
| 5040 Immediate(isolate()->factory()->sloppy_arguments_elements_map())); |
| 5041 __ lea(eax, Operand(ebx, reinterpret_cast<intptr_t>(Smi::FromInt(2)))); |
| 5042 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), eax); |
| 5043 __ mov(FieldOperand(edi, FixedArray::kHeaderSize + 0 * kPointerSize), esi); |
| 5044 __ lea(eax, Operand(edi, ebx, times_2, kParameterMapHeaderSize)); |
| 5045 __ mov(FieldOperand(edi, FixedArray::kHeaderSize + 1 * kPointerSize), eax); |
| 5046 |
| 5047 // Copy the parameter slots and the holes in the arguments. |
| 5048 // We need to fill in mapped_parameter_count slots. They index the context, |
| 5049 // where parameters are stored in reverse order, at |
| 5050 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1 |
| 5051 // The mapped parameter thus need to get indices |
| 5052 // MIN_CONTEXT_SLOTS+parameter_count-1 .. |
| 5053 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count |
| 5054 // We loop from right to left. |
| 5055 Label parameters_loop, parameters_test; |
| 5056 __ push(ecx); |
| 5057 __ mov(eax, Operand(esp, 3 * kPointerSize)); |
| 5058 __ mov(ebx, Immediate(Smi::FromInt(Context::MIN_CONTEXT_SLOTS))); |
| 5059 __ add(ebx, Operand(esp, 5 * kPointerSize)); |
| 5060 __ sub(ebx, eax); |
| 5061 __ mov(ecx, isolate()->factory()->the_hole_value()); |
| 5062 __ mov(edx, edi); |
| 5063 __ lea(edi, Operand(edi, eax, times_2, kParameterMapHeaderSize)); |
| 5064 // eax = loop variable (tagged) |
| 5065 // ebx = mapping index (tagged) |
| 5066 // ecx = the hole value |
| 5067 // edx = address of parameter map (tagged) |
| 5068 // edi = address of backing store (tagged) |
| 5069 // esp[0] = argument count (tagged) |
| 5070 // esp[4] = address of new object (tagged) |
| 5071 // esp[8] = address of receiver argument |
| 5072 // esp[12] = mapped parameter count (tagged) |
| 5073 // esp[16] = function |
| 5074 // esp[20] = parameter count (tagged) |
| 5075 __ jmp(¶meters_test, Label::kNear); |
| 5076 |
| 5077 __ bind(¶meters_loop); |
| 5078 __ sub(eax, Immediate(Smi::FromInt(1))); |
| 5079 __ mov(FieldOperand(edx, eax, times_2, kParameterMapHeaderSize), ebx); |
| 5080 __ mov(FieldOperand(edi, eax, times_2, FixedArray::kHeaderSize), ecx); |
| 5081 __ add(ebx, Immediate(Smi::FromInt(1))); |
| 5082 __ bind(¶meters_test); |
| 5083 __ test(eax, eax); |
| 5084 __ j(not_zero, ¶meters_loop, Label::kNear); |
| 5085 __ pop(ecx); |
| 5086 |
| 5087 __ bind(&skip_parameter_map); |
| 5088 |
| 5089 // ecx = argument count (tagged) |
| 5090 // edi = address of backing store (tagged) |
| 5091 // esp[0] = address of new object (tagged) |
| 5092 // esp[4] = address of receiver argument |
| 5093 // esp[8] = mapped parameter count (tagged) |
| 5094 // esp[12] = function |
| 5095 // esp[16] = parameter count (tagged) |
| 5096 // Copy arguments header and remaining slots (if there are any). |
| 5097 __ mov(FieldOperand(edi, FixedArray::kMapOffset), |
| 5098 Immediate(isolate()->factory()->fixed_array_map())); |
| 5099 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx); |
| 5100 |
| 5101 Label arguments_loop, arguments_test; |
| 5102 __ mov(ebx, Operand(esp, 2 * kPointerSize)); |
| 5103 __ mov(edx, Operand(esp, 1 * kPointerSize)); |
| 5104 __ sub(edx, ebx); // Is there a smarter way to do negative scaling? |
| 5105 __ sub(edx, ebx); |
| 5106 __ jmp(&arguments_test, Label::kNear); |
| 5107 |
| 5108 __ bind(&arguments_loop); |
| 5109 __ sub(edx, Immediate(kPointerSize)); |
| 5110 __ mov(eax, Operand(edx, 0)); |
| 5111 __ mov(FieldOperand(edi, ebx, times_2, FixedArray::kHeaderSize), eax); |
| 5112 __ add(ebx, Immediate(Smi::FromInt(1))); |
| 5113 |
| 5114 __ bind(&arguments_test); |
| 5115 __ cmp(ebx, ecx); |
| 5116 __ j(less, &arguments_loop, Label::kNear); |
| 5117 |
| 5118 // Restore. |
| 5119 __ pop(eax); // Address of arguments object. |
| 5120 __ Drop(4); |
| 5121 |
| 5122 // Return. |
| 5123 __ ret(0); |
| 5124 |
| 5125 // Do the runtime call to allocate the arguments object. |
| 5126 __ bind(&runtime); |
| 5127 __ pop(eax); // Remove saved mapped parameter count. |
| 5128 __ pop(edi); // Pop saved function. |
| 5129 __ pop(eax); // Remove saved parameter count. |
| 5130 __ pop(eax); // Pop return address. |
| 5131 __ push(edi); // Push function. |
| 5132 __ push(edx); // Push parameters pointer. |
| 5133 __ push(ecx); // Push parameter count. |
| 5134 __ push(eax); // Push return address. |
| 5135 __ TailCallRuntime(Runtime::kNewSloppyArguments); |
| 5136 } |
| 5137 |
| 5138 |
5160 void FastNewStrictArgumentsStub::Generate(MacroAssembler* masm) { | 5139 void FastNewStrictArgumentsStub::Generate(MacroAssembler* masm) { |
5161 // ----------- S t a t e ------------- | 5140 // ----------- S t a t e ------------- |
5162 // -- edi : function | 5141 // -- edi : function |
5163 // -- esi : context | 5142 // -- esi : context |
5164 // -- ebp : frame pointer | 5143 // -- ebp : frame pointer |
5165 // -- esp[0] : return address | 5144 // -- esp[0] : return address |
5166 // ----------------------------------- | 5145 // ----------------------------------- |
5167 __ AssertFunction(edi); | 5146 __ AssertFunction(edi); |
5168 | 5147 |
5169 // For Ignition we need to skip all possible handler/stub frames until | 5148 // For Ignition we need to skip all possible handler/stub frames until |
(...skipping 651 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5821 return_value_operand, NULL); | 5800 return_value_operand, NULL); |
5822 } | 5801 } |
5823 | 5802 |
5824 | 5803 |
5825 #undef __ | 5804 #undef __ |
5826 | 5805 |
5827 } // namespace internal | 5806 } // namespace internal |
5828 } // namespace v8 | 5807 } // namespace v8 |
5829 | 5808 |
5830 #endif // V8_TARGET_ARCH_IA32 | 5809 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |