Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/x64/builtins-x64.cc

Issue 146029: x64 code generation for construct calls, declaring global variables... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 11 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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(&copy); 105 __ bind(&copy);
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, &copy); 110 __ j(less, &copy);
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(&copy); 124 __ bind(&copy);
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, &copy); 129 __ j(less, &copy);
130 130
(...skipping 29 matching lines...) Expand all
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
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
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
OLDNEW
« no previous file with comments | « src/x64/assembler-x64.cc ('k') | src/x64/codegen-x64.cc » ('j') | src/x64/codegen-x64.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698