OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_X64 | 5 #if V8_TARGET_ARCH_X64 |
6 | 6 |
7 #include "src/bootstrapper.h" | 7 #include "src/bootstrapper.h" |
8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/ic/handler-compiler.h" | 10 #include "src/ic/handler-compiler.h" |
(...skipping 578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
589 // by calling the runtime system. | 589 // by calling the runtime system. |
590 __ bind(&slow); | 590 __ bind(&slow); |
591 __ PopReturnAddressTo(rbx); | 591 __ PopReturnAddressTo(rbx); |
592 __ Push(rdx); | 592 __ Push(rdx); |
593 __ PushReturnAddressFrom(rbx); | 593 __ PushReturnAddressFrom(rbx); |
594 __ TailCallRuntime(Runtime::kArguments, 1, 1); | 594 __ TailCallRuntime(Runtime::kArguments, 1, 1); |
595 } | 595 } |
596 | 596 |
597 | 597 |
598 void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { | 598 void ArgumentsAccessStub::GenerateNewSloppyFast(MacroAssembler* masm) { |
599 // Stack layout: | 599 // rcx : number of parameters (tagged) |
600 // rsp[0] : return address | 600 // rdx : parameters pointer |
601 // rsp[8] : number of parameters (tagged) | 601 // rdi : function |
602 // rsp[16] : receiver displacement | 602 // rsp[0] : return address |
603 // rsp[24] : function | |
604 // Registers used over the whole function: | 603 // Registers used over the whole function: |
605 // rbx: the mapped parameter count (untagged) | 604 // rbx: the mapped parameter count (untagged) |
606 // rax: the allocated object (tagged). | 605 // rax: the allocated object (tagged). |
607 Factory* factory = isolate()->factory(); | 606 Factory* factory = isolate()->factory(); |
608 | 607 |
609 StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER); | 608 DCHECK(rdi.is(ArgumentsAccessNewDescriptor::function())); |
610 __ SmiToInteger64(rbx, args.GetArgumentOperand(2)); | 609 DCHECK(rcx.is(ArgumentsAccessNewDescriptor::parameter_count())); |
| 610 DCHECK(rdx.is(ArgumentsAccessNewDescriptor::parameter_pointer())); |
| 611 |
| 612 __ SmiToInteger64(rbx, rcx); |
611 // rbx = parameter count (untagged) | 613 // rbx = parameter count (untagged) |
612 | 614 |
613 // Check if the calling frame is an arguments adaptor frame. | 615 // Check if the calling frame is an arguments adaptor frame. |
614 Label runtime; | 616 Label adaptor_frame, try_allocate, runtime; |
615 Label adaptor_frame, try_allocate; | 617 __ movp(rax, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
616 __ movp(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 618 __ movp(r8, Operand(rax, StandardFrameConstants::kContextOffset)); |
617 __ movp(rcx, Operand(rdx, StandardFrameConstants::kContextOffset)); | 619 __ Cmp(r8, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
618 __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | |
619 __ j(equal, &adaptor_frame); | 620 __ j(equal, &adaptor_frame); |
620 | 621 |
621 // No adaptor, parameter count = argument count. | 622 // No adaptor, parameter count = argument count. |
622 __ movp(rcx, rbx); | 623 __ movp(r11, rbx); |
623 __ jmp(&try_allocate, Label::kNear); | 624 __ jmp(&try_allocate, Label::kNear); |
624 | 625 |
625 // We have an adaptor frame. Patch the parameters pointer. | 626 // We have an adaptor frame. Patch the parameters pointer. |
626 __ bind(&adaptor_frame); | 627 __ bind(&adaptor_frame); |
627 __ SmiToInteger64(rcx, | 628 __ SmiToInteger64( |
628 Operand(rdx, | 629 r11, Operand(rax, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
629 ArgumentsAdaptorFrameConstants::kLengthOffset)); | 630 __ leap(rdx, Operand(rax, r11, times_pointer_size, |
630 __ leap(rdx, Operand(rdx, rcx, times_pointer_size, | 631 StandardFrameConstants::kCallerSPOffset)); |
631 StandardFrameConstants::kCallerSPOffset)); | |
632 __ movp(args.GetArgumentOperand(1), rdx); | |
633 | 632 |
634 // rbx = parameter count (untagged) | 633 // rbx = parameter count (untagged) |
635 // rcx = argument count (untagged) | 634 // r11 = argument count (untagged) |
636 // Compute the mapped parameter count = min(rbx, rcx) in rbx. | 635 // Compute the mapped parameter count = min(rbx, r11) in rbx. |
637 __ cmpp(rbx, rcx); | 636 __ cmpp(rbx, r11); |
638 __ j(less_equal, &try_allocate, Label::kNear); | 637 __ j(less_equal, &try_allocate, Label::kNear); |
639 __ movp(rbx, rcx); | 638 __ movp(rbx, r11); |
640 | 639 |
641 __ bind(&try_allocate); | 640 __ bind(&try_allocate); |
642 | 641 |
643 // Compute the sizes of backing store, parameter map, and arguments object. | 642 // Compute the sizes of backing store, parameter map, and arguments object. |
644 // 1. Parameter map, has 2 extra words containing context and backing store. | 643 // 1. Parameter map, has 2 extra words containing context and backing store. |
645 const int kParameterMapHeaderSize = | 644 const int kParameterMapHeaderSize = |
646 FixedArray::kHeaderSize + 2 * kPointerSize; | 645 FixedArray::kHeaderSize + 2 * kPointerSize; |
647 Label no_parameter_map; | 646 Label no_parameter_map; |
648 __ xorp(r8, r8); | 647 __ xorp(r8, r8); |
649 __ testp(rbx, rbx); | 648 __ testp(rbx, rbx); |
650 __ j(zero, &no_parameter_map, Label::kNear); | 649 __ j(zero, &no_parameter_map, Label::kNear); |
651 __ leap(r8, Operand(rbx, times_pointer_size, kParameterMapHeaderSize)); | 650 __ leap(r8, Operand(rbx, times_pointer_size, kParameterMapHeaderSize)); |
652 __ bind(&no_parameter_map); | 651 __ bind(&no_parameter_map); |
653 | 652 |
654 // 2. Backing store. | 653 // 2. Backing store. |
655 __ leap(r8, Operand(r8, rcx, times_pointer_size, FixedArray::kHeaderSize)); | 654 __ leap(r8, Operand(r8, r11, times_pointer_size, FixedArray::kHeaderSize)); |
656 | 655 |
657 // 3. Arguments object. | 656 // 3. Arguments object. |
658 __ addp(r8, Immediate(Heap::kSloppyArgumentsObjectSize)); | 657 __ addp(r8, Immediate(Heap::kSloppyArgumentsObjectSize)); |
659 | 658 |
660 // Do the allocation of all three objects in one go. | 659 // Do the allocation of all three objects in one go. |
661 __ Allocate(r8, rax, rdx, rdi, &runtime, TAG_OBJECT); | 660 __ Allocate(r8, rax, r9, no_reg, &runtime, TAG_OBJECT); |
662 | 661 |
663 // rax = address of new object(s) (tagged) | 662 // rax = address of new object(s) (tagged) |
664 // rcx = argument count (untagged) | 663 // r11 = argument count (untagged) |
665 // Get the arguments map from the current native context into rdi. | 664 // Get the arguments map from the current native context into r9. |
666 Label has_mapped_parameters, instantiate; | 665 Label has_mapped_parameters, instantiate; |
667 __ movp(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 666 __ movp(r9, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
668 __ movp(rdi, FieldOperand(rdi, GlobalObject::kNativeContextOffset)); | 667 __ movp(r9, FieldOperand(r9, GlobalObject::kNativeContextOffset)); |
669 __ testp(rbx, rbx); | 668 __ testp(rbx, rbx); |
670 __ j(not_zero, &has_mapped_parameters, Label::kNear); | 669 __ j(not_zero, &has_mapped_parameters, Label::kNear); |
671 | 670 |
672 const int kIndex = Context::SLOPPY_ARGUMENTS_MAP_INDEX; | 671 const int kIndex = Context::SLOPPY_ARGUMENTS_MAP_INDEX; |
673 __ movp(rdi, Operand(rdi, Context::SlotOffset(kIndex))); | 672 __ movp(r9, Operand(r9, Context::SlotOffset(kIndex))); |
674 __ jmp(&instantiate, Label::kNear); | 673 __ jmp(&instantiate, Label::kNear); |
675 | 674 |
676 const int kAliasedIndex = Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX; | 675 const int kAliasedIndex = Context::FAST_ALIASED_ARGUMENTS_MAP_INDEX; |
677 __ bind(&has_mapped_parameters); | 676 __ bind(&has_mapped_parameters); |
678 __ movp(rdi, Operand(rdi, Context::SlotOffset(kAliasedIndex))); | 677 __ movp(r9, Operand(r9, Context::SlotOffset(kAliasedIndex))); |
679 __ bind(&instantiate); | 678 __ bind(&instantiate); |
680 | 679 |
681 // rax = address of new object (tagged) | 680 // rax = address of new object (tagged) |
682 // rbx = mapped parameter count (untagged) | 681 // rbx = mapped parameter count (untagged) |
683 // rcx = argument count (untagged) | 682 // r11 = argument count (untagged) |
684 // rdi = address of arguments map (tagged) | 683 // r9 = address of arguments map (tagged) |
685 __ movp(FieldOperand(rax, JSObject::kMapOffset), rdi); | 684 __ movp(FieldOperand(rax, JSObject::kMapOffset), r9); |
686 __ LoadRoot(kScratchRegister, Heap::kEmptyFixedArrayRootIndex); | 685 __ LoadRoot(kScratchRegister, Heap::kEmptyFixedArrayRootIndex); |
687 __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), kScratchRegister); | 686 __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), kScratchRegister); |
688 __ movp(FieldOperand(rax, JSObject::kElementsOffset), kScratchRegister); | 687 __ movp(FieldOperand(rax, JSObject::kElementsOffset), kScratchRegister); |
689 | 688 |
690 // Set up the callee in-object property. | 689 // Set up the callee in-object property. |
691 STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); | 690 STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); |
692 __ movp(rdx, args.GetArgumentOperand(0)); | 691 __ AssertNotSmi(rdi); |
693 __ AssertNotSmi(rdx); | |
694 __ movp(FieldOperand(rax, JSObject::kHeaderSize + | 692 __ movp(FieldOperand(rax, JSObject::kHeaderSize + |
695 Heap::kArgumentsCalleeIndex * kPointerSize), | 693 Heap::kArgumentsCalleeIndex * kPointerSize), |
696 rdx); | 694 rdi); |
697 | 695 |
698 // Use the length (smi tagged) and set that as an in-object property too. | 696 // Use the length (smi tagged) and set that as an in-object property too. |
699 // Note: rcx is tagged from here on. | 697 // Note: r11 is tagged from here on. |
700 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); | 698 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); |
701 __ Integer32ToSmi(rcx, rcx); | 699 __ Integer32ToSmi(r11, r11); |
702 __ movp(FieldOperand(rax, JSObject::kHeaderSize + | 700 __ movp(FieldOperand(rax, JSObject::kHeaderSize + |
703 Heap::kArgumentsLengthIndex * kPointerSize), | 701 Heap::kArgumentsLengthIndex * kPointerSize), |
704 rcx); | 702 r11); |
705 | 703 |
706 // Set up the elements pointer in the allocated arguments object. | 704 // Set up the elements pointer in the allocated arguments object. |
707 // If we allocated a parameter map, edi will point there, otherwise to the | 705 // If we allocated a parameter map, rdi will point there, otherwise to the |
708 // backing store. | 706 // backing store. |
709 __ leap(rdi, Operand(rax, Heap::kSloppyArgumentsObjectSize)); | 707 __ leap(rdi, Operand(rax, Heap::kSloppyArgumentsObjectSize)); |
710 __ movp(FieldOperand(rax, JSObject::kElementsOffset), rdi); | 708 __ movp(FieldOperand(rax, JSObject::kElementsOffset), rdi); |
711 | 709 |
712 // rax = address of new object (tagged) | 710 // rax = address of new object (tagged) |
713 // rbx = mapped parameter count (untagged) | 711 // rbx = mapped parameter count (untagged) |
714 // rcx = argument count (tagged) | 712 // r11 = argument count (tagged) |
715 // rdi = address of parameter map or backing store (tagged) | 713 // rdi = address of parameter map or backing store (tagged) |
716 | 714 |
717 // Initialize parameter map. If there are no mapped arguments, we're done. | 715 // Initialize parameter map. If there are no mapped arguments, we're done. |
718 Label skip_parameter_map; | 716 Label skip_parameter_map; |
719 __ testp(rbx, rbx); | 717 __ testp(rbx, rbx); |
720 __ j(zero, &skip_parameter_map); | 718 __ j(zero, &skip_parameter_map); |
721 | 719 |
722 __ LoadRoot(kScratchRegister, Heap::kSloppyArgumentsElementsMapRootIndex); | 720 __ LoadRoot(kScratchRegister, Heap::kSloppyArgumentsElementsMapRootIndex); |
723 // rbx contains the untagged argument count. Add 2 and tag to write. | 721 // rbx contains the untagged argument count. Add 2 and tag to write. |
724 __ movp(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister); | 722 __ movp(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister); |
725 __ Integer64PlusConstantToSmi(r9, rbx, 2); | 723 __ Integer64PlusConstantToSmi(r9, rbx, 2); |
726 __ movp(FieldOperand(rdi, FixedArray::kLengthOffset), r9); | 724 __ movp(FieldOperand(rdi, FixedArray::kLengthOffset), r9); |
727 __ movp(FieldOperand(rdi, FixedArray::kHeaderSize + 0 * kPointerSize), rsi); | 725 __ movp(FieldOperand(rdi, FixedArray::kHeaderSize + 0 * kPointerSize), rsi); |
728 __ leap(r9, Operand(rdi, rbx, times_pointer_size, kParameterMapHeaderSize)); | 726 __ leap(r9, Operand(rdi, rbx, times_pointer_size, kParameterMapHeaderSize)); |
729 __ movp(FieldOperand(rdi, FixedArray::kHeaderSize + 1 * kPointerSize), r9); | 727 __ movp(FieldOperand(rdi, FixedArray::kHeaderSize + 1 * kPointerSize), r9); |
730 | 728 |
731 // Copy the parameter slots and the holes in the arguments. | 729 // Copy the parameter slots and the holes in the arguments. |
732 // We need to fill in mapped_parameter_count slots. They index the context, | 730 // We need to fill in mapped_parameter_count slots. They index the context, |
733 // where parameters are stored in reverse order, at | 731 // where parameters are stored in reverse order, at |
734 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1 | 732 // MIN_CONTEXT_SLOTS .. MIN_CONTEXT_SLOTS+parameter_count-1 |
735 // The mapped parameter thus need to get indices | 733 // The mapped parameter thus need to get indices |
736 // MIN_CONTEXT_SLOTS+parameter_count-1 .. | 734 // MIN_CONTEXT_SLOTS+parameter_count-1 .. |
737 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count | 735 // MIN_CONTEXT_SLOTS+parameter_count-mapped_parameter_count |
738 // We loop from right to left. | 736 // We loop from right to left. |
739 Label parameters_loop, parameters_test; | 737 Label parameters_loop, parameters_test; |
740 | 738 |
741 // Load tagged parameter count into r9. | 739 // Load tagged parameter count into r9. |
742 __ Integer32ToSmi(r9, rbx); | 740 __ Integer32ToSmi(r9, rbx); |
743 __ Move(r8, Smi::FromInt(Context::MIN_CONTEXT_SLOTS)); | 741 __ Move(r8, Smi::FromInt(Context::MIN_CONTEXT_SLOTS)); |
744 __ addp(r8, args.GetArgumentOperand(2)); | 742 __ addp(r8, rcx); |
745 __ subp(r8, r9); | 743 __ subp(r8, r9); |
746 __ Move(r11, factory->the_hole_value()); | 744 __ movp(rcx, rdi); |
747 __ movp(rdx, rdi); | |
748 __ leap(rdi, Operand(rdi, rbx, times_pointer_size, kParameterMapHeaderSize)); | 745 __ leap(rdi, Operand(rdi, rbx, times_pointer_size, kParameterMapHeaderSize)); |
749 // r9 = loop variable (tagged) | 746 __ SmiToInteger64(r9, r9); |
| 747 // r9 = loop variable (untagged) |
750 // r8 = mapping index (tagged) | 748 // r8 = mapping index (tagged) |
751 // r11 = the hole value | 749 // rcx = address of parameter map (tagged) |
752 // rdx = address of parameter map (tagged) | |
753 // rdi = address of backing store (tagged) | 750 // rdi = address of backing store (tagged) |
754 __ jmp(¶meters_test, Label::kNear); | 751 __ jmp(¶meters_test, Label::kNear); |
755 | 752 |
756 __ bind(¶meters_loop); | 753 __ bind(¶meters_loop); |
757 __ SmiSubConstant(r9, r9, Smi::FromInt(1)); | 754 __ subp(r9, Immediate(1)); |
758 __ SmiToInteger64(kScratchRegister, r9); | 755 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); |
759 __ movp(FieldOperand(rdx, kScratchRegister, | 756 __ movp(FieldOperand(rcx, r9, times_pointer_size, kParameterMapHeaderSize), |
760 times_pointer_size, | |
761 kParameterMapHeaderSize), | |
762 r8); | 757 r8); |
763 __ movp(FieldOperand(rdi, kScratchRegister, | 758 __ movp(FieldOperand(rdi, r9, times_pointer_size, FixedArray::kHeaderSize), |
764 times_pointer_size, | 759 kScratchRegister); |
765 FixedArray::kHeaderSize), | |
766 r11); | |
767 __ SmiAddConstant(r8, r8, Smi::FromInt(1)); | 760 __ SmiAddConstant(r8, r8, Smi::FromInt(1)); |
768 __ bind(¶meters_test); | 761 __ bind(¶meters_test); |
769 __ SmiTest(r9); | 762 __ testp(r9, r9); |
770 __ j(not_zero, ¶meters_loop, Label::kNear); | 763 __ j(not_zero, ¶meters_loop, Label::kNear); |
771 | 764 |
772 __ bind(&skip_parameter_map); | 765 __ bind(&skip_parameter_map); |
773 | 766 |
774 // rcx = argument count (tagged) | 767 // r11 = argument count (tagged) |
775 // rdi = address of backing store (tagged) | 768 // rdi = address of backing store (tagged) |
776 // Copy arguments header and remaining slots (if there are any). | 769 // Copy arguments header and remaining slots (if there are any). |
777 __ Move(FieldOperand(rdi, FixedArray::kMapOffset), | 770 __ Move(FieldOperand(rdi, FixedArray::kMapOffset), |
778 factory->fixed_array_map()); | 771 factory->fixed_array_map()); |
779 __ movp(FieldOperand(rdi, FixedArray::kLengthOffset), rcx); | 772 __ movp(FieldOperand(rdi, FixedArray::kLengthOffset), r11); |
780 | 773 |
781 Label arguments_loop, arguments_test; | 774 Label arguments_loop, arguments_test; |
782 __ movp(r8, rbx); | 775 __ movp(r8, rbx); |
783 __ movp(rdx, args.GetArgumentOperand(1)); | 776 // Untag r11 for the loop below. |
784 // Untag rcx for the loop below. | 777 __ SmiToInteger64(r11, r11); |
785 __ SmiToInteger64(rcx, rcx); | |
786 __ leap(kScratchRegister, Operand(r8, times_pointer_size, 0)); | 778 __ leap(kScratchRegister, Operand(r8, times_pointer_size, 0)); |
787 __ subp(rdx, kScratchRegister); | 779 __ subp(rdx, kScratchRegister); |
788 __ jmp(&arguments_test, Label::kNear); | 780 __ jmp(&arguments_test, Label::kNear); |
789 | 781 |
790 __ bind(&arguments_loop); | 782 __ bind(&arguments_loop); |
791 __ subp(rdx, Immediate(kPointerSize)); | 783 __ subp(rdx, Immediate(kPointerSize)); |
792 __ movp(r9, Operand(rdx, 0)); | 784 __ movp(r9, Operand(rdx, 0)); |
793 __ movp(FieldOperand(rdi, r8, | 785 __ movp(FieldOperand(rdi, r8, |
794 times_pointer_size, | 786 times_pointer_size, |
795 FixedArray::kHeaderSize), | 787 FixedArray::kHeaderSize), |
796 r9); | 788 r9); |
797 __ addp(r8, Immediate(1)); | 789 __ addp(r8, Immediate(1)); |
798 | 790 |
799 __ bind(&arguments_test); | 791 __ bind(&arguments_test); |
800 __ cmpp(r8, rcx); | 792 __ cmpp(r8, r11); |
801 __ j(less, &arguments_loop, Label::kNear); | 793 __ j(less, &arguments_loop, Label::kNear); |
802 | 794 |
803 // Return and remove the on-stack parameters. | 795 // Return. |
804 __ ret(3 * kPointerSize); | 796 __ ret(0); |
805 | 797 |
806 // Do the runtime call to allocate the arguments object. | 798 // Do the runtime call to allocate the arguments object. |
807 // rcx = argument count (untagged) | 799 // r11 = argument count (untagged) |
808 __ bind(&runtime); | 800 __ bind(&runtime); |
809 __ Integer32ToSmi(rcx, rcx); | 801 __ Integer32ToSmi(r11, r11); |
810 __ movp(args.GetArgumentOperand(2), rcx); // Patch argument count. | 802 __ PopReturnAddressTo(rax); |
| 803 __ Push(rdi); // Push function. |
| 804 __ Push(rdx); // Push parameters pointer. |
| 805 __ Push(r11); // Push parameter count. |
| 806 __ PushReturnAddressFrom(rax); |
811 __ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1); | 807 __ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1); |
812 } | 808 } |
813 | 809 |
814 | 810 |
815 void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) { | 811 void ArgumentsAccessStub::GenerateNewSloppySlow(MacroAssembler* masm) { |
816 // rsp[0] : return address | 812 // rcx : number of parameters (tagged) |
817 // rsp[8] : number of parameters | 813 // rdx : parameters pointer |
818 // rsp[16] : receiver displacement | 814 // rdi : function |
819 // rsp[24] : function | 815 // rsp[0] : return address |
| 816 |
| 817 DCHECK(rdi.is(ArgumentsAccessNewDescriptor::function())); |
| 818 DCHECK(rcx.is(ArgumentsAccessNewDescriptor::parameter_count())); |
| 819 DCHECK(rdx.is(ArgumentsAccessNewDescriptor::parameter_pointer())); |
820 | 820 |
821 // Check if the calling frame is an arguments adaptor frame. | 821 // Check if the calling frame is an arguments adaptor frame. |
822 Label runtime; | 822 Label runtime; |
823 __ movp(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 823 __ movp(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
824 __ movp(rcx, Operand(rdx, StandardFrameConstants::kContextOffset)); | 824 __ movp(rax, Operand(rbx, StandardFrameConstants::kContextOffset)); |
825 __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | 825 __ Cmp(rax, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
826 __ j(not_equal, &runtime); | 826 __ j(not_equal, &runtime); |
827 | 827 |
828 // Patch the arguments.length and the parameters pointer. | 828 // Patch the arguments.length and the parameters pointer. |
829 StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER); | 829 StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER); |
830 __ movp(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 830 __ movp(rcx, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
831 __ movp(args.GetArgumentOperand(2), rcx); | 831 __ SmiToInteger64(rax, rcx); |
832 __ SmiToInteger64(rcx, rcx); | 832 __ leap(rdx, Operand(rbx, rax, times_pointer_size, |
833 __ leap(rdx, Operand(rdx, rcx, times_pointer_size, | 833 StandardFrameConstants::kCallerSPOffset)); |
834 StandardFrameConstants::kCallerSPOffset)); | |
835 __ movp(args.GetArgumentOperand(1), rdx); | |
836 | 834 |
837 __ bind(&runtime); | 835 __ bind(&runtime); |
| 836 __ PopReturnAddressTo(rax); |
| 837 __ Push(rdi); // Push function. |
| 838 __ Push(rdx); // Push parameters pointer. |
| 839 __ Push(rcx); // Push parameter count. |
| 840 __ PushReturnAddressFrom(rax); |
838 __ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1); | 841 __ TailCallRuntime(Runtime::kNewSloppyArguments, 3, 1); |
839 } | 842 } |
840 | 843 |
841 | 844 |
842 void LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) { | 845 void LoadIndexedInterceptorStub::Generate(MacroAssembler* masm) { |
843 // Return address is on the stack. | 846 // Return address is on the stack. |
844 Label slow; | 847 Label slow; |
845 | 848 |
846 Register receiver = LoadDescriptor::ReceiverRegister(); | 849 Register receiver = LoadDescriptor::ReceiverRegister(); |
847 Register key = LoadDescriptor::NameRegister(); | 850 Register key = LoadDescriptor::NameRegister(); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
894 StubRuntimeCallHelper call_helper; | 897 StubRuntimeCallHelper call_helper; |
895 char_at_generator.GenerateSlow(masm, PART_OF_IC_HANDLER, call_helper); | 898 char_at_generator.GenerateSlow(masm, PART_OF_IC_HANDLER, call_helper); |
896 | 899 |
897 __ bind(&miss); | 900 __ bind(&miss); |
898 PropertyAccessCompiler::TailCallBuiltin( | 901 PropertyAccessCompiler::TailCallBuiltin( |
899 masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC)); | 902 masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC)); |
900 } | 903 } |
901 | 904 |
902 | 905 |
903 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { | 906 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { |
904 // rsp[0] : return address | 907 // rcx : number of parameters (tagged) |
905 // rsp[8] : number of parameters | 908 // rdx : parameters pointer |
906 // rsp[16] : receiver displacement | 909 // rdi : function |
907 // rsp[24] : function | 910 // rsp[0] : return address |
| 911 |
| 912 DCHECK(rdi.is(ArgumentsAccessNewDescriptor::function())); |
| 913 DCHECK(rcx.is(ArgumentsAccessNewDescriptor::parameter_count())); |
| 914 DCHECK(rdx.is(ArgumentsAccessNewDescriptor::parameter_pointer())); |
908 | 915 |
909 // Check if the calling frame is an arguments adaptor frame. | 916 // Check if the calling frame is an arguments adaptor frame. |
910 Label adaptor_frame, try_allocate, runtime; | 917 Label adaptor_frame, try_allocate, runtime; |
911 __ movp(rdx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | 918 __ movp(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); |
912 __ movp(rcx, Operand(rdx, StandardFrameConstants::kContextOffset)); | 919 __ movp(rax, Operand(rbx, StandardFrameConstants::kContextOffset)); |
913 __ Cmp(rcx, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | 920 __ Cmp(rax, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
914 __ j(equal, &adaptor_frame); | 921 __ j(equal, &adaptor_frame); |
915 | 922 |
916 // Get the length from the frame. | 923 // Get the length from the frame. |
917 StackArgumentsAccessor args(rsp, 3, ARGUMENTS_DONT_CONTAIN_RECEIVER); | 924 __ SmiToInteger64(rax, rcx); |
918 __ movp(rcx, args.GetArgumentOperand(2)); | |
919 __ SmiToInteger64(rcx, rcx); | |
920 __ jmp(&try_allocate); | 925 __ jmp(&try_allocate); |
921 | 926 |
922 // Patch the arguments.length and the parameters pointer. | 927 // Patch the arguments.length and the parameters pointer. |
923 __ bind(&adaptor_frame); | 928 __ bind(&adaptor_frame); |
924 __ movp(rcx, Operand(rdx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 929 __ movp(rcx, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
925 | 930 __ SmiToInteger64(rax, rcx); |
926 __ movp(args.GetArgumentOperand(2), rcx); | 931 __ leap(rdx, Operand(rbx, rax, times_pointer_size, |
927 __ SmiToInteger64(rcx, rcx); | 932 StandardFrameConstants::kCallerSPOffset)); |
928 __ leap(rdx, Operand(rdx, rcx, times_pointer_size, | |
929 StandardFrameConstants::kCallerSPOffset)); | |
930 __ movp(args.GetArgumentOperand(1), rdx); | |
931 | 933 |
932 // Try the new space allocation. Start out with computing the size of | 934 // Try the new space allocation. Start out with computing the size of |
933 // the arguments object and the elements array. | 935 // the arguments object and the elements array. |
934 Label add_arguments_object; | 936 Label add_arguments_object; |
935 __ bind(&try_allocate); | 937 __ bind(&try_allocate); |
936 __ testp(rcx, rcx); | 938 __ testp(rax, rax); |
937 __ j(zero, &add_arguments_object, Label::kNear); | 939 __ j(zero, &add_arguments_object, Label::kNear); |
938 __ leap(rcx, Operand(rcx, times_pointer_size, FixedArray::kHeaderSize)); | 940 __ leap(rax, Operand(rax, times_pointer_size, FixedArray::kHeaderSize)); |
939 __ bind(&add_arguments_object); | 941 __ bind(&add_arguments_object); |
940 __ addp(rcx, Immediate(Heap::kStrictArgumentsObjectSize)); | 942 __ addp(rax, Immediate(Heap::kStrictArgumentsObjectSize)); |
941 | 943 |
942 // Do the allocation of both objects in one go. | 944 // Do the allocation of both objects in one go. |
943 __ Allocate(rcx, rax, rdx, rbx, &runtime, TAG_OBJECT); | 945 __ Allocate(rax, rax, rbx, no_reg, &runtime, TAG_OBJECT); |
944 | 946 |
945 // Get the arguments map from the current native context. | 947 // Get the arguments map from the current native context. |
946 __ movp(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); | 948 __ movp(rdi, Operand(rsi, Context::SlotOffset(Context::GLOBAL_OBJECT_INDEX))); |
947 __ movp(rdi, FieldOperand(rdi, GlobalObject::kNativeContextOffset)); | 949 __ movp(rdi, FieldOperand(rdi, GlobalObject::kNativeContextOffset)); |
948 const int offset = Context::SlotOffset(Context::STRICT_ARGUMENTS_MAP_INDEX); | 950 const int offset = Context::SlotOffset(Context::STRICT_ARGUMENTS_MAP_INDEX); |
949 __ movp(rdi, Operand(rdi, offset)); | 951 __ movp(rdi, Operand(rdi, offset)); |
950 | 952 |
951 __ movp(FieldOperand(rax, JSObject::kMapOffset), rdi); | 953 __ movp(FieldOperand(rax, JSObject::kMapOffset), rdi); |
952 __ LoadRoot(kScratchRegister, Heap::kEmptyFixedArrayRootIndex); | 954 __ LoadRoot(kScratchRegister, Heap::kEmptyFixedArrayRootIndex); |
953 __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), kScratchRegister); | 955 __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), kScratchRegister); |
954 __ movp(FieldOperand(rax, JSObject::kElementsOffset), kScratchRegister); | 956 __ movp(FieldOperand(rax, JSObject::kElementsOffset), kScratchRegister); |
955 | 957 |
956 // Get the length (smi tagged) and set that as an in-object property too. | 958 // Get the length (smi tagged) and set that as an in-object property too. |
957 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); | 959 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); |
958 __ movp(rcx, args.GetArgumentOperand(2)); | |
959 __ movp(FieldOperand(rax, JSObject::kHeaderSize + | 960 __ movp(FieldOperand(rax, JSObject::kHeaderSize + |
960 Heap::kArgumentsLengthIndex * kPointerSize), | 961 Heap::kArgumentsLengthIndex * kPointerSize), |
961 rcx); | 962 rcx); |
962 | 963 |
963 // If there are no actual arguments, we're done. | 964 // If there are no actual arguments, we're done. |
964 Label done; | 965 Label done; |
965 __ testp(rcx, rcx); | 966 __ testp(rcx, rcx); |
966 __ j(zero, &done); | 967 __ j(zero, &done); |
967 | 968 |
968 // Get the parameters pointer from the stack. | |
969 __ movp(rdx, args.GetArgumentOperand(1)); | |
970 | |
971 // Set up the elements pointer in the allocated arguments object and | 969 // Set up the elements pointer in the allocated arguments object and |
972 // initialize the header in the elements fixed array. | 970 // initialize the header in the elements fixed array. |
973 __ leap(rdi, Operand(rax, Heap::kStrictArgumentsObjectSize)); | 971 __ leap(rdi, Operand(rax, Heap::kStrictArgumentsObjectSize)); |
974 __ movp(FieldOperand(rax, JSObject::kElementsOffset), rdi); | 972 __ movp(FieldOperand(rax, JSObject::kElementsOffset), rdi); |
975 __ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex); | 973 __ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex); |
976 __ movp(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister); | 974 __ movp(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister); |
| 975 __ movp(FieldOperand(rdi, FixedArray::kLengthOffset), rcx); |
977 | 976 |
978 | |
979 __ movp(FieldOperand(rdi, FixedArray::kLengthOffset), rcx); | |
980 // Untag the length for the loop below. | 977 // Untag the length for the loop below. |
981 __ SmiToInteger64(rcx, rcx); | 978 __ SmiToInteger64(rcx, rcx); |
982 | 979 |
983 // Copy the fixed array slots. | 980 // Copy the fixed array slots. |
984 Label loop; | 981 Label loop; |
985 __ bind(&loop); | 982 __ bind(&loop); |
986 __ movp(rbx, Operand(rdx, -1 * kPointerSize)); // Skip receiver. | 983 __ movp(rbx, Operand(rdx, -1 * kPointerSize)); // Skip receiver. |
987 __ movp(FieldOperand(rdi, FixedArray::kHeaderSize), rbx); | 984 __ movp(FieldOperand(rdi, FixedArray::kHeaderSize), rbx); |
988 __ addp(rdi, Immediate(kPointerSize)); | 985 __ addp(rdi, Immediate(kPointerSize)); |
989 __ subp(rdx, Immediate(kPointerSize)); | 986 __ subp(rdx, Immediate(kPointerSize)); |
990 __ decp(rcx); | 987 __ decp(rcx); |
991 __ j(not_zero, &loop); | 988 __ j(not_zero, &loop); |
992 | 989 |
993 // Return and remove the on-stack parameters. | 990 // Return. |
994 __ bind(&done); | 991 __ bind(&done); |
995 __ ret(3 * kPointerSize); | 992 __ ret(0); |
996 | 993 |
997 // Do the runtime call to allocate the arguments object. | 994 // Do the runtime call to allocate the arguments object. |
998 __ bind(&runtime); | 995 __ bind(&runtime); |
| 996 __ PopReturnAddressTo(rax); |
| 997 __ Push(rdi); // Push function. |
| 998 __ Push(rdx); // Push parameters pointer. |
| 999 __ Push(rcx); // Push parameter count. |
| 1000 __ PushReturnAddressFrom(rax); |
999 __ TailCallRuntime(Runtime::kNewStrictArguments, 3, 1); | 1001 __ TailCallRuntime(Runtime::kNewStrictArguments, 3, 1); |
1000 } | 1002 } |
1001 | 1003 |
1002 | 1004 |
1003 void RegExpExecStub::Generate(MacroAssembler* masm) { | 1005 void RegExpExecStub::Generate(MacroAssembler* masm) { |
1004 // Just jump directly to runtime if native RegExp is not selected at compile | 1006 // Just jump directly to runtime if native RegExp is not selected at compile |
1005 // time or if regexp entry in generated code is turned off runtime switch or | 1007 // time or if regexp entry in generated code is turned off runtime switch or |
1006 // at compilation. | 1008 // at compilation. |
1007 #ifdef V8_INTERPRETED_REGEXP | 1009 #ifdef V8_INTERPRETED_REGEXP |
1008 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); | 1010 __ TailCallRuntime(Runtime::kRegExpExec, 4, 1); |
(...skipping 4563 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5572 kStackSpace, nullptr, return_value_operand, NULL); | 5574 kStackSpace, nullptr, return_value_operand, NULL); |
5573 } | 5575 } |
5574 | 5576 |
5575 | 5577 |
5576 #undef __ | 5578 #undef __ |
5577 | 5579 |
5578 } // namespace internal | 5580 } // namespace internal |
5579 } // namespace v8 | 5581 } // namespace v8 |
5580 | 5582 |
5581 #endif // V8_TARGET_ARCH_X64 | 5583 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |