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

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

Issue 6087011: Draft of ES5 fix to Function.prototype.call and apply (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 11 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/ia32/builtins-ia32.cc ('k') | test/mjsunit/apply.js » ('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 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 592 matching lines...) Expand 10 before | Expand all | Expand 10 after
603 603
604 // 2. Get the function to call (passed as receiver) from the stack, check 604 // 2. Get the function to call (passed as receiver) from the stack, check
605 // if it is a function. 605 // if it is a function.
606 Label non_function; 606 Label non_function;
607 // The function to call is at position n+1 on the stack. 607 // The function to call is at position n+1 on the stack.
608 __ movq(rdi, Operand(rsp, rax, times_pointer_size, 1 * kPointerSize)); 608 __ movq(rdi, Operand(rsp, rax, times_pointer_size, 1 * kPointerSize));
609 __ JumpIfSmi(rdi, &non_function); 609 __ JumpIfSmi(rdi, &non_function);
610 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx); 610 __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rcx);
611 __ j(not_equal, &non_function); 611 __ j(not_equal, &non_function);
612 612
613 // 3a. Patch the first argument if necessary when calling a function. 613 // Change context eagerly in case we need the global receiver.
614 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
615
614 Label shift_arguments; 616 Label shift_arguments;
615 { Label convert_to_object, use_global_receiver, patch_receiver; 617 __ jmp(&shift_arguments);
616 // Change context eagerly in case we need the global receiver.
617 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
618 618
619 __ movq(rbx, Operand(rsp, rax, times_pointer_size, 0)); 619 // 3. Patch the first argument when calling a non-function. The
620 __ JumpIfSmi(rbx, &convert_to_object); 620 // CALL_NON_FUNCTION builtin expects the non-function callee as
621 621 // receiver, so overwrite the first argument which will ultimately
622 __ CompareRoot(rbx, Heap::kNullValueRootIndex); 622 // become the receiver.
623 __ j(equal, &use_global_receiver);
624 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
625 __ j(equal, &use_global_receiver);
626
627 __ CmpObjectType(rbx, FIRST_JS_OBJECT_TYPE, rcx);
628 __ j(below, &convert_to_object);
629 __ CmpInstanceType(rcx, LAST_JS_OBJECT_TYPE);
630 __ j(below_equal, &shift_arguments);
631
632 __ bind(&convert_to_object);
633 __ EnterInternalFrame(); // In order to preserve argument count.
634 __ Integer32ToSmi(rax, rax);
635 __ push(rax);
636
637 __ push(rbx);
638 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
639 __ movq(rbx, rax);
640
641 __ pop(rax);
642 __ SmiToInteger32(rax, rax);
643 __ LeaveInternalFrame();
644 // Restore the function to rdi.
645 __ movq(rdi, Operand(rsp, rax, times_pointer_size, 1 * kPointerSize));
646 __ jmp(&patch_receiver);
647
648 // Use the global receiver object from the called function as the
649 // receiver.
650 __ bind(&use_global_receiver);
651 const int kGlobalIndex =
652 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
653 __ movq(rbx, FieldOperand(rsi, kGlobalIndex));
654 __ movq(rbx, FieldOperand(rbx, GlobalObject::kGlobalContextOffset));
655 __ movq(rbx, FieldOperand(rbx, kGlobalIndex));
656 __ movq(rbx, FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
657
658 __ bind(&patch_receiver);
659 __ movq(Operand(rsp, rax, times_pointer_size, 0), rbx);
660
661 __ jmp(&shift_arguments);
662 }
663
664
665 // 3b. Patch the first argument when calling a non-function. The
666 // CALL_NON_FUNCTION builtin expects the non-function callee as
667 // receiver, so overwrite the first argument which will ultimately
668 // become the receiver.
669 __ bind(&non_function); 623 __ bind(&non_function);
670 __ movq(Operand(rsp, rax, times_pointer_size, 0), rdi); 624 __ movq(Operand(rsp, rax, times_pointer_size, 0), rdi);
671 __ Set(rdi, 0); 625 __ Set(rdi, 0);
672 626
673 // 4. Shift arguments and return address one slot down on the stack 627 // 4. Shift arguments and return address one slot down on the stack
674 // (overwriting the original receiver). Adjust argument count to make 628 // (overwriting the original receiver). Adjust argument count to make
675 // the original first argument the new receiver. 629 // the original first argument the new receiver.
676 __ bind(&shift_arguments); 630 __ bind(&shift_arguments);
677 { Label loop; 631 { Label loop;
678 __ movq(rcx, rax); 632 __ movq(rcx, rax);
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
762 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize; 716 StandardFrameConstants::kExpressionsOffset - 1 * kPointerSize;
763 const int kIndexOffset = kLimitOffset - 1 * kPointerSize; 717 const int kIndexOffset = kLimitOffset - 1 * kPointerSize;
764 __ push(rax); // limit 718 __ push(rax); // limit
765 __ push(Immediate(0)); // index 719 __ push(Immediate(0)); // index
766 720
767 // Change context eagerly to get the right global object if 721 // Change context eagerly to get the right global object if
768 // necessary. 722 // necessary.
769 __ movq(rdi, Operand(rbp, kFunctionOffset)); 723 __ movq(rdi, Operand(rbp, kFunctionOffset));
770 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); 724 __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
771 725
772 // Compute the receiver. 726 // Push the receiver.
773 Label call_to_object, use_global_receiver, push_receiver;
774 __ movq(rbx, Operand(rbp, kReceiverOffset)); 727 __ movq(rbx, Operand(rbp, kReceiverOffset));
775 __ JumpIfSmi(rbx, &call_to_object);
776 __ CompareRoot(rbx, Heap::kNullValueRootIndex);
777 __ j(equal, &use_global_receiver);
778 __ CompareRoot(rbx, Heap::kUndefinedValueRootIndex);
779 __ j(equal, &use_global_receiver);
780
781 // If given receiver is already a JavaScript object then there's no
782 // reason for converting it.
783 __ CmpObjectType(rbx, FIRST_JS_OBJECT_TYPE, rcx);
784 __ j(below, &call_to_object);
785 __ CmpInstanceType(rcx, LAST_JS_OBJECT_TYPE);
786 __ j(below_equal, &push_receiver);
787
788 // Convert the receiver to an object.
789 __ bind(&call_to_object);
790 __ push(rbx);
791 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION);
792 __ movq(rbx, rax);
793 __ jmp(&push_receiver);
794
795 // Use the current global receiver object as the receiver.
796 __ bind(&use_global_receiver);
797 const int kGlobalOffset =
798 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize;
799 __ movq(rbx, FieldOperand(rsi, kGlobalOffset));
800 __ movq(rbx, FieldOperand(rbx, GlobalObject::kGlobalContextOffset));
801 __ movq(rbx, FieldOperand(rbx, kGlobalOffset));
802 __ movq(rbx, FieldOperand(rbx, GlobalObject::kGlobalReceiverOffset));
803
804 // Push the receiver.
805 __ bind(&push_receiver);
806 __ push(rbx); 728 __ push(rbx);
807 729
808 // Copy all arguments from the array to the stack. 730 // Copy all arguments from the array to the stack.
809 Label entry, loop; 731 Label entry, loop;
810 __ movq(rax, Operand(rbp, kIndexOffset)); 732 __ movq(rax, Operand(rbp, kIndexOffset));
811 __ jmp(&entry); 733 __ jmp(&entry);
812 __ bind(&loop); 734 __ bind(&loop);
813 __ movq(rdx, Operand(rbp, kArgumentsOffset)); // load arguments 735 __ movq(rdx, Operand(rbp, kArgumentsOffset)); // load arguments
814 736
815 // Use inline caching to speed up access to arguments. 737 // Use inline caching to speed up access to arguments.
(...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after
1382 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) { 1304 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) {
1383 __ int3(); 1305 __ int3();
1384 } 1306 }
1385 1307
1386 1308
1387 #undef __ 1309 #undef __
1388 1310
1389 } } // namespace v8::internal 1311 } } // namespace v8::internal
1390 1312
1391 #endif // V8_TARGET_ARCH_X64 1313 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/ia32/builtins-ia32.cc ('k') | test/mjsunit/apply.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698