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