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

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

Issue 2850: Generalize the Function.prototype.call hooks in the... (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.h ('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 240 matching lines...) Expand 10 before | Expand all | Expand 10 after
251 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { 251 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) {
252 Generate_JSEntryTrampolineHelper(masm, false); 252 Generate_JSEntryTrampolineHelper(masm, false);
253 } 253 }
254 254
255 255
256 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { 256 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
257 Generate_JSEntryTrampolineHelper(masm, true); 257 Generate_JSEntryTrampolineHelper(masm, true);
258 } 258 }
259 259
260 260
261 void Builtins::Generate_FunctionCall(MacroAssembler* masm) {
262 // 1. Make sure we have at least one argument.
263 // r0: actual number of argument
264 { Label done;
265 __ tst(r0, Operand(r0));
266 __ b(ne, &done);
267 __ mov(r2, Operand(Factory::undefined_value()));
268 __ push(r2);
269 __ add(r0, r0, Operand(1));
270 __ bind(&done);
271 }
272
273 // 2. Get the function to call. Already in r1.
274 // r0: actual number of argument
275 { Label done, non_function, function;
276 __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2));
277 __ tst(r1, Operand(kSmiTagMask));
278 __ b(eq, &non_function);
279 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
280 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
281 __ cmp(r2, Operand(JS_FUNCTION_TYPE));
282 __ b(eq, &function);
283
284 // Non-function called: Clear the function to force exception.
285 __ bind(&non_function);
286 __ mov(r1, Operand(0));
287 __ b(&done);
288
289 // Change the context eagerly because it will be used below to get the
290 // right global object.
291 __ bind(&function);
292 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
293
294 __ bind(&done);
295 }
296
297 // 3. Make sure first argument is an object; convert if necessary.
298 // r0: actual number of arguments
299 // r1: function
300 { Label call_to_object, use_global_receiver, patch_receiver, done;
301 __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
302 __ ldr(r2, MemOperand(r2, -kPointerSize));
303
304 // r0: actual number of arguments
305 // r1: function
306 // r2: first argument
307 __ tst(r2, Operand(kSmiTagMask));
308 __ b(eq, &call_to_object);
309
310 __ mov(r3, Operand(Factory::null_value()));
311 __ cmp(r2, r3);
312 __ b(eq, &use_global_receiver);
313 __ mov(r3, Operand(Factory::undefined_value()));
314 __ cmp(r2, r3);
315 __ b(eq, &use_global_receiver);
316
317 __ ldr(r3, FieldMemOperand(r2, HeapObject::kMapOffset));
318 __ ldrb(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
319 __ cmp(r3, Operand(FIRST_JS_OBJECT_TYPE));
320 __ b(lt, &call_to_object);
321 __ cmp(r3, Operand(LAST_JS_OBJECT_TYPE));
322 __ b(le, &done);
323
324 __ bind(&call_to_object);
325 __ EnterInternalFrame();
326
327 // Store number of arguments and function across the call into the runtime.
328 __ mov(r0, Operand(r0, LSL, kSmiTagSize));
329 __ push(r0);
330 __ push(r1);
331
332 __ push(r2);
333 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS);
334 __ mov(r2, r0);
335
336 // Restore number of arguments and function.
337 __ pop(r1);
338 __ pop(r0);
339 __ mov(r0, Operand(r0, ASR, kSmiTagSize));
340
341 __ ExitInternalFrame();
342 __ b(&patch_receiver);
343
344 // Use the global object from the called function as the receiver.
345 __ bind(&use_global_receiver);
346 const int kGlobalIndex =
347 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
348 __ ldr(r2, FieldMemOperand(cp, kGlobalIndex));
349
350 __ bind(&patch_receiver);
351 __ add(r3, sp, Operand(r0, LSL, kPointerSizeLog2));
352 __ str(r2, MemOperand(r3, -kPointerSize));
353
354 __ bind(&done);
355 }
356
357 // 4. Shift stuff one slot down the stack
358 // r0: actual number of arguments (including call() receiver)
359 // r1: function
360 { Label loop;
361 // Calculate the copy start address (destination). Copy end address is sp.
362 __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
363
364 __ bind(&loop);
365 __ ldr(ip, MemOperand(r2, -kPointerSize));
366 __ str(ip, MemOperand(r2));
367 __ sub(r2, r2, Operand(kPointerSize));
368 __ cmp(r2, sp);
369 __ b(ne, &loop);
370 }
371
372 // 5. Adjust the actual number of arguments and remove the top element.
373 // r0: actual number of arguments (including call() receiver)
374 // r1: function
375 __ sub(r0, r0, Operand(1));
376 __ add(sp, sp, Operand(kPointerSize));
377
378 // 6. Get the code for the function or the non-function builtin.
379 // If number of expected arguments matches, then call. Otherwise restart
380 // the arguments adaptor stub.
381 // r0: actual number of arguments
382 // r1: function
383 { Label invoke;
384 __ tst(r1, r1);
385 __ b(ne, &invoke);
386 // __ stop("Generate_ArgumentsAdaptorTrampoline - non-function call");
387 __ mov(r2, Operand(0)); // expected arguments is 0 for CALL_NON_FUNCTION
388 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
389 __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)), code_target);
390
391 __ bind(&invoke);
392 __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
393 __ ldr(r2,
394 FieldMemOperand(r3,
395 SharedFunctionInfo::kFormalParameterCountOffset));
396 __ ldr(r3,
397 MemOperand(r3, SharedFunctionInfo::kCodeOffset - kHeapObjectTag));
398 __ add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
399 __ cmp(r2, r0); // Check formal and actual parameter counts.
400 __ Jump(Handle<Code>(builtin(ArgumentsAdaptorTrampoline)), code_target, ne);
401
402 // 7. Jump to the code in r3 without checking arguments.
403 ParameterCount expected(0);
404 __ InvokeCode(r3, expected, expected, JUMP_FUNCTION);
405 }
406 }
407
408
261 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { 409 void Builtins::Generate_FunctionApply(MacroAssembler* masm) {
262 const int kIndexOffset = -5 * kPointerSize; 410 const int kIndexOffset = -5 * kPointerSize;
263 const int kLimitOffset = -4 * kPointerSize; 411 const int kLimitOffset = -4 * kPointerSize;
264 const int kArgsOffset = 2 * kPointerSize; 412 const int kArgsOffset = 2 * kPointerSize;
265 const int kRecvOffset = 3 * kPointerSize; 413 const int kRecvOffset = 3 * kPointerSize;
266 const int kFunctionOffset = 4 * kPointerSize; 414 const int kFunctionOffset = 4 * kPointerSize;
267 415
268 __ EnterInternalFrame(); 416 __ EnterInternalFrame();
269 417
270 __ ldr(r0, MemOperand(fp, kFunctionOffset)); // get the function 418 __ ldr(r0, MemOperand(fp, kFunctionOffset)); // get the function
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
411 559
412 560
413 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) { 561 void Builtins::Generate_ArgumentsAdaptorTrampoline(MacroAssembler* masm) {
414 // ----------- S t a t e ------------- 562 // ----------- S t a t e -------------
415 // -- r0 : actual number of arguments 563 // -- r0 : actual number of arguments
416 // -- r1 : function (passed through to callee) 564 // -- r1 : function (passed through to callee)
417 // -- r2 : expected number of arguments 565 // -- r2 : expected number of arguments
418 // -- r3 : code entry to call 566 // -- r3 : code entry to call
419 // ----------------------------------- 567 // -----------------------------------
420 568
421 Label entry, invoke, function_prototype_call; 569 Label invoke, dont_adapt_arguments;
422 __ bind(&entry);
423 570
424 Label enough, too_few; 571 Label enough, too_few;
425 __ cmp(r0, Operand(r2)); 572 __ cmp(r0, Operand(r2));
426 __ b(lt, &too_few); 573 __ b(lt, &too_few);
427 __ cmp(r2, Operand(-1)); 574 __ cmp(r2, Operand(SharedFunctionInfo::kDontAdaptArgumentsSentinel));
428 __ b(eq, &function_prototype_call); 575 __ b(eq, &dont_adapt_arguments);
429 576
430 { // Enough parameters: actual >= excpected 577 { // Enough parameters: actual >= excpected
431 __ bind(&enough); 578 __ bind(&enough);
432 EnterArgumentsAdaptorFrame(masm); 579 EnterArgumentsAdaptorFrame(masm);
433 580
434 // Calculate copy start address into r0 and copy end address into r2. 581 // Calculate copy start address into r0 and copy end address into r2.
435 // r0: actual number of arguments as a smi 582 // r0: actual number of arguments as a smi
436 // r1: function 583 // r1: function
437 // r2: expected number of arguments 584 // r2: expected number of arguments
438 // r3: code entry to call 585 // r3: code entry to call
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
508 ExitArgumentsAdaptorFrame(masm); 655 ExitArgumentsAdaptorFrame(masm);
509 __ mov(pc, lr); 656 __ mov(pc, lr);
510 657
511 // Compute the offset from the beginning of the ArgumentsAdaptorTrampoline 658 // Compute the offset from the beginning of the ArgumentsAdaptorTrampoline
512 // builtin code object to the return address after the call. 659 // builtin code object to the return address after the call.
513 ASSERT(return_site.is_bound()); 660 ASSERT(return_site.is_bound());
514 arguments_adaptor_call_pc_offset_ = return_site.pos() + Code::kHeaderSize; 661 arguments_adaptor_call_pc_offset_ = return_site.pos() + Code::kHeaderSize;
515 662
516 663
517 // ------------------------------------------- 664 // -------------------------------------------
518 // Function.prototype.call implementation. 665 // Dont adapt arguments.
519 // ------------------------------------------- 666 // -------------------------------------------
520 // r0: actual number of argument 667 __ bind(&dont_adapt_arguments);
521 __ bind(&function_prototype_call); 668 __ mov(pc, r3);
522
523 // 1. Make sure we have at least one argument.
524 // r0: actual number of argument
525 { Label done;
526 __ tst(r0, Operand(r0));
527 __ b(ne, &done);
528 __ mov(r2, Operand(Factory::undefined_value()));
529 __ push(r2);
530 __ add(r0, r0, Operand(1));
531 __ bind(&done);
532 }
533
534 // 2. Get the function to call. Already in r1.
535 // r0: actual number of argument
536 { Label done, non_function, function;
537 __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2));
538 __ tst(r1, Operand(kSmiTagMask));
539 __ b(eq, &non_function);
540 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
541 __ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
542 __ cmp(r2, Operand(JS_FUNCTION_TYPE));
543 __ b(eq, &function);
544
545 // Non-function called: Clear the function to force exception.
546 __ bind(&non_function);
547 __ mov(r1, Operand(0));
548 __ b(&done);
549
550 // Change the context eagerly because it will be used below to get the
551 // right global object.
552 __ bind(&function);
553 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
554
555 __ bind(&done);
556 }
557
558 // 3. Make sure first argument is an object; convert if necessary.
559 // r0: actual number of arguments
560 // r1: function
561 { Label call_to_object, use_global_receiver, patch_receiver, done;
562 __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
563 __ ldr(r2, MemOperand(r2, -kPointerSize));
564
565 // r0: actual number of arguments
566 // r1: function
567 // r2: first argument
568 __ tst(r2, Operand(kSmiTagMask));
569 __ b(eq, &call_to_object);
570
571 __ mov(r3, Operand(Factory::null_value()));
572 __ cmp(r2, r3);
573 __ b(eq, &use_global_receiver);
574 __ mov(r3, Operand(Factory::undefined_value()));
575 __ cmp(r2, r3);
576 __ b(eq, &use_global_receiver);
577
578 __ ldr(r3, FieldMemOperand(r2, HeapObject::kMapOffset));
579 __ ldrb(r3, FieldMemOperand(r3, Map::kInstanceTypeOffset));
580 __ cmp(r3, Operand(FIRST_JS_OBJECT_TYPE));
581 __ b(lt, &call_to_object);
582 __ cmp(r3, Operand(LAST_JS_OBJECT_TYPE));
583 __ b(le, &done);
584
585 __ bind(&call_to_object);
586 __ EnterInternalFrame();
587
588 // Store number of arguments and function across the call into the runtime.
589 __ mov(r0, Operand(r0, LSL, kSmiTagSize));
590 __ push(r0);
591 __ push(r1);
592
593 __ push(r2);
594 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_JS);
595 __ mov(r2, r0);
596
597 // Restore number of arguments and function.
598 __ pop(r1);
599 __ pop(r0);
600 __ mov(r0, Operand(r0, ASR, kSmiTagSize));
601
602 __ ExitInternalFrame();
603 __ b(&patch_receiver);
604
605 // Use the global object from the called function as the receiver.
606 __ bind(&use_global_receiver);
607 const int kGlobalIndex =
608 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
609 __ ldr(r2, FieldMemOperand(cp, kGlobalIndex));
610
611 __ bind(&patch_receiver);
612 __ add(r3, sp, Operand(r0, LSL, kPointerSizeLog2));
613 __ str(r2, MemOperand(r3, -kPointerSize));
614
615 __ bind(&done);
616 }
617
618 // 4. Shift stuff one slot down the stack
619 // r0: actual number of arguments (including call() receiver)
620 // r1: function
621 { Label loop;
622 // Calculate the copy start address (destination). Copy end address is sp.
623 __ add(r2, sp, Operand(r0, LSL, kPointerSizeLog2));
624
625 __ bind(&loop);
626 __ ldr(ip, MemOperand(r2, -kPointerSize));
627 __ str(ip, MemOperand(r2));
628 __ sub(r2, r2, Operand(kPointerSize));
629 __ cmp(r2, sp);
630 __ b(ne, &loop);
631 }
632
633 // 5. Adjust the actual number of arguments and remove the top element.
634 // r0: actual number of arguments (including call() receiver)
635 // r1: function
636 __ sub(r0, r0, Operand(1));
637 __ add(sp, sp, Operand(kPointerSize));
638
639 // 6. Get the code for the function or the non-function builtin.
640 // If number of expected arguments matches, then call. Otherwise restart
641 // the arguments adaptor stub.
642 // r0: actual number of arguments
643 // r1: function
644 { Label invoke;
645 __ tst(r1, r1);
646 __ b(ne, &invoke);
647 // __ stop("Generate_ArgumentsAdaptorTrampoline - non-function call");
648 __ mov(r2, Operand(0)); // expected arguments is 0 for CALL_NON_FUNCTION
649 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION);
650 __ b(&enough);
651
652 __ bind(&invoke);
653 __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
654 __ ldr(r2,
655 FieldMemOperand(r3,
656 SharedFunctionInfo::kFormalParameterCountOffset));
657 __ ldr(r3,
658 MemOperand(r3, SharedFunctionInfo::kCodeOffset - kHeapObjectTag));
659 __ add(r3, r3, Operand(Code::kHeaderSize - kHeapObjectTag));
660 __ cmp(r2, r0); // Check formal and actual parameter counts.
661 __ b(ne, &entry);
662
663 // 7. Jump to the code in r3 without checking arguments.
664 ParameterCount expected(0);
665 __ InvokeCode(r3, expected, expected, JUMP_FUNCTION);
666 }
667 } 669 }
668 670
669 671
670 static void Generate_DebugBreakCallHelper(MacroAssembler* masm, 672 static void Generate_DebugBreakCallHelper(MacroAssembler* masm,
671 RegList pointer_regs) { 673 RegList pointer_regs) {
672 // Save the content of all general purpose registers in memory. This copy in 674 // Save the content of all general purpose registers in memory. This copy in
673 // memory is later pushed onto the JS expression stack for the fake JS frame 675 // memory is later pushed onto the JS expression stack for the fake JS frame
674 // generated and also to the C frame generated on top of that. In the JS 676 // generated and also to the C frame generated on top of that. In the JS
675 // frame ONLY the registers containing pointers will be pushed on the 677 // frame ONLY the registers containing pointers will be pushed on the
676 // expression stack. This causes the GC to update these pointers so that 678 // expression stack. This causes the GC to update these pointers so that
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
826 } 828 }
827 829
828 void Builtins::Generate_StubNoRegisters_DebugBreak(MacroAssembler* masm) { 830 void Builtins::Generate_StubNoRegisters_DebugBreak(MacroAssembler* masm) {
829 // Generate nothing as CodeStub CallFunction is not used on ARM. 831 // Generate nothing as CodeStub CallFunction is not used on ARM.
830 } 832 }
831 833
832 834
833 #undef __ 835 #undef __
834 836
835 } } // namespace v8::internal 837 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/builtins.h ('k') | src/builtins-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698