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

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

Issue 1930: Adapt to new calling convention on ARM. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 12 years, 3 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
« no previous file with comments | « src/builtins.cc ('k') | src/builtins-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2008 the V8 project authors. All rights reserved. 1 // Copyright 2006-2008 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 25 matching lines...) Expand all
36 36
37 #define __ masm-> 37 #define __ masm->
38 38
39 39
40 void Builtins::Generate_Adaptor(MacroAssembler* masm, 40 void Builtins::Generate_Adaptor(MacroAssembler* masm,
41 int argc, 41 int argc,
42 CFunctionId id) { 42 CFunctionId id) {
43 // r0 contains the number of arguments excluding the receiver. 43 // r0 contains the number of arguments excluding the receiver.
44 // JumpToBuiltin expects r0 to contains the number of arguments 44 // JumpToBuiltin expects r0 to contains the number of arguments
45 // including the receiver. 45 // including the receiver.
46 __ add(r0, r0, Operand(1)); 46 __ mov(r0, Operand(argc + 1));
47 __ mov(ip, Operand(ExternalReference::builtin_passed_function()));
48 __ str(r1, MemOperand(ip, 0));
47 __ JumpToBuiltin(ExternalReference(id)); 49 __ JumpToBuiltin(ExternalReference(id));
48 } 50 }
49 51
50 52
51 void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { 53 void Builtins::Generate_JSConstructCall(MacroAssembler* masm) {
52 // r0: number of arguments 54 // ----------- S t a t e -------------
55 // -- r0 : number of arguments
56 // -- r1 : constructor function
57 // -- lr : return address
58 // -- sp[...]: constructor arguments
59 // -----------------------------------
53 60
54 __ EnterJSFrame(0); 61 // Enter an internal frame.
62 __ EnterInternalFrame();
63
64 // Preserve the two incoming parameters
65 __ mov(r0, Operand(r0, LSL, kSmiTagSize));
66 __ push(r0); // smi-tagged arguments count
67 __ push(r1); // constructor function
55 68
56 // Allocate the new receiver object. 69 // Allocate the new receiver object.
57 __ ldr(r0, MemOperand(pp, JavaScriptFrameConstants::kFunctionOffset)); 70 __ push(r1); // argument for Runtime_NewObject
58 __ push(r0);
59 __ CallRuntime(Runtime::kNewObject, 1); 71 __ CallRuntime(Runtime::kNewObject, 1);
60 __ push(r0); // save the receiver 72 __ push(r0); // save the receiver
61 73
62 // Push the function and the allocated receiver from the stack. 74 // Push the function and the allocated receiver from the stack.
63 __ ldr(r1, MemOperand(pp, JavaScriptFrameConstants::kFunctionOffset)); 75 // sp[0]: receiver (newly allocated object)
76 // sp[1]: constructor function
77 // sp[2]: number of arguments (smi-tagged)
78 __ ldr(r1, MemOperand(sp, kPointerSize));
64 __ push(r1); // function 79 __ push(r1); // function
65 __ push(r0); // receiver 80 __ push(r0); // receiver
66 81
67 // Restore the arguments length from the stack. 82 // Reload the number of arguments from the stack.
68 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kArgsLengthOffset)); 83 // r1: constructor function
84 // sp[0]: receiver
85 // sp[1]: constructor function
86 // sp[2]: receiver
87 // sp[3]: constructor function
88 // sp[4]: number of arguments (smi-tagged)
89 __ ldr(r3, MemOperand(sp, 4 * kPointerSize));
69 90
70 // Setup pointer to last argument - receiver is not counted. 91 // Setup pointer to last argument.
71 __ sub(r2, pp, Operand(r0, LSL, kPointerSizeLog2)); 92 __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset));
72 __ sub(r2, r2, Operand(kPointerSize)); 93
94 // Setup number of arguments for function call below
95 __ mov(r0, Operand(r3, LSR, kSmiTagSize));
73 96
74 // Copy arguments and receiver to the expression stack. 97 // Copy arguments and receiver to the expression stack.
98 // r0: number of arguments
99 // r2: address of last argument (caller sp)
100 // r1: constructor function
101 // r3: number of arguments (smi-tagged)
102 // sp[0]: receiver
103 // sp[1]: constructor function
104 // sp[2]: receiver
105 // sp[3]: constructor function
106 // sp[4]: number of arguments (smi-tagged)
75 Label loop, entry; 107 Label loop, entry;
76 __ mov(r1, Operand(r0));
77 __ b(&entry); 108 __ b(&entry);
78 __ bind(&loop); 109 __ bind(&loop);
79 __ ldr(r3, MemOperand(r2, r1, LSL, kPointerSizeLog2)); 110 __ ldr(ip, MemOperand(r2, r3, LSL, kPointerSizeLog2 - 1));
80 __ push(r3); 111 __ push(ip);
81 __ bind(&entry); 112 __ bind(&entry);
82 __ sub(r1, r1, Operand(1), SetCC); 113 __ sub(r3, r3, Operand(2), SetCC);
83 __ b(ge, &loop); 114 __ b(ge, &loop);
84 115
85 // Get the function to call from the stack.
86 __ ldr(r1, MemOperand(pp, JavaScriptFrameConstants::kFunctionOffset));
87
88 // Call the function. 116 // Call the function.
117 // r0: number of arguments
118 // r1: constructor function
89 Label return_site; 119 Label return_site;
90 __ RecordPosition(position); 120 __ RecordPosition(position);
91 ParameterCount actual(r0); 121 ParameterCount actual(r0);
92 __ InvokeFunction(r1, actual, CALL_FUNCTION); 122 __ InvokeFunction(r1, actual, CALL_FUNCTION);
93 __ bind(&return_site); 123 __ bind(&return_site);
94 124
95 // Restore context from the frame and discard the function. 125 // Pop the function from the stack.
126 // sp[0]: constructor function
127 // sp[2]: receiver
128 // sp[3]: constructor function
129 // sp[4]: number of arguments (smi-tagged)
130 __ pop();
131
132 // Restore context from the frame.
133 // r0: result
134 // sp[0]: receiver
135 // sp[1]: constructor function
136 // sp[2]: number of arguments (smi-tagged)
96 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 137 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
97 __ pop();
98 138
99 // If the result is an object (in the ECMA sense), we should get rid 139 // If the result is an object (in the ECMA sense), we should get rid
100 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 140 // of the receiver and use the result; see ECMA-262 section 13.2.2-7
101 // on page 74. 141 // on page 74.
102 Label use_receiver, exit; 142 Label use_receiver, exit;
103 143
104 // If the result is a smi, it is *not* an object in the ECMA sense. 144 // If the result is a smi, it is *not* an object in the ECMA sense.
145 // r0: result
146 // sp[0]: receiver (newly allocated object)
147 // sp[1]: constructor function
148 // sp[2]: number of arguments (smi-tagged)
105 __ tst(r0, Operand(kSmiTagMask)); 149 __ tst(r0, Operand(kSmiTagMask));
106 __ b(eq, &use_receiver); 150 __ b(eq, &use_receiver);
107 151
108 // If the type of the result (stored in its map) is less than 152 // If the type of the result (stored in its map) is less than
109 // FIRST_JS_OBJECT_TYPE, it is not an object in the ECMA sense. 153 // FIRST_JS_OBJECT_TYPE, it is not an object in the ECMA sense.
110 __ ldr(r2, FieldMemOperand(r0, HeapObject::kMapOffset)); 154 __ ldr(r3, FieldMemOperand(r0, HeapObject::kMapOffset));
111 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset)); 155 __ ldrb(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
112 __ cmp(r2, Operand(FIRST_JS_OBJECT_TYPE)); 156 __ cmp(r3, Operand(FIRST_JS_OBJECT_TYPE));
113 __ b(ge, &exit); 157 __ b(ge, &exit);
114 158
115 // Throw away the result of the constructor invocation and use the 159 // Throw away the result of the constructor invocation and use the
116 // on-stack receiver as the result. 160 // on-stack receiver as the result.
117 __ bind(&use_receiver); 161 __ bind(&use_receiver);
118 __ ldr(r0, MemOperand(sp)); 162 __ ldr(r0, MemOperand(sp));
119 163
120 // Remove receiver from the stack, remove caller arguments, and 164 // Remove receiver from the stack, remove caller arguments, and
121 // return. 165 // return.
122 __ bind(&exit); 166 __ bind(&exit);
123 __ ExitJSFrame(RETURN); 167 // r0: result
168 // sp[0]: receiver (newly allocated object)
169 // sp[1]: constructor function
170 // sp[2]: number of arguments (smi-tagged)
171 __ ldr(r1, MemOperand(sp, 2 * kPointerSize));
172 __ ExitInternalFrame();
173 __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1));
174 __ add(sp, sp, Operand(kPointerSize));
175 __ mov(pc, Operand(lr));
124 176
125 // Compute the offset from the beginning of the JSConstructCall 177 // Compute the offset from the beginning of the JSConstructCall
126 // builtin code object to the return address after the call. 178 // builtin code object to the return address after the call.
127 ASSERT(return_site.is_bound()); 179 ASSERT(return_site.is_bound());
128 construct_call_pc_offset_ = return_site.pos() + Code::kHeaderSize; 180 construct_call_pc_offset_ = return_site.pos() + Code::kHeaderSize;
129 } 181 }
130 182
131 183
132 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, 184 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm,
133 bool is_construct) { 185 bool is_construct) {
134 // Called from Generate_JS_Entry 186 // Called from Generate_JS_Entry
135 // r0: code entry 187 // r0: code entry
136 // r1: function 188 // r1: function
137 // r2: receiver 189 // r2: receiver
138 // r3: argc 190 // r3: argc
139 // r4: argv 191 // r4: argv
140 // r5-r7, cp may be clobbered 192 // r5-r7, cp may be clobbered
141 193
142 // Enter the JS frame 194 // Clear the context before we push it when entering the JS frame.
143 // compute parameter pointer before making changes 195 __ mov(cp, Operand(0));
144 __ mov(ip, Operand(sp)); // ip == caller_sp == new pp
145 196
146 __ mov(r5, Operand(0)); // spare slot to store caller code object during GC 197 // Enter an internal frame.
147 __ mov(r6, Operand(0)); // no context 198 __ EnterInternalFrame();
148 __ mov(r7, Operand(0)); // no incoming parameters
149 __ mov(r8, Operand(0)); // caller_pp == NULL for trampoline frames
150 ASSERT(cp.bit() == r8.bit()); // adjust the code otherwise
151
152 // push in reverse order:
153 // code (r5==0), context (r6==0), args_len (r7==0), caller_pp (r8==0),
154 // caller_fp, sp_on_exit (caller_sp), caller_pc
155 __ stm(db_w, sp, r5.bit() | r6.bit() | r7.bit() | r8.bit() |
156 fp.bit() | ip.bit() | lr.bit());
157 // Setup new frame pointer.
158 __ add(fp, sp, Operand(-StandardFrameConstants::kCodeOffset));
159 __ mov(pp, Operand(ip)); // setup new parameter pointer
160 199
161 // Setup the context from the function argument. 200 // Setup the context from the function argument.
162 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 201 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
163 202
164 // Push the function and the receiver onto the stack. 203 // Push the function and the receiver onto the stack.
165 __ push(r1); 204 __ push(r1);
166 __ push(r2); 205 __ push(r2);
167 206
168 // Copy arguments to the stack in a loop. 207 // Copy arguments to the stack in a loop.
169 // r1: function 208 // r1: function
(...skipping 14 matching lines...) Expand all
184 // Initialize all JavaScript callee-saved registers, since they will be seen 223 // Initialize all JavaScript callee-saved registers, since they will be seen
185 // by the garbage collector as part of handlers. 224 // by the garbage collector as part of handlers.
186 __ mov(r4, Operand(Factory::undefined_value())); 225 __ mov(r4, Operand(Factory::undefined_value()));
187 __ mov(r5, Operand(r4)); 226 __ mov(r5, Operand(r4));
188 __ mov(r6, Operand(r4)); 227 __ mov(r6, Operand(r4));
189 __ mov(r7, Operand(r4)); 228 __ mov(r7, Operand(r4));
190 if (kR9Available == 1) 229 if (kR9Available == 1)
191 __ mov(r9, Operand(r4)); 230 __ mov(r9, Operand(r4));
192 231
193 // Invoke the code and pass argc as r0. 232 // Invoke the code and pass argc as r0.
233 __ mov(r0, Operand(r3));
194 if (is_construct) { 234 if (is_construct) {
195 __ mov(r0, Operand(r3));
196 __ Call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)), 235 __ Call(Handle<Code>(Builtins::builtin(Builtins::JSConstructCall)),
197 code_target); 236 code_target);
198 } else { 237 } else {
199 ParameterCount actual(r3); 238 ParameterCount actual(r0);
200 __ InvokeFunction(r1, actual, CALL_FUNCTION); 239 __ InvokeFunction(r1, actual, CALL_FUNCTION);
201 } 240 }
202 241
203 // Exit the JS frame and remove the parameters (except function), and return. 242 // Exit the JS frame and remove the parameters (except function), and return.
204 // Respect ABI stack constraint. 243 // Respect ABI stack constraint.
205 __ add(sp, fp, Operand(StandardFrameConstants::kCallerFPOffset)); 244 __ ExitInternalFrame();
206 __ ldm(ia, sp, fp.bit() | sp.bit() | pc.bit()); 245 __ mov(pc, lr);
207 246
208 // r0: result 247 // r0: result
209 // pp: not restored, should not be used anymore
210 } 248 }
211 249
212 250
213 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { 251 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
214 Generate_JSEntryTrampolineHelper(masm, false); 252 Generate_JSEntryTrampolineHelper(masm, false);
215 } 253 }
216 254
217 255
218 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { 256 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
219 Generate_JSEntryTrampolineHelper(masm, true); 257 Generate_JSEntryTrampolineHelper(masm, true);
220 } 258 }
221 259
222 260
223 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { 261 void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
224 // TODO(1233523): Implement. Unused for now. 262 const int kIndexOffset = -5 * kPointerSize;
225 __ stop("Builtins::Generate_FunctionApply"); 263 const int kLimitOffset = -4 * kPointerSize;
264 const int kArgsOffset = 2 * kPointerSize;
265 const int kRecvOffset = 3 * kPointerSize;
266 const int kFunctionOffset = 4 * kPointerSize;
267
268 __ EnterInternalFrame();
269
270 __ ldr(r0, MemOperand(fp, kFunctionOffset)); // get the function
271 __ push(r0);
272 __ ldr(r0, MemOperand(fp, kArgsOffset)); // get the args array
273 __ push(r0);
274 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_JS);
275
276 // Eagerly check for stack-overflow before starting to push the arguments.
277 // r0: number of arguments
278 Label okay;
279 { Label L;
280 __ mov(r1, Operand(391864 << kSmiTagSize));
281 __ cmp(r0, r1);
282 __ b(cc, &L);
283 __ bind(&L);
284 }
285 ExternalReference stack_guard_limit_address =
286 ExternalReference::address_of_stack_guard_limit();
287 __ mov(r2, Operand(stack_guard_limit_address));
288 __ ldr(r2, MemOperand(r2));
289 __ sub(r2, sp, r2);
290 __ sub(r2, r2, Operand(3 * kPointerSize)); // limit, index, receiver
291
292 __ cmp(r2, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
293 __ b(hi, &okay);
294
295 // Out of stack space.
296 __ ldr(r1, MemOperand(fp, kFunctionOffset));
297 __ push(r1);
298 __ push(r0);
299 __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_JS);
300
301 // Push current limit and index.
302 __ bind(&okay);
303 __ push(r0); // limit
304 __ mov(r1, Operand(0)); // initial index
305 __ push(r1);
306
307 // Change context eagerly to get the right global object if necessary.
308 __ ldr(r0, MemOperand(fp, kFunctionOffset));
309 __ ldr(cp, FieldMemOperand(r0, JSFunction::kContextOffset));
310
311 // Compute the receiver.
312 Label call_to_object, use_global_receiver, push_receiver;
313 __ ldr(r0, MemOperand(fp, kRecvOffset));
314 __ tst(r0, Operand(kSmiTagMask));
315 __ b(eq, &call_to_object);
316 __ mov(r1, Operand(Factory::null_value()));
317 __ cmp(r0, r1);
318 __ b(eq, &use_global_receiver);
319 __ mov(r1, Operand(Factory::undefined_value()));
320 __ cmp(r0, r1);
321 __ b(eq, &use_global_receiver);
322
323 // Check if the receiver is already a JavaScript object.
324 // r0: receiver
325 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset));
326 __ ldrb(r1, FieldMemOperand(r1, Map::kInstanceTypeOffset));
327 __ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE));
328 __ b(lt, &call_to_object);
329 __ cmp(r1, Operand(LAST_JS_OBJECT_TYPE));
330 __ b(le, &push_receiver);
331
332 // Convert the receiver to a regular object.
333 // r0: receiver
334 __ bind(&call_to_object);
335 __ push(r0);
336 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS);
337 __ b(&push_receiver);
338
339 // Use the current global object as the receiver.
340 __ bind(&use_global_receiver);
341 __ ldr(r0, FieldMemOperand(cp, Context::kHeaderSize +
342 Context::GLOBAL_INDEX * kPointerSize));
343
344 // Push the receiver.
345 // r0: receiver
346 __ bind(&push_receiver);
347 __ push(r0);
348
349 // Copy all arguments from the array to the stack.
350 Label entry, loop;
351 __ ldr(r0, MemOperand(fp, kIndexOffset));
352 __ b(&entry);
353
354 // Load the current argument from the arguments array and push it to the
355 // stack.
356 // r0: current argument index
357 __ bind(&loop);
358 __ ldr(r1, MemOperand(fp, kArgsOffset));
359 __ push(r1);
360 __ push(r0);
361
362 // Call the runtime to access the property in the arguments array.
363 __ CallRuntime(Runtime::kGetProperty, 2);
364 __ push(r0);
365
366 // Use inline caching to access the arguments.
367 __ ldr(r0, MemOperand(fp, kIndexOffset));
368 __ add(r0, r0, Operand(1 << kSmiTagSize));
369 __ str(r0, MemOperand(fp, kIndexOffset));
370
371 // Test if the copy loop has finished copying all the elements from the
372 // arguments object.
373 __ bind(&entry);
374 __ ldr(r1, MemOperand(fp, kLimitOffset));
375 __ cmp(r0, r1);
376 __ b(ne, &loop);
377
378 // Invoke the function.
379 ParameterCount actual(r0);
380 __ mov(r0, Operand(r0, ASR, kSmiTagSize));
381 __ ldr(r1, MemOperand(fp, kFunctionOffset));
382 __ InvokeFunction(r1, actual, CALL_FUNCTION);
383
384 // Tear down the internal frame and remove function, receiver and args.
385 __ ExitInternalFrame();
386 __ add(sp, sp, Operand(3 * kPointerSize));
387 __ mov(pc, lr);
226 } 388 }
227 389
228 390
391 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) {
392 __ mov(r0, Operand(r0, LSL, kSmiTagSize));
393 __ mov(r4, Operand(ArgumentsAdaptorFrame::SENTINEL));
394 __ stm(db_w, sp, r0.bit() | r1.bit() | r4.bit() | fp.bit() | lr.bit());
395 __ add(fp, sp, Operand(3 * kPointerSize));
396 }
397
398
399 static void ExitArgumentsAdaptorFrame(MacroAssembler* masm) {
400 // ----------- S t a t e -------------
401 // -- r0 : result being passed through
402 // -----------------------------------
403 // Get the number of arguments passed (as a smi), tear down the frame and
404 // then tear down the parameters.
405 __ ldr(r1, MemOperand(fp, -3 * kPointerSize));
406 __ mov(sp, fp);
407 __ ldm(ia_w, sp, fp.bit() | lr.bit());
408 __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - kSmiTagSize));
409 __ add(sp, sp, Operand(kPointerSize)); // adjust for receiver
410 }
411
412
229 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { 413 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
230 // TODO(1233523): Implement. Unused for now. 414 // ----------- S t a t e -------------
231 __ stop("Builtins::Generate_ArgumentsAdaptorTrampoline"); 415 // -- r0 : actual number of arguments
232 416 // -- r1 : function (passed through to callee)
417 // -- r2 : expected number of arguments
418 // -- r3 : code entry to call
419 // -----------------------------------
420
421 Label entry, invoke, function_prototype_call;
422 __ bind(&entry);
423
424 Label enough, too_few;
425 __ cmp(r0, Operand(r2));
426 __ b(lt, &too_few);
427 __ cmp(r2, Operand(-1));
428 __ b(eq, &function_prototype_call);
429
430 { // Enough parameters: actual >= excpected
431 __ bind(&enough);
432 EnterArgumentsAdaptorFrame(masm);
433
434 // Calculate copy start address into r0 and copy end address into r2.
435 // r0: actual number of arguments as a smi
436 // r1: function
437 // r2: expected number of arguments
438 // r3: code entry to call
439 __ add(r0, fp, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
440 // adjust for return address and receiver
441 __ add(r0, r0, Operand(2 * kPointerSize));
442 __ sub(r2, r0, Operand(r2, LSL, kPointerSizeLog2));
443
444 // Copy the arguments (including the receiver) to the new stack frame.
445 // r0: copy start address
446 // r1: function
447 // r2: copy end address
448 // r3: code entry to call
449
450 Label copy;
451 __ bind(&copy);
452 __ ldr(ip, MemOperand(r0, 0));
453 __ push(ip);
454 __ cmp(r0, r2); // Compare before moving to next argument.
455 __ sub(r0, r0, Operand(kPointerSize));
456 __ b(ne, &copy);
457
458 __ b(&invoke);
459 }
460
461 { // Too few parameters: Actual < expected
462 __ bind(&too_few);
463 EnterArgumentsAdaptorFrame(masm);
464
465 // Calculate copy start address into r0 and copy end address is fp.
466 // r0: actual number of arguments as a smi
467 // r1: function
468 // r2: expected number of arguments
469 // r3: code entry to call
470 __ add(r0, fp, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize));
471
472 // Copy the arguments (including the receiver) to the new stack frame.
473 // r0: copy start address
474 // r1: function
475 // r2: expected number of arguments
476 // r3: code entry to call
477 Label copy;
478 __ bind(&copy);
479 // Adjust load for return address and receiver.
480 __ ldr(ip, MemOperand(r0, 2 * kPointerSize));
481 __ push(ip);
482 __ cmp(r0, fp); // Compare before moving to next argument.
483 __ sub(r0, r0, Operand(kPointerSize));
484 __ b(ne, &copy);
485
486 // Fill the remaining expected arguments with undefined.
487 // r1: function
488 // r2: expected number of arguments
489 // r3: code entry to call
490 __ mov(ip, Operand(Factory::undefined_value()));
491 __ sub(r2, fp, Operand(r2, LSL, kPointerSizeLog2));
492 __ sub(r2, r2, Operand(4 * kPointerSize)); // Adjust for frame.
493
494 Label fill;
495 __ bind(&fill);
496 __ push(ip);
497 __ cmp(sp, r2);
498 __ b(ne, &fill);
499 }
500
501 // Call the entry point.
233 Label return_site; 502 Label return_site;
503 __ bind(&invoke);
504
505 // TODO(iposva): remove compatibility layer using r0
506 __ ldr(r0, MemOperand(fp, -3 * kPointerSize));
507 __ mov(r0, Operand(r0, LSR, kSmiTagSize));
508
509 __ Call(r3);
234 __ bind(&return_site); 510 __ bind(&return_site);
235 511
512 ExitArgumentsAdaptorFrame(masm);
513 __ mov(pc, lr);
514
236 // Compute the offset from the beginning of the ArgumentsAdaptorTrampoline 515 // Compute the offset from the beginning of the ArgumentsAdaptorTrampoline
237 // builtin code object to the return address after the call. 516 // builtin code object to the return address after the call.
238 ASSERT(return_site.is_bound()); 517 ASSERT(return_site.is_bound());
239 arguments_adaptor_call_pc_offset_ = return_site.pos() + Code::kHeaderSize; 518 arguments_adaptor_call_pc_offset_ = return_site.pos() + Code::kHeaderSize;
519
520
521 // -------------------------------------------
522 // Function.prototype.call implementation.
523 // -------------------------------------------
524 // r0: actual number of argument
525 __ bind(&function_prototype_call);
526
527 // 1. Make sure we have at least one argument.
528 // r0: actual number of argument
529 { Label done;
530 __ tst(r0, Operand(r0));
531 __ b(ne, &done);
532 __ mov(r2, Operand(Factory::undefined_value()));
533 __ push(r2);
534 __ add(r0, r0, Operand(1));
535 __ bind(&done);
536 }
537
538 // 2. Get the function to call. Already in r1.
539 // r0: actual number of argument
540 { Label done, non_function, function;
541 __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2));
542 __ tst(r1, Operand(kSmiTagMask));
543 __ b(eq, &non_function);
544 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
545 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
546 __ cmp(r2, Operand(JS_FUNCTION_TYPE));
547 __ b(eq, &function);
548
549 // Non-function called: Clear the function to force exception.
550 __ bind(&non_function);
551 __ mov(r1, Operand(0));
552 __ b(&done);
553
554 // Change the context eagerly because it will be used below to get the
555 // right global object.
556 __ bind(&function);
557 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
558
559 __ bind(&done);
560 }
561
562 // 3. Make sure first argument is an object; convert if necessary.
563 // r0: actual number of arguments
564 // r1: function
565 { Label call_to_object, use_global_receiver, patch_receiver, done;
566 __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
567 __ ldr(r2, MemOperand(r2, -kPointerSize));
568
569 // r0: actual number of arguments
570 // r1: function
571 // r2: first argument
572 __ tst(r2, Operand(kSmiTagMask));
573 __ b(eq, &call_to_object);
574
575 __ mov(r3, Operand(Factory::null_value()));
576 __ cmp(r2, r3);
577 __ b(eq, &use_global_receiver);
578 __ mov(r3, Operand(Factory::undefined_value()));
579 __ cmp(r2, r3);
580 __ b(eq, &use_global_receiver);
581
582 __ ldr(r3, FieldMemOperand(r2, HeapObject::kMapOffset));
583 __ ldrb(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
584 __ cmp(r3, Operand(FIRST_JS_OBJECT_TYPE));
585 __ b(lt, &call_to_object);
586 __ cmp(r3, Operand(LAST_JS_OBJECT_TYPE));
587 __ b(le, &done);
588
589 __ bind(&call_to_object);
590 __ EnterInternalFrame();
591
592 // Store number of arguments and function across the call into the runtime.
593 __ mov(r0, Operand(r0, LSL, kSmiTagSize));
594 __ push(r0);
595 __ push(r1);
596
597 __ push(r2);
598 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS);
599 __ mov(r2, r0);
600
601 // Restore number of arguments and function.
602 __ pop(r1);
603 __ pop(r0);
604 __ mov(r0, Operand(r0, ASR, kSmiTagSize));
605
606 __ ExitInternalFrame();
607 __ b(&patch_receiver);
608
609 // Use the global object from the called function as the receiver.
610 __ bind(&use_global_receiver);
611 const int kGlobalIndex =
612 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
613 __ ldr(r2, FieldMemOperand(cp, kGlobalIndex));
614
615 __ bind(&patch_receiver);
616 __ add(r3, sp, Operand(r0, LSL, kPointerSizeLog2));
617 __ str(r2, MemOperand(r3, -kPointerSize));
618
619 __ bind(&done);
620 }
621
622 // 4. Shift stuff one slot down the stack
623 // r0: actual number of arguments (including call() receiver)
624 // r1: function
625 { Label loop;
626 // Calculate the copy start address (destination). Copy end address is sp.
627 __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
628
629 __ bind(&loop);
630 __ ldr(ip, MemOperand(r2, -kPointerSize));
631 __ str(ip, MemOperand(r2));
632 __ sub(r2, r2, Operand(kPointerSize));
633 __ cmp(r2, sp);
634 __ b(ne, &loop);
635 }
636
637 // 5. Adjust the actual number of arguments and remove the top element.
638 // r0: actual number of arguments (including call() receiver)
639 // r1: function
640 __ sub(r0, r0, Operand(1));
641 __ add(sp, sp, Operand(kPointerSize));
642
643 // 6. Get the code for the function or the non-function builtin.
644 // If number of expected arguments matches, then call. Otherwise restart
645 // the arguments adaptor stub.
646 // r0: actual number of arguments
647 // r1: function
648 { Label invoke;
649 __ tst(r1, r1);
650 __ b(ne, &invoke);
651 __ stop("Generate_ArgumentsAdaptorTrampoline - non-function call");
652 __ mov(r2, Operand(0)); // expected arguments is 0 for CALL_NON_FUNCTION
653 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
654 __ b(&enough);
655
656 __ bind(&invoke);
657 __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
658 __ ldr(r2,
659 FieldMemOperand(r3,
660 SharedFunctionInfo::kFormalParameterCountOffset));
661 __ ldr(r3,
662 MemOperand(r3, SharedFunctionInfo::kCodeOffset - kHeapObjectTag));
663 __ add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
664 __ cmp(r2, r0); // Check formal and actual parameter counts.
665 __ b(ne, &entry);
666
667 // 7. Jump to the code in r3 without checking arguments.
668 ParameterCount expected(0);
669 __ InvokeCode(r3, expected, expected, JUMP_FUNCTION);
670 }
240 } 671 }
241 672
242 673
243 static void Generate_DebugBreakCallHelper(MacroAssembler* masm, 674 static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
244 RegList pointer_regs) { 675 RegList pointer_regs) {
245 // Save the content of all general purpose registers in memory. This copy in 676 // Save the content of all general purpose registers in memory. This copy in
246 // memory is later pushed onto the JS expression stack for the fake JS frame 677 // memory is later pushed onto the JS expression stack for the fake JS frame
247 // generated and also to the C frame generated on top of that. In the JS 678 // generated and also to the C frame generated on top of that. In the JS
248 // frame ONLY the registers containing pointers will be pushed on the 679 // frame ONLY the registers containing pointers will be pushed on the
249 // expression stack. This causes the GC to update these pointers so that 680 // expression stack. This causes the GC to update these pointers so that
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
399 } 830 }
400 831
401 void Builtins::Generate_StubNoRegisters_DebugBreak(MacroAssembler* masm) { 832 void Builtins::Generate_StubNoRegisters_DebugBreak(MacroAssembler* masm) {
402 // Generate nothing as CodeStub CallFunction is not used on ARM. 833 // Generate nothing as CodeStub CallFunction is not used on ARM.
403 } 834 }
404 835
405 836
406 #undef __ 837 #undef __
407 838
408 } } // namespace v8::internal 839 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/builtins.cc ('k') | src/builtins-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698