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 859 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
870 Label no_parameter_map; | 870 Label no_parameter_map; |
871 __ test(ebx, ebx); | 871 __ test(ebx, ebx); |
872 __ j(zero, &no_parameter_map, Label::kNear); | 872 __ j(zero, &no_parameter_map, Label::kNear); |
873 __ lea(ebx, Operand(ebx, times_2, kParameterMapHeaderSize)); | 873 __ lea(ebx, Operand(ebx, times_2, kParameterMapHeaderSize)); |
874 __ bind(&no_parameter_map); | 874 __ bind(&no_parameter_map); |
875 | 875 |
876 // 2. Backing store. | 876 // 2. Backing store. |
877 __ lea(ebx, Operand(ebx, ecx, times_2, FixedArray::kHeaderSize)); | 877 __ lea(ebx, Operand(ebx, ecx, times_2, FixedArray::kHeaderSize)); |
878 | 878 |
879 // 3. Arguments object. | 879 // 3. Arguments object. |
880 __ add(ebx, Immediate(Heap::kSloppyArgumentsObjectSize)); | 880 __ add(ebx, Immediate(JSSloppyArgumentsObject::kSize)); |
881 | 881 |
882 // Do the allocation of all three objects in one go. | 882 // Do the allocation of all three objects in one go. |
883 __ Allocate(ebx, eax, edi, no_reg, &runtime, TAG_OBJECT); | 883 __ Allocate(ebx, eax, edi, no_reg, &runtime, TAG_OBJECT); |
884 | 884 |
885 // eax = address of new object(s) (tagged) | 885 // eax = address of new object(s) (tagged) |
886 // ecx = argument count (smi-tagged) | 886 // ecx = argument count (smi-tagged) |
887 // esp[0] = mapped parameter count (tagged) | 887 // esp[0] = mapped parameter count (tagged) |
888 // esp[4] = function | 888 // esp[4] = function |
889 // esp[8] = parameter count (tagged) | 889 // esp[8] = parameter count (tagged) |
890 // Get the arguments map from the current native context into edi. | 890 // Get the arguments map from the current native context into edi. |
(...skipping 20 matching lines...) Expand all Loading... |
911 // esp[4] = function | 911 // esp[4] = function |
912 // esp[8] = parameter count (tagged) | 912 // esp[8] = parameter count (tagged) |
913 // Copy the JS object part. | 913 // Copy the JS object part. |
914 __ mov(FieldOperand(eax, JSObject::kMapOffset), edi); | 914 __ mov(FieldOperand(eax, JSObject::kMapOffset), edi); |
915 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), | 915 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), |
916 masm->isolate()->factory()->empty_fixed_array()); | 916 masm->isolate()->factory()->empty_fixed_array()); |
917 __ mov(FieldOperand(eax, JSObject::kElementsOffset), | 917 __ mov(FieldOperand(eax, JSObject::kElementsOffset), |
918 masm->isolate()->factory()->empty_fixed_array()); | 918 masm->isolate()->factory()->empty_fixed_array()); |
919 | 919 |
920 // Set up the callee in-object property. | 920 // Set up the callee in-object property. |
921 STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); | 921 STATIC_ASSERT(JSSloppyArgumentsObject::kCalleeIndex == 1); |
922 __ mov(edi, Operand(esp, 1 * kPointerSize)); | 922 __ mov(edi, Operand(esp, 1 * kPointerSize)); |
923 __ AssertNotSmi(edi); | 923 __ AssertNotSmi(edi); |
924 __ mov(FieldOperand(eax, JSObject::kHeaderSize + | 924 __ mov(FieldOperand(eax, JSSloppyArgumentsObject::kCalleeOffset), edi); |
925 Heap::kArgumentsCalleeIndex * kPointerSize), | |
926 edi); | |
927 | 925 |
928 // Use the length (smi tagged) and set that as an in-object property too. | 926 // Use the length (smi tagged) and set that as an in-object property too. |
929 __ AssertSmi(ecx); | 927 __ AssertSmi(ecx); |
930 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); | 928 __ mov(FieldOperand(eax, JSSloppyArgumentsObject::kLengthOffset), ecx); |
931 __ mov(FieldOperand(eax, JSObject::kHeaderSize + | |
932 Heap::kArgumentsLengthIndex * kPointerSize), | |
933 ecx); | |
934 | 929 |
935 // Set up the elements pointer in the allocated arguments object. | 930 // Set up the elements pointer in the allocated arguments object. |
936 // If we allocated a parameter map, edi will point there, otherwise to the | 931 // If we allocated a parameter map, edi will point there, otherwise to the |
937 // backing store. | 932 // backing store. |
938 __ lea(edi, Operand(eax, Heap::kSloppyArgumentsObjectSize)); | 933 __ lea(edi, Operand(eax, JSSloppyArgumentsObject::kSize)); |
939 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); | 934 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); |
940 | 935 |
941 // eax = address of new object (tagged) | 936 // eax = address of new object (tagged) |
942 // ebx = mapped parameter count (tagged) | 937 // ebx = mapped parameter count (tagged) |
943 // ecx = argument count (tagged) | 938 // ecx = argument count (tagged) |
944 // edx = address of receiver argument | 939 // edx = address of receiver argument |
945 // edi = address of parameter map or backing store (tagged) | 940 // edi = address of parameter map or backing store (tagged) |
946 // esp[0] = mapped parameter count (tagged) | 941 // esp[0] = mapped parameter count (tagged) |
947 // esp[4] = function | 942 // esp[4] = function |
948 // esp[8] = parameter count (tagged) | 943 // esp[8] = parameter count (tagged) |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1048 __ pop(eax); // Remove saved parameter count. | 1043 __ pop(eax); // Remove saved parameter count. |
1049 __ pop(eax); // Pop return address. | 1044 __ pop(eax); // Pop return address. |
1050 __ push(edi); // Push function. | 1045 __ push(edi); // Push function. |
1051 __ push(edx); // Push parameters pointer. | 1046 __ push(edx); // Push parameters pointer. |
1052 __ push(ecx); // Push parameter count. | 1047 __ push(ecx); // Push parameter count. |
1053 __ push(eax); // Push return address. | 1048 __ push(eax); // Push return address. |
1054 __ TailCallRuntime(Runtime::kNewSloppyArguments); | 1049 __ TailCallRuntime(Runtime::kNewSloppyArguments); |
1055 } | 1050 } |
1056 | 1051 |
1057 | 1052 |
1058 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { | |
1059 // ecx : number of parameters (tagged) | |
1060 // edx : parameters pointer | |
1061 // edi : function | |
1062 // esp[0] : return address | |
1063 | |
1064 DCHECK(edi.is(ArgumentsAccessNewDescriptor::function())); | |
1065 DCHECK(ecx.is(ArgumentsAccessNewDescriptor::parameter_count())); | |
1066 DCHECK(edx.is(ArgumentsAccessNewDescriptor::parameter_pointer())); | |
1067 | |
1068 // Check if the calling frame is an arguments adaptor frame. | |
1069 Label try_allocate, runtime; | |
1070 __ mov(ebx, Operand(ebp, StandardFrameConstants::kCallerFPOffset)); | |
1071 __ mov(eax, Operand(ebx, StandardFrameConstants::kContextOffset)); | |
1072 __ cmp(eax, Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | |
1073 __ j(not_equal, &try_allocate, Label::kNear); | |
1074 | |
1075 // Patch the arguments.length and the parameters pointer. | |
1076 __ mov(ecx, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | |
1077 __ lea(edx, | |
1078 Operand(ebx, ecx, times_2, StandardFrameConstants::kCallerSPOffset)); | |
1079 | |
1080 // Try the new space allocation. Start out with computing the size of | |
1081 // the arguments object and the elements array. | |
1082 Label add_arguments_object; | |
1083 __ bind(&try_allocate); | |
1084 __ mov(eax, ecx); | |
1085 __ test(eax, eax); | |
1086 __ j(zero, &add_arguments_object, Label::kNear); | |
1087 __ lea(eax, Operand(eax, times_2, FixedArray::kHeaderSize)); | |
1088 __ bind(&add_arguments_object); | |
1089 __ add(eax, Immediate(Heap::kStrictArgumentsObjectSize)); | |
1090 | |
1091 // Do the allocation of both objects in one go. | |
1092 __ Allocate(eax, eax, ebx, no_reg, &runtime, TAG_OBJECT); | |
1093 | |
1094 // Get the arguments map from the current native context. | |
1095 __ mov(edi, NativeContextOperand()); | |
1096 __ mov(edi, ContextOperand(edi, Context::STRICT_ARGUMENTS_MAP_INDEX)); | |
1097 | |
1098 __ mov(FieldOperand(eax, JSObject::kMapOffset), edi); | |
1099 __ mov(FieldOperand(eax, JSObject::kPropertiesOffset), | |
1100 masm->isolate()->factory()->empty_fixed_array()); | |
1101 __ mov(FieldOperand(eax, JSObject::kElementsOffset), | |
1102 masm->isolate()->factory()->empty_fixed_array()); | |
1103 | |
1104 // Get the length (smi tagged) and set that as an in-object property too. | |
1105 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); | |
1106 __ AssertSmi(ecx); | |
1107 __ mov(FieldOperand(eax, JSObject::kHeaderSize + | |
1108 Heap::kArgumentsLengthIndex * kPointerSize), | |
1109 ecx); | |
1110 | |
1111 // If there are no actual arguments, we're done. | |
1112 Label done; | |
1113 __ test(ecx, ecx); | |
1114 __ j(zero, &done, Label::kNear); | |
1115 | |
1116 // Set up the elements pointer in the allocated arguments object and | |
1117 // initialize the header in the elements fixed array. | |
1118 __ lea(edi, Operand(eax, Heap::kStrictArgumentsObjectSize)); | |
1119 __ mov(FieldOperand(eax, JSObject::kElementsOffset), edi); | |
1120 __ mov(FieldOperand(edi, FixedArray::kMapOffset), | |
1121 Immediate(isolate()->factory()->fixed_array_map())); | |
1122 __ mov(FieldOperand(edi, FixedArray::kLengthOffset), ecx); | |
1123 | |
1124 // Untag the length for the loop below. | |
1125 __ SmiUntag(ecx); | |
1126 | |
1127 // Copy the fixed array slots. | |
1128 Label loop; | |
1129 __ bind(&loop); | |
1130 __ mov(ebx, Operand(edx, -1 * kPointerSize)); // Skip receiver. | |
1131 __ mov(FieldOperand(edi, FixedArray::kHeaderSize), ebx); | |
1132 __ add(edi, Immediate(kPointerSize)); | |
1133 __ sub(edx, Immediate(kPointerSize)); | |
1134 __ dec(ecx); | |
1135 __ j(not_zero, &loop); | |
1136 | |
1137 // Return. | |
1138 __ bind(&done); | |
1139 __ ret(0); | |
1140 | |
1141 // Do the runtime call to allocate the arguments object. | |
1142 __ bind(&runtime); | |
1143 __ pop(eax); // Pop return address. | |
1144 __ push(edi); // Push function. | |
1145 __ push(edx); // Push parameters pointer. | |
1146 __ push(ecx); // Push parameter count. | |
1147 __ push(eax); // Push return address. | |
1148 __ TailCallRuntime(Runtime::kNewStrictArguments); | |
1149 } | |
1150 | |
1151 | |
1152 void RegExpExecStub::Generate(MacroAssembler* masm) { | 1053 void RegExpExecStub::Generate(MacroAssembler* masm) { |
1153 // Just jump directly to runtime if native RegExp is not selected at compile | 1054 // Just jump directly to runtime if native RegExp is not selected at compile |
1154 // time or if regexp entry in generated code is turned off runtime switch or | 1055 // time or if regexp entry in generated code is turned off runtime switch or |
1155 // at compilation. | 1056 // at compilation. |
1156 #ifdef V8_INTERPRETED_REGEXP | 1057 #ifdef V8_INTERPRETED_REGEXP |
1157 __ TailCallRuntime(Runtime::kRegExpExec); | 1058 __ TailCallRuntime(Runtime::kRegExpExec); |
1158 #else // V8_INTERPRETED_REGEXP | 1059 #else // V8_INTERPRETED_REGEXP |
1159 | 1060 |
1160 // Stack frame on entry. | 1061 // Stack frame on entry. |
1161 // esp[0]: return address | 1062 // esp[0]: return address |
(...skipping 4148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5310 __ CallRuntime(Runtime::kAllocateInNewSpace); | 5211 __ CallRuntime(Runtime::kAllocateInNewSpace); |
5311 __ mov(edx, eax); | 5212 __ mov(edx, eax); |
5312 __ Pop(ebx); | 5213 __ Pop(ebx); |
5313 __ Pop(eax); | 5214 __ Pop(eax); |
5314 } | 5215 } |
5315 __ jmp(&done_allocate); | 5216 __ jmp(&done_allocate); |
5316 } | 5217 } |
5317 } | 5218 } |
5318 | 5219 |
5319 | 5220 |
| 5221 void FastNewStrictArgumentsStub::Generate(MacroAssembler* masm) { |
| 5222 // ----------- S t a t e ------------- |
| 5223 // -- edi : function |
| 5224 // -- esi : context |
| 5225 // -- ebp : frame pointer |
| 5226 // -- esp[0] : return address |
| 5227 // ----------------------------------- |
| 5228 __ AssertFunction(edi); |
| 5229 |
| 5230 // For Ignition we need to skip all possible handler/stub frames until |
| 5231 // we reach the JavaScript frame for the function (similar to what the |
| 5232 // runtime fallback implementation does). So make edx point to that |
| 5233 // JavaScript frame. |
| 5234 { |
| 5235 Label loop, loop_entry; |
| 5236 __ mov(edx, ebp); |
| 5237 __ jmp(&loop_entry, Label::kNear); |
| 5238 __ bind(&loop); |
| 5239 __ mov(edx, Operand(edx, StandardFrameConstants::kCallerFPOffset)); |
| 5240 __ bind(&loop_entry); |
| 5241 __ cmp(edi, Operand(edx, StandardFrameConstants::kMarkerOffset)); |
| 5242 __ j(not_equal, &loop); |
| 5243 } |
| 5244 |
| 5245 // Check if we have an arguments adaptor frame below the function frame. |
| 5246 Label arguments_adaptor, arguments_done; |
| 5247 __ mov(ebx, Operand(edx, StandardFrameConstants::kCallerFPOffset)); |
| 5248 __ cmp(Operand(ebx, StandardFrameConstants::kContextOffset), |
| 5249 Immediate(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
| 5250 __ j(equal, &arguments_adaptor, Label::kNear); |
| 5251 { |
| 5252 __ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
| 5253 __ mov(eax, |
| 5254 FieldOperand(eax, SharedFunctionInfo::kFormalParameterCountOffset)); |
| 5255 __ lea(ebx, |
| 5256 Operand(edx, eax, times_half_pointer_size, |
| 5257 StandardFrameConstants::kCallerSPOffset - 1 * kPointerSize)); |
| 5258 } |
| 5259 __ jmp(&arguments_done, Label::kNear); |
| 5260 __ bind(&arguments_adaptor); |
| 5261 { |
| 5262 __ mov(eax, Operand(ebx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 5263 __ lea(ebx, |
| 5264 Operand(ebx, eax, times_half_pointer_size, |
| 5265 StandardFrameConstants::kCallerSPOffset - 1 * kPointerSize)); |
| 5266 } |
| 5267 __ bind(&arguments_done); |
| 5268 |
| 5269 // ----------- S t a t e ------------- |
| 5270 // -- eax : number of arguments (tagged) |
| 5271 // -- ebx : pointer to the first argument |
| 5272 // -- esi : context |
| 5273 // -- esp[0] : return address |
| 5274 // ----------------------------------- |
| 5275 |
| 5276 // Allocate space for the strict arguments object plus the backing store. |
| 5277 Label allocate, done_allocate; |
| 5278 __ lea(ecx, |
| 5279 Operand(eax, times_half_pointer_size, |
| 5280 JSStrictArgumentsObject::kSize + FixedArray::kHeaderSize)); |
| 5281 __ Allocate(ecx, edx, edi, no_reg, &allocate, TAG_OBJECT); |
| 5282 __ bind(&done_allocate); |
| 5283 |
| 5284 // Setup the elements array in edx. |
| 5285 __ mov(FieldOperand(edx, FixedArray::kMapOffset), |
| 5286 isolate()->factory()->fixed_array_map()); |
| 5287 __ mov(FieldOperand(edx, FixedArray::kLengthOffset), eax); |
| 5288 { |
| 5289 Label loop, done_loop; |
| 5290 __ Move(ecx, Smi::FromInt(0)); |
| 5291 __ bind(&loop); |
| 5292 __ cmp(ecx, eax); |
| 5293 __ j(equal, &done_loop, Label::kNear); |
| 5294 __ mov(edi, Operand(ebx, 0 * kPointerSize)); |
| 5295 __ mov(FieldOperand(edx, ecx, times_half_pointer_size, |
| 5296 FixedArray::kHeaderSize), |
| 5297 edi); |
| 5298 __ sub(ebx, Immediate(1 * kPointerSize)); |
| 5299 __ add(ecx, Immediate(Smi::FromInt(1))); |
| 5300 __ jmp(&loop); |
| 5301 __ bind(&done_loop); |
| 5302 } |
| 5303 |
| 5304 // Setup the rest parameter array in edi. |
| 5305 __ lea(edi, |
| 5306 Operand(edx, eax, times_half_pointer_size, FixedArray::kHeaderSize)); |
| 5307 __ LoadGlobalFunction(Context::STRICT_ARGUMENTS_MAP_INDEX, ecx); |
| 5308 __ mov(FieldOperand(edi, JSStrictArgumentsObject::kMapOffset), ecx); |
| 5309 __ mov(FieldOperand(edi, JSStrictArgumentsObject::kPropertiesOffset), |
| 5310 isolate()->factory()->empty_fixed_array()); |
| 5311 __ mov(FieldOperand(edi, JSStrictArgumentsObject::kElementsOffset), edx); |
| 5312 __ mov(FieldOperand(edi, JSStrictArgumentsObject::kLengthOffset), eax); |
| 5313 STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize); |
| 5314 __ mov(eax, edi); |
| 5315 __ Ret(); |
| 5316 |
| 5317 // Fall back to %AllocateInNewSpace. |
| 5318 __ bind(&allocate); |
| 5319 { |
| 5320 FrameScope scope(masm, StackFrame::INTERNAL); |
| 5321 __ SmiTag(ecx); |
| 5322 __ Push(eax); |
| 5323 __ Push(ebx); |
| 5324 __ Push(ecx); |
| 5325 __ CallRuntime(Runtime::kAllocateInNewSpace); |
| 5326 __ mov(edx, eax); |
| 5327 __ Pop(ebx); |
| 5328 __ Pop(eax); |
| 5329 } |
| 5330 __ jmp(&done_allocate); |
| 5331 } |
| 5332 |
| 5333 |
5320 void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) { | 5334 void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) { |
5321 Register context_reg = esi; | 5335 Register context_reg = esi; |
5322 Register slot_reg = ebx; | 5336 Register slot_reg = ebx; |
5323 Register result_reg = eax; | 5337 Register result_reg = eax; |
5324 Label slow_case; | 5338 Label slow_case; |
5325 | 5339 |
5326 // Go up context chain to the script context. | 5340 // Go up context chain to the script context. |
5327 for (int i = 0; i < depth(); ++i) { | 5341 for (int i = 0; i < depth(); ++i) { |
5328 __ mov(result_reg, ContextOperand(context_reg, Context::PREVIOUS_INDEX)); | 5342 __ mov(result_reg, ContextOperand(context_reg, Context::PREVIOUS_INDEX)); |
5329 context_reg = result_reg; | 5343 context_reg = result_reg; |
(...skipping 538 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5868 return_value_operand, NULL); | 5882 return_value_operand, NULL); |
5869 } | 5883 } |
5870 | 5884 |
5871 | 5885 |
5872 #undef __ | 5886 #undef __ |
5873 | 5887 |
5874 } // namespace internal | 5888 } // namespace internal |
5875 } // namespace v8 | 5889 } // namespace v8 |
5876 | 5890 |
5877 #endif // V8_TARGET_ARCH_IA32 | 5891 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |