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 633 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
644 __ xorp(r8, r8); | 644 __ xorp(r8, r8); |
645 __ testp(rbx, rbx); | 645 __ testp(rbx, rbx); |
646 __ j(zero, &no_parameter_map, Label::kNear); | 646 __ j(zero, &no_parameter_map, Label::kNear); |
647 __ leap(r8, Operand(rbx, times_pointer_size, kParameterMapHeaderSize)); | 647 __ leap(r8, Operand(rbx, times_pointer_size, kParameterMapHeaderSize)); |
648 __ bind(&no_parameter_map); | 648 __ bind(&no_parameter_map); |
649 | 649 |
650 // 2. Backing store. | 650 // 2. Backing store. |
651 __ leap(r8, Operand(r8, r11, times_pointer_size, FixedArray::kHeaderSize)); | 651 __ leap(r8, Operand(r8, r11, times_pointer_size, FixedArray::kHeaderSize)); |
652 | 652 |
653 // 3. Arguments object. | 653 // 3. Arguments object. |
654 __ addp(r8, Immediate(Heap::kSloppyArgumentsObjectSize)); | 654 __ addp(r8, Immediate(JSSloppyArgumentsObject::kSize)); |
655 | 655 |
656 // Do the allocation of all three objects in one go. | 656 // Do the allocation of all three objects in one go. |
657 __ Allocate(r8, rax, r9, no_reg, &runtime, TAG_OBJECT); | 657 __ Allocate(r8, rax, r9, no_reg, &runtime, TAG_OBJECT); |
658 | 658 |
659 // rax = address of new object(s) (tagged) | 659 // rax = address of new object(s) (tagged) |
660 // r11 = argument count (untagged) | 660 // r11 = argument count (untagged) |
661 // Get the arguments map from the current native context into r9. | 661 // Get the arguments map from the current native context into r9. |
662 Label has_mapped_parameters, instantiate; | 662 Label has_mapped_parameters, instantiate; |
663 __ movp(r9, NativeContextOperand()); | 663 __ movp(r9, NativeContextOperand()); |
664 __ testp(rbx, rbx); | 664 __ testp(rbx, rbx); |
(...skipping 11 matching lines...) Expand all Loading... |
676 // rax = address of new object (tagged) | 676 // rax = address of new object (tagged) |
677 // rbx = mapped parameter count (untagged) | 677 // rbx = mapped parameter count (untagged) |
678 // r11 = argument count (untagged) | 678 // r11 = argument count (untagged) |
679 // r9 = address of arguments map (tagged) | 679 // r9 = address of arguments map (tagged) |
680 __ movp(FieldOperand(rax, JSObject::kMapOffset), r9); | 680 __ movp(FieldOperand(rax, JSObject::kMapOffset), r9); |
681 __ LoadRoot(kScratchRegister, Heap::kEmptyFixedArrayRootIndex); | 681 __ LoadRoot(kScratchRegister, Heap::kEmptyFixedArrayRootIndex); |
682 __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), kScratchRegister); | 682 __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), kScratchRegister); |
683 __ movp(FieldOperand(rax, JSObject::kElementsOffset), kScratchRegister); | 683 __ movp(FieldOperand(rax, JSObject::kElementsOffset), kScratchRegister); |
684 | 684 |
685 // Set up the callee in-object property. | 685 // Set up the callee in-object property. |
686 STATIC_ASSERT(Heap::kArgumentsCalleeIndex == 1); | |
687 __ AssertNotSmi(rdi); | 686 __ AssertNotSmi(rdi); |
688 __ movp(FieldOperand(rax, JSObject::kHeaderSize + | 687 __ movp(FieldOperand(rax, JSSloppyArgumentsObject::kCalleeOffset), rdi); |
689 Heap::kArgumentsCalleeIndex * kPointerSize), | |
690 rdi); | |
691 | 688 |
692 // Use the length (smi tagged) and set that as an in-object property too. | 689 // Use the length (smi tagged) and set that as an in-object property too. |
693 // Note: r11 is tagged from here on. | 690 // Note: r11 is tagged from here on. |
694 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); | |
695 __ Integer32ToSmi(r11, r11); | 691 __ Integer32ToSmi(r11, r11); |
696 __ movp(FieldOperand(rax, JSObject::kHeaderSize + | 692 __ movp(FieldOperand(rax, JSSloppyArgumentsObject::kLengthOffset), r11); |
697 Heap::kArgumentsLengthIndex * kPointerSize), | |
698 r11); | |
699 | 693 |
700 // Set up the elements pointer in the allocated arguments object. | 694 // Set up the elements pointer in the allocated arguments object. |
701 // If we allocated a parameter map, rdi will point there, otherwise to the | 695 // If we allocated a parameter map, rdi will point there, otherwise to the |
702 // backing store. | 696 // backing store. |
703 __ leap(rdi, Operand(rax, Heap::kSloppyArgumentsObjectSize)); | 697 __ leap(rdi, Operand(rax, JSSloppyArgumentsObject::kSize)); |
704 __ movp(FieldOperand(rax, JSObject::kElementsOffset), rdi); | 698 __ movp(FieldOperand(rax, JSObject::kElementsOffset), rdi); |
705 | 699 |
706 // rax = address of new object (tagged) | 700 // rax = address of new object (tagged) |
707 // rbx = mapped parameter count (untagged) | 701 // rbx = mapped parameter count (untagged) |
708 // r11 = argument count (tagged) | 702 // r11 = argument count (tagged) |
709 // rdi = address of parameter map or backing store (tagged) | 703 // rdi = address of parameter map or backing store (tagged) |
710 | 704 |
711 // Initialize parameter map. If there are no mapped arguments, we're done. | 705 // Initialize parameter map. If there are no mapped arguments, we're done. |
712 Label skip_parameter_map; | 706 Label skip_parameter_map; |
713 __ testp(rbx, rbx); | 707 __ testp(rbx, rbx); |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
892 | 886 |
893 StubRuntimeCallHelper call_helper; | 887 StubRuntimeCallHelper call_helper; |
894 char_at_generator.GenerateSlow(masm, PART_OF_IC_HANDLER, call_helper); | 888 char_at_generator.GenerateSlow(masm, PART_OF_IC_HANDLER, call_helper); |
895 | 889 |
896 __ bind(&miss); | 890 __ bind(&miss); |
897 PropertyAccessCompiler::TailCallBuiltin( | 891 PropertyAccessCompiler::TailCallBuiltin( |
898 masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC)); | 892 masm, PropertyAccessCompiler::MissBuiltin(Code::KEYED_LOAD_IC)); |
899 } | 893 } |
900 | 894 |
901 | 895 |
902 void ArgumentsAccessStub::GenerateNewStrict(MacroAssembler* masm) { | |
903 // rcx : number of parameters (tagged) | |
904 // rdx : parameters pointer | |
905 // rdi : function | |
906 // rsp[0] : return address | |
907 | |
908 DCHECK(rdi.is(ArgumentsAccessNewDescriptor::function())); | |
909 DCHECK(rcx.is(ArgumentsAccessNewDescriptor::parameter_count())); | |
910 DCHECK(rdx.is(ArgumentsAccessNewDescriptor::parameter_pointer())); | |
911 | |
912 // Check if the calling frame is an arguments adaptor frame. | |
913 Label adaptor_frame, try_allocate, runtime; | |
914 __ movp(rbx, Operand(rbp, StandardFrameConstants::kCallerFPOffset)); | |
915 __ movp(rax, Operand(rbx, StandardFrameConstants::kContextOffset)); | |
916 __ Cmp(rax, Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); | |
917 __ j(equal, &adaptor_frame); | |
918 | |
919 // Get the length from the frame. | |
920 __ SmiToInteger64(rax, rcx); | |
921 __ jmp(&try_allocate); | |
922 | |
923 // Patch the arguments.length and the parameters pointer. | |
924 __ bind(&adaptor_frame); | |
925 __ movp(rcx, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset)); | |
926 __ SmiToInteger64(rax, rcx); | |
927 __ leap(rdx, Operand(rbx, rax, times_pointer_size, | |
928 StandardFrameConstants::kCallerSPOffset)); | |
929 | |
930 // Try the new space allocation. Start out with computing the size of | |
931 // the arguments object and the elements array. | |
932 Label add_arguments_object; | |
933 __ bind(&try_allocate); | |
934 __ testp(rax, rax); | |
935 __ j(zero, &add_arguments_object, Label::kNear); | |
936 __ leap(rax, Operand(rax, times_pointer_size, FixedArray::kHeaderSize)); | |
937 __ bind(&add_arguments_object); | |
938 __ addp(rax, Immediate(Heap::kStrictArgumentsObjectSize)); | |
939 | |
940 // Do the allocation of both objects in one go. | |
941 __ Allocate(rax, rax, rbx, no_reg, &runtime, TAG_OBJECT); | |
942 | |
943 // Get the arguments map from the current native context. | |
944 __ movp(rdi, NativeContextOperand()); | |
945 __ movp(rdi, ContextOperand(rdi, Context::STRICT_ARGUMENTS_MAP_INDEX)); | |
946 | |
947 __ movp(FieldOperand(rax, JSObject::kMapOffset), rdi); | |
948 __ LoadRoot(kScratchRegister, Heap::kEmptyFixedArrayRootIndex); | |
949 __ movp(FieldOperand(rax, JSObject::kPropertiesOffset), kScratchRegister); | |
950 __ movp(FieldOperand(rax, JSObject::kElementsOffset), kScratchRegister); | |
951 | |
952 // Get the length (smi tagged) and set that as an in-object property too. | |
953 STATIC_ASSERT(Heap::kArgumentsLengthIndex == 0); | |
954 __ movp(FieldOperand(rax, JSObject::kHeaderSize + | |
955 Heap::kArgumentsLengthIndex * kPointerSize), | |
956 rcx); | |
957 | |
958 // If there are no actual arguments, we're done. | |
959 Label done; | |
960 __ testp(rcx, rcx); | |
961 __ j(zero, &done); | |
962 | |
963 // Set up the elements pointer in the allocated arguments object and | |
964 // initialize the header in the elements fixed array. | |
965 __ leap(rdi, Operand(rax, Heap::kStrictArgumentsObjectSize)); | |
966 __ movp(FieldOperand(rax, JSObject::kElementsOffset), rdi); | |
967 __ LoadRoot(kScratchRegister, Heap::kFixedArrayMapRootIndex); | |
968 __ movp(FieldOperand(rdi, FixedArray::kMapOffset), kScratchRegister); | |
969 __ movp(FieldOperand(rdi, FixedArray::kLengthOffset), rcx); | |
970 | |
971 // Untag the length for the loop below. | |
972 __ SmiToInteger64(rcx, rcx); | |
973 | |
974 // Copy the fixed array slots. | |
975 Label loop; | |
976 __ bind(&loop); | |
977 __ movp(rbx, Operand(rdx, -1 * kPointerSize)); // Skip receiver. | |
978 __ movp(FieldOperand(rdi, FixedArray::kHeaderSize), rbx); | |
979 __ addp(rdi, Immediate(kPointerSize)); | |
980 __ subp(rdx, Immediate(kPointerSize)); | |
981 __ decp(rcx); | |
982 __ j(not_zero, &loop); | |
983 | |
984 // Return. | |
985 __ bind(&done); | |
986 __ ret(0); | |
987 | |
988 // Do the runtime call to allocate the arguments object. | |
989 __ bind(&runtime); | |
990 __ PopReturnAddressTo(rax); | |
991 __ Push(rdi); // Push function. | |
992 __ Push(rdx); // Push parameters pointer. | |
993 __ Push(rcx); // Push parameter count. | |
994 __ PushReturnAddressFrom(rax); | |
995 __ TailCallRuntime(Runtime::kNewStrictArguments); | |
996 } | |
997 | |
998 | |
999 void RegExpExecStub::Generate(MacroAssembler* masm) { | 896 void RegExpExecStub::Generate(MacroAssembler* masm) { |
1000 // Just jump directly to runtime if native RegExp is not selected at compile | 897 // Just jump directly to runtime if native RegExp is not selected at compile |
1001 // time or if regexp entry in generated code is turned off runtime switch or | 898 // time or if regexp entry in generated code is turned off runtime switch or |
1002 // at compilation. | 899 // at compilation. |
1003 #ifdef V8_INTERPRETED_REGEXP | 900 #ifdef V8_INTERPRETED_REGEXP |
1004 __ TailCallRuntime(Runtime::kRegExpExec); | 901 __ TailCallRuntime(Runtime::kRegExpExec); |
1005 #else // V8_INTERPRETED_REGEXP | 902 #else // V8_INTERPRETED_REGEXP |
1006 | 903 |
1007 // Stack frame on entry. | 904 // Stack frame on entry. |
1008 // rsp[0] : return address | 905 // rsp[0] : return address |
(...skipping 4019 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5028 __ movp(rdx, rax); | 4925 __ movp(rdx, rax); |
5029 __ Pop(rbx); | 4926 __ Pop(rbx); |
5030 __ Pop(rax); | 4927 __ Pop(rax); |
5031 __ SmiToInteger32(rax, rax); | 4928 __ SmiToInteger32(rax, rax); |
5032 } | 4929 } |
5033 __ jmp(&done_allocate); | 4930 __ jmp(&done_allocate); |
5034 } | 4931 } |
5035 } | 4932 } |
5036 | 4933 |
5037 | 4934 |
| 4935 void FastNewStrictArgumentsStub::Generate(MacroAssembler* masm) { |
| 4936 // ----------- S t a t e ------------- |
| 4937 // -- rdi : function |
| 4938 // -- rsi : context |
| 4939 // -- rbp : frame pointer |
| 4940 // -- rsp[0] : return address |
| 4941 // ----------------------------------- |
| 4942 __ AssertFunction(rdi); |
| 4943 |
| 4944 // For Ignition we need to skip all possible handler/stub frames until |
| 4945 // we reach the JavaScript frame for the function (similar to what the |
| 4946 // runtime fallback implementation does). So make rdx point to that |
| 4947 // JavaScript frame. |
| 4948 { |
| 4949 Label loop, loop_entry; |
| 4950 __ movp(rdx, rbp); |
| 4951 __ jmp(&loop_entry, Label::kNear); |
| 4952 __ bind(&loop); |
| 4953 __ movp(rdx, Operand(rdx, StandardFrameConstants::kCallerFPOffset)); |
| 4954 __ bind(&loop_entry); |
| 4955 __ cmpp(rdi, Operand(rdx, StandardFrameConstants::kMarkerOffset)); |
| 4956 __ j(not_equal, &loop); |
| 4957 } |
| 4958 |
| 4959 // Check if we have an arguments adaptor frame below the function frame. |
| 4960 Label arguments_adaptor, arguments_done; |
| 4961 __ movp(rbx, Operand(rdx, StandardFrameConstants::kCallerFPOffset)); |
| 4962 __ Cmp(Operand(rbx, StandardFrameConstants::kContextOffset), |
| 4963 Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR)); |
| 4964 __ j(equal, &arguments_adaptor, Label::kNear); |
| 4965 { |
| 4966 __ movp(rax, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); |
| 4967 __ LoadSharedFunctionInfoSpecialField( |
| 4968 rax, rax, SharedFunctionInfo::kFormalParameterCountOffset); |
| 4969 __ leap(rbx, Operand(rdx, rax, times_pointer_size, |
| 4970 StandardFrameConstants::kCallerSPOffset - |
| 4971 1 * kPointerSize)); |
| 4972 } |
| 4973 __ jmp(&arguments_done, Label::kNear); |
| 4974 __ bind(&arguments_adaptor); |
| 4975 { |
| 4976 __ SmiToInteger32( |
| 4977 rax, Operand(rbx, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
| 4978 __ leap(rbx, Operand(rbx, rax, times_pointer_size, |
| 4979 StandardFrameConstants::kCallerSPOffset - |
| 4980 1 * kPointerSize)); |
| 4981 } |
| 4982 __ bind(&arguments_done); |
| 4983 |
| 4984 // ----------- S t a t e ------------- |
| 4985 // -- rax : number of arguments |
| 4986 // -- rbx : pointer to the first argument |
| 4987 // -- rsi : context |
| 4988 // -- rsp[0] : return address |
| 4989 // ----------------------------------- |
| 4990 |
| 4991 // Allocate space for the strict arguments object plus the backing store. |
| 4992 Label allocate, done_allocate; |
| 4993 __ leal(rcx, Operand(rax, times_pointer_size, JSStrictArgumentsObject::kSize + |
| 4994 FixedArray::kHeaderSize)); |
| 4995 __ Allocate(rcx, rdx, rdi, no_reg, &allocate, TAG_OBJECT); |
| 4996 __ bind(&done_allocate); |
| 4997 |
| 4998 // Compute the arguments.length in rdi. |
| 4999 __ Integer32ToSmi(rdi, rax); |
| 5000 |
| 5001 // Setup the elements array in rdx. |
| 5002 __ LoadRoot(rcx, Heap::kFixedArrayMapRootIndex); |
| 5003 __ movp(FieldOperand(rdx, FixedArray::kMapOffset), rcx); |
| 5004 __ movp(FieldOperand(rdx, FixedArray::kLengthOffset), rdi); |
| 5005 { |
| 5006 Label loop, done_loop; |
| 5007 __ Set(rcx, 0); |
| 5008 __ bind(&loop); |
| 5009 __ cmpl(rcx, rax); |
| 5010 __ j(equal, &done_loop, Label::kNear); |
| 5011 __ movp(kScratchRegister, Operand(rbx, 0 * kPointerSize)); |
| 5012 __ movp( |
| 5013 FieldOperand(rdx, rcx, times_pointer_size, FixedArray::kHeaderSize), |
| 5014 kScratchRegister); |
| 5015 __ subp(rbx, Immediate(1 * kPointerSize)); |
| 5016 __ addl(rcx, Immediate(1)); |
| 5017 __ jmp(&loop); |
| 5018 __ bind(&done_loop); |
| 5019 } |
| 5020 |
| 5021 // Setup the strict arguments object in rax. |
| 5022 __ leap(rax, |
| 5023 Operand(rdx, rax, times_pointer_size, FixedArray::kHeaderSize)); |
| 5024 __ LoadNativeContextSlot(Context::STRICT_ARGUMENTS_MAP_INDEX, rcx); |
| 5025 __ movp(FieldOperand(rax, JSStrictArgumentsObject::kMapOffset), rcx); |
| 5026 __ LoadRoot(rcx, Heap::kEmptyFixedArrayRootIndex); |
| 5027 __ movp(FieldOperand(rax, JSStrictArgumentsObject::kPropertiesOffset), rcx); |
| 5028 __ movp(FieldOperand(rax, JSStrictArgumentsObject::kElementsOffset), rdx); |
| 5029 __ movp(FieldOperand(rax, JSStrictArgumentsObject::kLengthOffset), rdi); |
| 5030 STATIC_ASSERT(JSStrictArgumentsObject::kSize == 4 * kPointerSize); |
| 5031 __ Ret(); |
| 5032 |
| 5033 // Fall back to %AllocateInNewSpace. |
| 5034 __ bind(&allocate); |
| 5035 { |
| 5036 FrameScope scope(masm, StackFrame::INTERNAL); |
| 5037 __ Integer32ToSmi(rax, rax); |
| 5038 __ Integer32ToSmi(rcx, rcx); |
| 5039 __ Push(rax); |
| 5040 __ Push(rbx); |
| 5041 __ Push(rcx); |
| 5042 __ CallRuntime(Runtime::kAllocateInNewSpace); |
| 5043 __ movp(rdx, rax); |
| 5044 __ Pop(rbx); |
| 5045 __ Pop(rax); |
| 5046 __ SmiToInteger32(rax, rax); |
| 5047 } |
| 5048 __ jmp(&done_allocate); |
| 5049 } |
| 5050 |
| 5051 |
5038 void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) { | 5052 void LoadGlobalViaContextStub::Generate(MacroAssembler* masm) { |
5039 Register context_reg = rsi; | 5053 Register context_reg = rsi; |
5040 Register slot_reg = rbx; | 5054 Register slot_reg = rbx; |
5041 Register result_reg = rax; | 5055 Register result_reg = rax; |
5042 Label slow_case; | 5056 Label slow_case; |
5043 | 5057 |
5044 // Go up context chain to the script context. | 5058 // Go up context chain to the script context. |
5045 for (int i = 0; i < depth(); ++i) { | 5059 for (int i = 0; i < depth(); ++i) { |
5046 __ movp(rdi, ContextOperand(context_reg, Context::PREVIOUS_INDEX)); | 5060 __ movp(rdi, ContextOperand(context_reg, Context::PREVIOUS_INDEX)); |
5047 context_reg = rdi; | 5061 context_reg = rdi; |
(...skipping 539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5587 NULL); | 5601 NULL); |
5588 } | 5602 } |
5589 | 5603 |
5590 | 5604 |
5591 #undef __ | 5605 #undef __ |
5592 | 5606 |
5593 } // namespace internal | 5607 } // namespace internal |
5594 } // namespace v8 | 5608 } // namespace v8 |
5595 | 5609 |
5596 #endif // V8_TARGET_ARCH_X64 | 5610 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |