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 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_X64 | 7 #if V8_TARGET_ARCH_X64 |
8 | 8 |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
(...skipping 4603 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4614 Label fast_elements_case; | 4614 Label fast_elements_case; |
4615 __ cmpl(rcx, Immediate(FAST_ELEMENTS)); | 4615 __ cmpl(rcx, Immediate(FAST_ELEMENTS)); |
4616 __ j(equal, &fast_elements_case); | 4616 __ j(equal, &fast_elements_case); |
4617 GenerateCase(masm, FAST_HOLEY_ELEMENTS); | 4617 GenerateCase(masm, FAST_HOLEY_ELEMENTS); |
4618 | 4618 |
4619 __ bind(&fast_elements_case); | 4619 __ bind(&fast_elements_case); |
4620 GenerateCase(masm, FAST_ELEMENTS); | 4620 GenerateCase(masm, FAST_ELEMENTS); |
4621 } | 4621 } |
4622 | 4622 |
4623 | 4623 |
4624 void CallApiFunctionStub::Generate(MacroAssembler* masm) { | 4624 static void CallApiFunctionStubHelper(MacroAssembler* masm, |
| 4625 const ParameterCount& argc, |
| 4626 bool return_first_arg, |
| 4627 bool call_data_undefined) { |
4625 // ----------- S t a t e ------------- | 4628 // ----------- S t a t e ------------- |
4626 // -- rax : callee | 4629 // -- rax : callee |
4627 // -- rbx : call_data | 4630 // -- rbx : call_data |
4628 // -- rcx : holder | 4631 // -- rcx : holder |
4629 // -- rdx : api_function_address | 4632 // -- rdx : api_function_address |
4630 // -- rsi : context | 4633 // -- rsi : context |
4631 // -- | 4634 // -- rdi : number of arguments if argc is a register |
4632 // -- rsp[0] : return address | 4635 // -- rsp[0] : return address |
4633 // -- rsp[8] : last argument | 4636 // -- rsp[8] : last argument |
4634 // -- ... | 4637 // -- ... |
4635 // -- rsp[argc * 8] : first argument | 4638 // -- rsp[argc * 8] : first argument |
4636 // -- rsp[(argc + 1) * 8] : receiver | 4639 // -- rsp[(argc + 1) * 8] : receiver |
4637 // ----------------------------------- | 4640 // ----------------------------------- |
4638 | 4641 |
4639 Register callee = rax; | 4642 Register callee = rax; |
4640 Register call_data = rbx; | 4643 Register call_data = rbx; |
4641 Register holder = rcx; | 4644 Register holder = rcx; |
4642 Register api_function_address = rdx; | 4645 Register api_function_address = rdx; |
4643 Register return_address = rdi; | |
4644 Register context = rsi; | 4646 Register context = rsi; |
4645 | 4647 |
4646 int argc = this->argc(); | |
4647 bool is_store = this->is_store(); | |
4648 bool call_data_undefined = this->call_data_undefined(); | |
4649 | |
4650 typedef FunctionCallbackArguments FCA; | 4648 typedef FunctionCallbackArguments FCA; |
4651 | 4649 |
4652 STATIC_ASSERT(FCA::kContextSaveIndex == 6); | 4650 STATIC_ASSERT(FCA::kContextSaveIndex == 6); |
4653 STATIC_ASSERT(FCA::kCalleeIndex == 5); | 4651 STATIC_ASSERT(FCA::kCalleeIndex == 5); |
4654 STATIC_ASSERT(FCA::kDataIndex == 4); | 4652 STATIC_ASSERT(FCA::kDataIndex == 4); |
4655 STATIC_ASSERT(FCA::kReturnValueOffset == 3); | 4653 STATIC_ASSERT(FCA::kReturnValueOffset == 3); |
4656 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); | 4654 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); |
4657 STATIC_ASSERT(FCA::kIsolateIndex == 1); | 4655 STATIC_ASSERT(FCA::kIsolateIndex == 1); |
4658 STATIC_ASSERT(FCA::kHolderIndex == 0); | 4656 STATIC_ASSERT(FCA::kHolderIndex == 0); |
4659 STATIC_ASSERT(FCA::kArgsLength == 7); | 4657 STATIC_ASSERT(FCA::kArgsLength == 7); |
4660 | 4658 |
4661 __ PopReturnAddressTo(return_address); | 4659 DCHECK(argc.is_immediate() || rdi.is(argc.reg())); |
4662 | 4660 |
4663 // context save | 4661 if (kPointerSize == kInt64Size) { |
4664 __ Push(context); | 4662 // pop return address and save context |
4665 // load context from callee | 4663 __ xchgq(context, Operand(rsp, 0)); |
4666 __ movp(context, FieldOperand(callee, JSFunction::kContextOffset)); | 4664 } else { |
| 4665 // x32 handling. |
| 4666 __ PopReturnAddressTo(kScratchRegister); |
| 4667 __ Push(context); |
| 4668 __ movq(context, kScratchRegister); |
| 4669 } |
4667 | 4670 |
4668 // callee | 4671 // callee |
4669 __ Push(callee); | 4672 __ Push(callee); |
4670 | 4673 |
4671 // call data | 4674 // call data |
4672 __ Push(call_data); | 4675 __ Push(call_data); |
4673 Register scratch = call_data; | 4676 Register scratch = call_data; |
4674 if (!call_data_undefined) { | 4677 if (!call_data_undefined) { |
4675 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); | 4678 __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); |
4676 } | 4679 } |
4677 // return value | 4680 // return value |
4678 __ Push(scratch); | 4681 __ Push(scratch); |
4679 // return value default | 4682 // return value default |
4680 __ Push(scratch); | 4683 __ Push(scratch); |
4681 // isolate | 4684 // isolate |
4682 __ Move(scratch, | 4685 __ Move(scratch, ExternalReference::isolate_address(masm->isolate())); |
4683 ExternalReference::isolate_address(isolate())); | |
4684 __ Push(scratch); | 4686 __ Push(scratch); |
4685 // holder | 4687 // holder |
4686 __ Push(holder); | 4688 __ Push(holder); |
4687 | 4689 |
4688 __ movp(scratch, rsp); | 4690 __ movp(scratch, rsp); |
4689 // Push return address back on stack. | 4691 // Push return address back on stack. |
4690 __ PushReturnAddressFrom(return_address); | 4692 __ PushReturnAddressFrom(context); |
| 4693 |
| 4694 // load context from callee |
| 4695 __ movp(context, FieldOperand(callee, JSFunction::kContextOffset)); |
4691 | 4696 |
4692 // Allocate the v8::Arguments structure in the arguments' space since | 4697 // Allocate the v8::Arguments structure in the arguments' space since |
4693 // it's not controlled by GC. | 4698 // it's not controlled by GC. |
4694 const int kApiStackSpace = 4; | 4699 const int kApiStackSpace = 4; |
4695 | 4700 |
4696 __ PrepareCallApiFunction(kApiStackSpace); | 4701 __ PrepareCallApiFunction(kApiStackSpace); |
4697 | 4702 |
4698 // FunctionCallbackInfo::implicit_args_. | 4703 // FunctionCallbackInfo::implicit_args_. |
4699 __ movp(StackSpaceOperand(0), scratch); | 4704 __ movp(StackSpaceOperand(0), scratch); |
4700 __ addp(scratch, Immediate((argc + FCA::kArgsLength - 1) * kPointerSize)); | 4705 if (argc.is_immediate()) { |
4701 __ movp(StackSpaceOperand(1), scratch); // FunctionCallbackInfo::values_. | 4706 __ addp(scratch, Immediate((argc.immediate() + FCA::kArgsLength - 1) * |
4702 __ Set(StackSpaceOperand(2), argc); // FunctionCallbackInfo::length_. | 4707 kPointerSize)); |
4703 // FunctionCallbackInfo::is_construct_call_. | 4708 // FunctionCallbackInfo::values_. |
4704 __ Set(StackSpaceOperand(3), 0); | 4709 __ movp(StackSpaceOperand(1), scratch); |
| 4710 // FunctionCallbackInfo::length_. |
| 4711 __ Set(StackSpaceOperand(2), argc.immediate()); |
| 4712 // FunctionCallbackInfo::is_construct_call_. |
| 4713 __ Set(StackSpaceOperand(3), 0); |
| 4714 } else { |
| 4715 __ leap(scratch, Operand(scratch, argc.reg(), times_pointer_size, |
| 4716 (FCA::kArgsLength - 1) * kPointerSize)); |
| 4717 // FunctionCallbackInfo::values_. |
| 4718 __ movp(StackSpaceOperand(1), scratch); |
| 4719 // FunctionCallbackInfo::length_. |
| 4720 __ movp(StackSpaceOperand(2), argc.reg()); |
| 4721 // FunctionCallbackInfo::is_construct_call_. |
| 4722 __ leap(argc.reg(), Operand(argc.reg(), times_pointer_size, |
| 4723 (FCA::kArgsLength + 1) * kPointerSize)); |
| 4724 __ movp(StackSpaceOperand(3), argc.reg()); |
| 4725 } |
4705 | 4726 |
4706 #if defined(__MINGW64__) || defined(_WIN64) | 4727 #if defined(__MINGW64__) || defined(_WIN64) |
4707 Register arguments_arg = rcx; | 4728 Register arguments_arg = rcx; |
4708 Register callback_arg = rdx; | 4729 Register callback_arg = rdx; |
4709 #else | 4730 #else |
4710 Register arguments_arg = rdi; | 4731 Register arguments_arg = rdi; |
4711 Register callback_arg = rsi; | 4732 Register callback_arg = rsi; |
4712 #endif | 4733 #endif |
4713 | 4734 |
4714 // It's okay if api_function_address == callback_arg | 4735 // It's okay if api_function_address == callback_arg |
4715 // but not arguments_arg | 4736 // but not arguments_arg |
4716 DCHECK(!api_function_address.is(arguments_arg)); | 4737 DCHECK(!api_function_address.is(arguments_arg)); |
4717 | 4738 |
4718 // v8::InvocationCallback's argument. | 4739 // v8::InvocationCallback's argument. |
4719 __ leap(arguments_arg, StackSpaceOperand(0)); | 4740 __ leap(arguments_arg, StackSpaceOperand(0)); |
4720 | 4741 |
4721 ExternalReference thunk_ref = | 4742 ExternalReference thunk_ref = |
4722 ExternalReference::invoke_function_callback(isolate()); | 4743 ExternalReference::invoke_function_callback(masm->isolate()); |
4723 | 4744 |
4724 // Accessor for FunctionCallbackInfo and first js arg. | 4745 // Accessor for FunctionCallbackInfo and first js arg. |
4725 StackArgumentsAccessor args_from_rbp(rbp, FCA::kArgsLength + 1, | 4746 StackArgumentsAccessor args_from_rbp(rbp, FCA::kArgsLength + 1, |
4726 ARGUMENTS_DONT_CONTAIN_RECEIVER); | 4747 ARGUMENTS_DONT_CONTAIN_RECEIVER); |
4727 Operand context_restore_operand = args_from_rbp.GetArgumentOperand( | 4748 Operand context_restore_operand = args_from_rbp.GetArgumentOperand( |
4728 FCA::kArgsLength - FCA::kContextSaveIndex); | 4749 FCA::kArgsLength - FCA::kContextSaveIndex); |
4729 // Stores return the first js argument | 4750 Operand is_construct_call_operand = StackSpaceOperand(3); |
4730 Operand return_value_operand = args_from_rbp.GetArgumentOperand( | 4751 Operand return_value_operand = args_from_rbp.GetArgumentOperand( |
4731 is_store ? 0 : FCA::kArgsLength - FCA::kReturnValueOffset); | 4752 return_first_arg ? 0 : FCA::kArgsLength - FCA::kReturnValueOffset); |
4732 __ CallApiFunctionAndReturn( | 4753 int stack_space = 0; |
4733 api_function_address, | 4754 Operand* stack_space_operand = &is_construct_call_operand; |
4734 thunk_ref, | 4755 if (argc.is_immediate()) { |
4735 callback_arg, | 4756 stack_space = argc.immediate() + FCA::kArgsLength + 1; |
4736 argc + FCA::kArgsLength + 1, | 4757 stack_space_operand = nullptr; |
4737 return_value_operand, | 4758 } |
4738 &context_restore_operand); | 4759 __ CallApiFunctionAndReturn(api_function_address, thunk_ref, callback_arg, |
| 4760 stack_space, stack_space_operand, |
| 4761 return_value_operand, &context_restore_operand); |
4739 } | 4762 } |
4740 | 4763 |
4741 | 4764 |
| 4765 void CallApiFunctionStub::Generate(MacroAssembler* masm) { |
| 4766 // TODO(dcarney): make rax contain the function address. |
| 4767 bool call_data_undefined = this->call_data_undefined(); |
| 4768 CallApiFunctionStubHelper(masm, ParameterCount(rdi), false, |
| 4769 call_data_undefined); |
| 4770 } |
| 4771 |
| 4772 |
| 4773 void CallApiAccessorStub::Generate(MacroAssembler* masm) { |
| 4774 bool is_store = this->is_store(); |
| 4775 int argc = is_store ? 1 : 0; |
| 4776 bool call_data_undefined = this->call_data_undefined(); |
| 4777 CallApiFunctionStubHelper(masm, ParameterCount(argc), is_store, |
| 4778 call_data_undefined); |
| 4779 } |
| 4780 |
| 4781 |
4742 void CallApiGetterStub::Generate(MacroAssembler* masm) { | 4782 void CallApiGetterStub::Generate(MacroAssembler* masm) { |
4743 // ----------- S t a t e ------------- | 4783 // ----------- S t a t e ------------- |
4744 // -- rsp[0] : return address | 4784 // -- rsp[0] : return address |
4745 // -- rsp[8] : name | 4785 // -- rsp[8] : name |
4746 // -- rsp[16 - kArgsLength*8] : PropertyCallbackArguments object | 4786 // -- rsp[16 - kArgsLength*8] : PropertyCallbackArguments object |
4747 // -- ... | 4787 // -- ... |
4748 // -- r8 : api_function_address | 4788 // -- r8 : api_function_address |
4749 // ----------------------------------- | 4789 // ----------------------------------- |
4750 | 4790 |
4751 #if defined(__MINGW64__) || defined(_WIN64) | 4791 #if defined(__MINGW64__) || defined(_WIN64) |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4785 // It's okay if api_function_address == getter_arg | 4825 // It's okay if api_function_address == getter_arg |
4786 // but not accessor_info_arg or name_arg | 4826 // but not accessor_info_arg or name_arg |
4787 DCHECK(!api_function_address.is(accessor_info_arg) && | 4827 DCHECK(!api_function_address.is(accessor_info_arg) && |
4788 !api_function_address.is(name_arg)); | 4828 !api_function_address.is(name_arg)); |
4789 | 4829 |
4790 // The name handler is counted as an argument. | 4830 // The name handler is counted as an argument. |
4791 StackArgumentsAccessor args(rbp, PropertyCallbackArguments::kArgsLength); | 4831 StackArgumentsAccessor args(rbp, PropertyCallbackArguments::kArgsLength); |
4792 Operand return_value_operand = args.GetArgumentOperand( | 4832 Operand return_value_operand = args.GetArgumentOperand( |
4793 PropertyCallbackArguments::kArgsLength - 1 - | 4833 PropertyCallbackArguments::kArgsLength - 1 - |
4794 PropertyCallbackArguments::kReturnValueOffset); | 4834 PropertyCallbackArguments::kReturnValueOffset); |
4795 __ CallApiFunctionAndReturn(api_function_address, | 4835 __ CallApiFunctionAndReturn(api_function_address, thunk_ref, getter_arg, |
4796 thunk_ref, | 4836 kStackSpace, nullptr, return_value_operand, NULL); |
4797 getter_arg, | |
4798 kStackSpace, | |
4799 return_value_operand, | |
4800 NULL); | |
4801 } | 4837 } |
4802 | 4838 |
4803 | 4839 |
4804 #undef __ | 4840 #undef __ |
4805 | 4841 |
4806 } } // namespace v8::internal | 4842 } } // namespace v8::internal |
4807 | 4843 |
4808 #endif // V8_TARGET_ARCH_X64 | 4844 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |