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 |
730 void RegExpExecStub::Generate(MacroAssembler* masm) { | 992 void RegExpExecStub::Generate(MacroAssembler* masm) { |
731 // Just jump directly to runtime if native RegExp is not selected at compile | 993 // Just jump directly to runtime if native RegExp is not selected at compile |
732 // time or if regexp entry in generated code is turned off runtime switch or | 994 // time or if regexp entry in generated code is turned off runtime switch or |
733 // at compilation. | 995 // at compilation. |
734 #ifdef V8_INTERPRETED_REGEXP | 996 #ifdef V8_INTERPRETED_REGEXP |
735 __ TailCallRuntime(Runtime::kRegExpExec); | 997 __ TailCallRuntime(Runtime::kRegExpExec); |
736 #else // V8_INTERPRETED_REGEXP | 998 #else // V8_INTERPRETED_REGEXP |
737 | 999 |
738 // Stack frame on entry. | 1000 // Stack frame on entry. |
739 // esp[0]: return address | 1001 // esp[0]: return address |
(...skipping 4148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4888 __ CallRuntime(Runtime::kAllocateInNewSpace); | 5150 __ CallRuntime(Runtime::kAllocateInNewSpace); |
4889 __ mov(edx, eax); | 5151 __ mov(edx, eax); |
4890 __ Pop(ebx); | 5152 __ Pop(ebx); |
4891 __ Pop(eax); | 5153 __ Pop(eax); |
4892 } | 5154 } |
4893 __ jmp(&done_allocate); | 5155 __ jmp(&done_allocate); |
4894 } | 5156 } |
4895 } | 5157 } |
4896 | 5158 |
4897 | 5159 |
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 | |
5139 void FastNewStrictArgumentsStub::Generate(MacroAssembler* masm) { | 5160 void FastNewStrictArgumentsStub::Generate(MacroAssembler* masm) { |
5140 // ----------- S t a t e ------------- | 5161 // ----------- S t a t e ------------- |
5141 // -- edi : function | 5162 // -- edi : function |
5142 // -- esi : context | 5163 // -- esi : context |
5143 // -- ebp : frame pointer | 5164 // -- ebp : frame pointer |
5144 // -- esp[0] : return address | 5165 // -- esp[0] : return address |
5145 // ----------------------------------- | 5166 // ----------------------------------- |
5146 __ AssertFunction(edi); | 5167 __ AssertFunction(edi); |
5147 | 5168 |
5148 // For Ignition we need to skip all possible handler/stub frames until | 5169 // 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... |
5800 return_value_operand, NULL); | 5821 return_value_operand, NULL); |
5801 } | 5822 } |
5802 | 5823 |
5803 | 5824 |
5804 #undef __ | 5825 #undef __ |
5805 | 5826 |
5806 } // namespace internal | 5827 } // namespace internal |
5807 } // namespace v8 | 5828 } // namespace v8 |
5808 | 5829 |
5809 #endif // V8_TARGET_ARCH_IA32 | 5830 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |