OLD | NEW |
---|---|
1 // Copyright 2009 the V8 project authors. All rights reserved. | 1 // Copyright 2009 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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
46 // Store the arguments adaptor context sentinel. | 46 // Store the arguments adaptor context sentinel. |
47 __ push(Immediate(ArgumentsAdaptorFrame::SENTINEL)); | 47 __ push(Immediate(ArgumentsAdaptorFrame::SENTINEL)); |
48 | 48 |
49 // Push the function on the stack. | 49 // Push the function on the stack. |
50 __ push(rdi); | 50 __ push(rdi); |
51 | 51 |
52 // Preserve the number of arguments on the stack. Must preserve both | 52 // Preserve the number of arguments on the stack. Must preserve both |
53 // eax and ebx because these registers are used when copying the | 53 // eax and ebx because these registers are used when copying the |
54 // arguments and the receiver. | 54 // arguments and the receiver. |
55 ASSERT(kSmiTagSize == 1); | 55 ASSERT(kSmiTagSize == 1); |
56 __ lea(rcx, Operand(rax, rax, kTimes1, kSmiTag)); | 56 __ lea(rcx, Operand(rax, rax, times_1, kSmiTag)); |
57 __ push(rcx); | 57 __ push(rcx); |
58 } | 58 } |
59 | 59 |
60 | 60 |
61 static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) { | 61 static void LeaveArgumentsAdaptorFrame(MacroAssembler* masm) { |
62 // Retrieve the number of arguments from the stack. Number is a Smi. | 62 // Retrieve the number of arguments from the stack. Number is a Smi. |
63 __ movq(rbx, Operand(rbp, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 63 __ movq(rbx, Operand(rbp, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
64 | 64 |
65 // Leave the frame. | 65 // Leave the frame. |
66 __ movq(rsp, rbp); | 66 __ movq(rsp, rbp); |
67 __ pop(rbp); | 67 __ pop(rbp); |
68 | 68 |
69 // Remove caller arguments from the stack. | 69 // Remove caller arguments from the stack. |
70 // rbx holds a Smi, so we convery to dword offset by multiplying by 4. | 70 // rbx holds a Smi, so we convery to dword offset by multiplying by 4. |
71 ASSERT_EQ(kSmiTagSize, 1 && kSmiTag == 0); | 71 ASSERT_EQ(kSmiTagSize, 1 && kSmiTag == 0); |
72 ASSERT_EQ(kPointerSize, (1 << kSmiTagSize) * 4); | 72 ASSERT_EQ(kPointerSize, (1 << kSmiTagSize) * 4); |
73 __ pop(rcx); | 73 __ pop(rcx); |
74 __ lea(rsp, Operand(rsp, rbx, kTimes4, 1 * kPointerSize)); // 1 ~ receiver | 74 __ lea(rsp, Operand(rsp, rbx, times_4, 1 * kPointerSize)); // 1 ~ receiver |
75 __ push(rcx); | 75 __ push(rcx); |
76 } | 76 } |
77 | 77 |
78 | 78 |
79 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { | 79 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { |
80 // ----------- S t a t e ------------- | 80 // ----------- S t a t e ------------- |
81 // -- rax : actual number of arguments | 81 // -- rax : actual number of arguments |
82 // -- rbx : expected number of arguments | 82 // -- rbx : expected number of arguments |
83 // -- rdx : code entry to call | 83 // -- rdx : code entry to call |
84 // ----------------------------------- | 84 // ----------------------------------- |
85 | 85 |
86 Label invoke, dont_adapt_arguments; | 86 Label invoke, dont_adapt_arguments; |
87 __ IncrementCounter(&Counters::arguments_adaptors, 1); | 87 __ IncrementCounter(&Counters::arguments_adaptors, 1); |
88 | 88 |
89 Label enough, too_few; | 89 Label enough, too_few; |
90 __ cmpq(rax, rbx); | 90 __ cmpq(rax, rbx); |
91 __ j(less, &too_few); | 91 __ j(less, &too_few); |
92 __ cmpq(rbx, Immediate(SharedFunctionInfo::kDontAdaptArgumentsSentinel)); | 92 __ cmpq(rbx, Immediate(SharedFunctionInfo::kDontAdaptArgumentsSentinel)); |
93 __ j(equal, &dont_adapt_arguments); | 93 __ j(equal, &dont_adapt_arguments); |
94 | 94 |
95 { // Enough parameters: Actual >= expected. | 95 { // Enough parameters: Actual >= expected. |
96 __ bind(&enough); | 96 __ bind(&enough); |
97 EnterArgumentsAdaptorFrame(masm); | 97 EnterArgumentsAdaptorFrame(masm); |
98 | 98 |
99 // Copy receiver and all expected arguments. | 99 // Copy receiver and all expected arguments. |
100 const int offset = StandardFrameConstants::kCallerSPOffset; | 100 const int offset = StandardFrameConstants::kCallerSPOffset; |
101 __ lea(rax, Operand(rbp, rax, kTimesPointerSize, offset)); | 101 __ lea(rax, Operand(rbp, rax, times_pointer_size, offset)); |
102 __ movq(rcx, Immediate(-1)); // account for receiver | 102 __ movq(rcx, Immediate(-1)); // account for receiver |
103 | 103 |
104 Label copy; | 104 Label copy; |
105 __ bind(©); | 105 __ bind(©); |
106 __ incq(rcx); | 106 __ incq(rcx); |
107 __ push(Operand(rax, 0)); | 107 __ push(Operand(rax, 0)); |
108 __ subq(rax, Immediate(kPointerSize)); | 108 __ subq(rax, Immediate(kPointerSize)); |
109 __ cmpq(rcx, rbx); | 109 __ cmpq(rcx, rbx); |
110 __ j(less, ©); | 110 __ j(less, ©); |
111 __ jmp(&invoke); | 111 __ jmp(&invoke); |
112 } | 112 } |
113 | 113 |
114 { // Too few parameters: Actual < expected. | 114 { // Too few parameters: Actual < expected. |
115 __ bind(&too_few); | 115 __ bind(&too_few); |
116 EnterArgumentsAdaptorFrame(masm); | 116 EnterArgumentsAdaptorFrame(masm); |
117 | 117 |
118 // Copy receiver and all actual arguments. | 118 // Copy receiver and all actual arguments. |
119 const int offset = StandardFrameConstants::kCallerSPOffset; | 119 const int offset = StandardFrameConstants::kCallerSPOffset; |
120 __ lea(rdi, Operand(rbp, rax, kTimesPointerSize, offset)); | 120 __ lea(rdi, Operand(rbp, rax, times_pointer_size, offset)); |
121 __ movq(rcx, Immediate(-1)); // account for receiver | 121 __ movq(rcx, Immediate(-1)); // account for receiver |
122 | 122 |
123 Label copy; | 123 Label copy; |
124 __ bind(©); | 124 __ bind(©); |
125 __ incq(rcx); | 125 __ incq(rcx); |
126 __ push(Operand(rdi, 0)); | 126 __ push(Operand(rdi, 0)); |
127 __ subq(rdi, Immediate(kPointerSize)); | 127 __ subq(rdi, Immediate(kPointerSize)); |
128 __ cmpq(rcx, rax); | 128 __ cmpq(rcx, rax); |
129 __ j(less, ©); | 129 __ j(less, ©); |
130 | 130 |
(...skipping 29 matching lines...) Expand all Loading... | |
160 | 160 |
161 | 161 |
162 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { | 162 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { |
163 masm->int3(); // UNIMPLEMENTED. | 163 masm->int3(); // UNIMPLEMENTED. |
164 } | 164 } |
165 | 165 |
166 void Builtins::Generate_FunctionCall(MacroAssembler* masm) { | 166 void Builtins::Generate_FunctionCall(MacroAssembler* masm) { |
167 masm->int3(); // UNIMPLEMENTED. | 167 masm->int3(); // UNIMPLEMENTED. |
168 } | 168 } |
169 | 169 |
170 | |
170 void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { | 171 void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { |
171 masm->int3(); // UNIMPLEMENTED. | 172 // ----------- S t a t e ------------- |
173 // -- rax: number of arguments | |
174 // -- rdi: constructor function | |
175 // ----------------------------------- | |
176 | |
177 Label non_function_call; | |
178 // Check that function is not a smi. | |
179 __ testl(rdi, Immediate(kSmiTagMask)); | |
180 __ j(zero, &non_function_call); | |
181 // Check that function is a JSFunction. | |
182 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); | |
183 __ j(not_equal, &non_function_call); | |
184 | |
185 // Jump to the function-specific construct stub. | |
186 __ movq(rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); | |
187 __ movq(rbx, FieldOperand(rbx, SharedFunctionInfo::kConstructStubOffset)); | |
188 __ lea(rbx, FieldOperand(rbx, Code::kHeaderSize)); | |
189 __ jmp(rbx); | |
190 | |
191 // edi: called object | |
192 // eax: number of arguments | |
193 __ bind(&non_function_call); | |
194 | |
195 // Set expected number of arguments to zero (not changing eax). | |
196 __ movq(rbx, Immediate(0)); | |
197 __ GetBuiltinEntry(rdx, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); | |
198 __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)), | |
199 RelocInfo::CODE_TARGET); | |
172 } | 200 } |
173 | 201 |
202 | |
174 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { | 203 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { |
175 masm->int3(); // UNIMPLEMENTED. | 204 // Enter a construct frame. |
205 __ EnterConstructFrame(); | |
William Hesse
2009/06/24 07:55:57
What is the calling convention of this function on
Mads Ager (chromium)
2009/06/24 08:18:50
rax: number of arguments
rdi: constructor function
| |
206 | |
207 // Store a smi-tagged arguments count on the stack. | |
208 __ shl(rax, Immediate(kSmiTagSize)); | |
209 __ push(rax); | |
210 | |
211 // Push the function to invoke on the stack. | |
212 __ push(rdi); | |
213 | |
214 // Try to allocate the object without transitioning into C code. If any of the | |
215 // preconditions is not met, the code bails out to the runtime call. | |
216 Label rt_call, allocated; | |
217 | |
218 // TODO(x64): Implement inlined allocation. | |
219 | |
220 // Allocate the new receiver object using the runtime call. | |
221 // rdi: function (constructor) | |
222 __ bind(&rt_call); | |
223 // Must restore edi (constructor) before calling runtime. | |
224 __ movq(rdi, Operand(rsp, 0)); | |
225 __ push(rdi); | |
226 __ CallRuntime(Runtime::kNewObject, 1); | |
227 __ movq(rbx, rax); // store result in ebx | |
William Hesse
2009/06/24 07:55:57
rbx, not ebx
Mads Ager (chromium)
2009/06/24 08:18:50
Done.
| |
228 | |
229 // New object allocated. | |
230 // ebx: newly allocated object | |
William Hesse
2009/06/24 07:55:57
rbx
Mads Ager (chromium)
2009/06/24 08:18:50
Done.
| |
231 __ bind(&allocated); | |
232 // Retrieve the function from the stack. | |
233 __ pop(rdi); | |
234 | |
235 // Retrieve smi-tagged arguments count from the stack. | |
236 __ movq(rax, Operand(rsp, 0)); | |
237 __ shr(rax, Immediate(kSmiTagSize)); | |
238 | |
239 // Push the allocated receiver to the stack. We need two copies | |
240 // because we may have to return the original one and the calling | |
241 // conventions dictate that the called function pops the receiver. | |
242 __ push(rbx); | |
243 __ push(rbx); | |
244 | |
245 // Setup pointer to last argument. | |
246 __ lea(rbx, Operand(rbp, StandardFrameConstants::kCallerSPOffset)); | |
247 | |
248 // Copy arguments and receiver to the expression stack. | |
249 Label loop, entry; | |
250 __ movq(rcx, rax); | |
251 __ jmp(&entry); | |
252 __ bind(&loop); | |
253 __ push(Operand(rbx, rcx, times_pointer_size, 0)); | |
William Hesse
2009/06/24 07:55:57
Isn't there a three-argument version of Operand(Re
Mads Ager (chromium)
2009/06/24 08:18:50
There isn't no, and I'm not sure it adds much to h
| |
254 __ bind(&entry); | |
255 __ decq(rcx); | |
256 __ j(greater_equal, &loop); | |
257 | |
258 // Call the function. | |
259 ParameterCount actual(rax); | |
260 __ InvokeFunction(rdi, actual, CALL_FUNCTION); | |
261 | |
262 // Restore context from the frame. | |
263 __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); | |
264 | |
265 // If the result is an object (in the ECMA sense), we should get rid | |
266 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 | |
267 // on page 74. | |
268 Label use_receiver, exit; | |
269 // If the result is a smi, it is *not* an object in the ECMA sense. | |
270 __ testl(rax, Immediate(kSmiTagMask)); | |
271 __ j(zero, &use_receiver); | |
272 | |
273 // If the type of the result (stored in its map) is less than | |
274 // FIRST_JS_OBJECT_TYPE, it is not an object in the ECMA sense. | |
275 __ movq(rcx, FieldOperand(rax, HeapObject::kMapOffset)); | |
276 __ CmpInstanceType(rcx, FIRST_JS_OBJECT_TYPE); | |
William Hesse
2009/06/24 07:55:57
CmpInstanceType can now be written inline as a sin
Mads Ager (chromium)
2009/06/24 08:18:50
CmpInstanceType does the one instruction compare.
| |
277 __ j(greater_equal, &exit); | |
278 | |
279 // Throw away the result of the constructor invocation and use the | |
280 // on-stack receiver as the result. | |
281 __ bind(&use_receiver); | |
282 __ movq(rax, Operand(rsp, 0)); | |
283 | |
284 // Restore the arguments count and leave the construct frame. | |
285 __ bind(&exit); | |
286 __ movq(rbx, Operand(rsp, kPointerSize)); // get arguments count | |
287 __ LeaveConstructFrame(); | |
288 | |
289 // Remove caller arguments from the stack and return. | |
290 ASSERT(kSmiTagSize == 1 && kSmiTag == 0); | |
291 __ pop(rcx); | |
292 __ lea(rsp, Operand(rsp, rbx, times_4, 1 * kPointerSize)); // 1 ~ receiver | |
293 __ push(rcx); | |
294 __ ret(0); | |
176 } | 295 } |
177 | 296 |
297 | |
178 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, | 298 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, |
179 bool is_construct) { | 299 bool is_construct) { |
180 // Expects five C++ function parameters. | 300 // Expects five C++ function parameters. |
181 // - Address entry (ignored) | 301 // - Address entry (ignored) |
182 // - JSFunction* function ( | 302 // - JSFunction* function ( |
183 // - Object* receiver | 303 // - Object* receiver |
184 // - int argc | 304 // - int argc |
185 // - Object*** argv | 305 // - Object*** argv |
186 // (see Handle::Invoke in execution.cc). | 306 // (see Handle::Invoke in execution.cc). |
187 | 307 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
251 // rsi : context | 371 // rsi : context |
252 // rdi : function | 372 // rdi : function |
253 | 373 |
254 // Copy arguments to the stack in a loop. | 374 // Copy arguments to the stack in a loop. |
255 // Register rbx points to array of pointers to handle locations. | 375 // Register rbx points to array of pointers to handle locations. |
256 // Push the values of these handles. | 376 // Push the values of these handles. |
257 Label loop, entry; | 377 Label loop, entry; |
258 __ xor_(rcx, rcx); // Set loop variable to 0. | 378 __ xor_(rcx, rcx); // Set loop variable to 0. |
259 __ jmp(&entry); | 379 __ jmp(&entry); |
260 __ bind(&loop); | 380 __ bind(&loop); |
261 __ movq(kScratchRegister, Operand(rbx, rcx, kTimesPointerSize, 0)); | 381 __ movq(kScratchRegister, Operand(rbx, rcx, times_pointer_size, 0)); |
262 __ push(Operand(kScratchRegister, 0)); // dereference handle | 382 __ push(Operand(kScratchRegister, 0)); // dereference handle |
263 __ addq(rcx, Immediate(1)); | 383 __ addq(rcx, Immediate(1)); |
264 __ bind(&entry); | 384 __ bind(&entry); |
265 __ cmpq(rcx, rax); | 385 __ cmpq(rcx, rax); |
266 __ j(not_equal, &loop); | 386 __ j(not_equal, &loop); |
267 | 387 |
268 // Invoke the code. | 388 // Invoke the code. |
269 if (is_construct) { | 389 if (is_construct) { |
270 // Expects rdi to hold function pointer. | 390 // Expects rdi to hold function pointer. |
271 __ movq(kScratchRegister, | 391 __ movq(kScratchRegister, |
(...skipping 18 matching lines...) Expand all Loading... | |
290 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { | 410 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { |
291 Generate_JSEntryTrampolineHelper(masm, false); | 411 Generate_JSEntryTrampolineHelper(masm, false); |
292 } | 412 } |
293 | 413 |
294 | 414 |
295 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { | 415 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { |
296 Generate_JSEntryTrampolineHelper(masm, true); | 416 Generate_JSEntryTrampolineHelper(masm, true); |
297 } | 417 } |
298 | 418 |
299 } } // namespace v8::internal | 419 } } // namespace v8::internal |
OLD | NEW |