| 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 |