OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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_IA32 | 7 #if V8_TARGET_ARCH_IA32 |
8 | 8 |
9 #include "src/base/bits.h" | 9 #include "src/base/bits.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 4663 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4674 Label fast_elements_case; | 4674 Label fast_elements_case; |
4675 __ cmp(ecx, Immediate(FAST_ELEMENTS)); | 4675 __ cmp(ecx, Immediate(FAST_ELEMENTS)); |
4676 __ j(equal, &fast_elements_case); | 4676 __ j(equal, &fast_elements_case); |
4677 GenerateCase(masm, FAST_HOLEY_ELEMENTS); | 4677 GenerateCase(masm, FAST_HOLEY_ELEMENTS); |
4678 | 4678 |
4679 __ bind(&fast_elements_case); | 4679 __ bind(&fast_elements_case); |
4680 GenerateCase(masm, FAST_ELEMENTS); | 4680 GenerateCase(masm, FAST_ELEMENTS); |
4681 } | 4681 } |
4682 | 4682 |
4683 | 4683 |
4684 void CallApiFunctionStub::Generate(MacroAssembler* masm) { | 4684 static void CallApiFunctionStubHelper(MacroAssembler* masm, |
| 4685 const ParameterCount& argc, |
| 4686 bool return_first_arg, |
| 4687 bool call_data_undefined) { |
4685 // ----------- S t a t e ------------- | 4688 // ----------- S t a t e ------------- |
4686 // -- eax : callee | 4689 // -- eax : callee |
4687 // -- ebx : call_data | 4690 // -- ebx : call_data |
4688 // -- ecx : holder | 4691 // -- ecx : holder |
4689 // -- edx : api_function_address | 4692 // -- edx : api_function_address |
4690 // -- esi : context | 4693 // -- esi : context |
| 4694 // -- edi : number of arguments if argc is a register |
4691 // -- | 4695 // -- |
4692 // -- esp[0] : return address | 4696 // -- esp[0] : return address |
4693 // -- esp[4] : last argument | 4697 // -- esp[4] : last argument |
4694 // -- ... | 4698 // -- ... |
4695 // -- esp[argc * 4] : first argument | 4699 // -- esp[argc * 4] : first argument |
4696 // -- esp[(argc + 1) * 4] : receiver | 4700 // -- esp[(argc + 1) * 4] : receiver |
4697 // ----------------------------------- | 4701 // ----------------------------------- |
4698 | 4702 |
4699 Register callee = eax; | 4703 Register callee = eax; |
4700 Register call_data = ebx; | 4704 Register call_data = ebx; |
4701 Register holder = ecx; | 4705 Register holder = ecx; |
4702 Register api_function_address = edx; | 4706 Register api_function_address = edx; |
4703 Register return_address = edi; | |
4704 Register context = esi; | 4707 Register context = esi; |
4705 | 4708 |
4706 int argc = this->argc(); | |
4707 bool is_store = this->is_store(); | |
4708 bool call_data_undefined = this->call_data_undefined(); | |
4709 | |
4710 typedef FunctionCallbackArguments FCA; | 4709 typedef FunctionCallbackArguments FCA; |
4711 | 4710 |
4712 STATIC_ASSERT(FCA::kContextSaveIndex == 6); | 4711 STATIC_ASSERT(FCA::kContextSaveIndex == 6); |
4713 STATIC_ASSERT(FCA::kCalleeIndex == 5); | 4712 STATIC_ASSERT(FCA::kCalleeIndex == 5); |
4714 STATIC_ASSERT(FCA::kDataIndex == 4); | 4713 STATIC_ASSERT(FCA::kDataIndex == 4); |
4715 STATIC_ASSERT(FCA::kReturnValueOffset == 3); | 4714 STATIC_ASSERT(FCA::kReturnValueOffset == 3); |
4716 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); | 4715 STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); |
4717 STATIC_ASSERT(FCA::kIsolateIndex == 1); | 4716 STATIC_ASSERT(FCA::kIsolateIndex == 1); |
4718 STATIC_ASSERT(FCA::kHolderIndex == 0); | 4717 STATIC_ASSERT(FCA::kHolderIndex == 0); |
4719 STATIC_ASSERT(FCA::kArgsLength == 7); | 4718 STATIC_ASSERT(FCA::kArgsLength == 7); |
4720 | 4719 |
4721 __ pop(return_address); | 4720 DCHECK(argc.is_immediate() || edi.is(argc.reg())); |
4722 | 4721 |
4723 // context save | 4722 // pop return address and save context |
4724 __ push(context); | 4723 __ xchg(context, Operand(esp, 0)); |
4725 // load context from callee | |
4726 __ mov(context, FieldOperand(callee, JSFunction::kContextOffset)); | |
4727 | 4724 |
4728 // callee | 4725 // callee |
4729 __ push(callee); | 4726 __ push(callee); |
4730 | 4727 |
4731 // call data | 4728 // call data |
4732 __ push(call_data); | 4729 __ push(call_data); |
4733 | 4730 |
4734 Register scratch = call_data; | 4731 Register scratch = call_data; |
4735 if (!call_data_undefined) { | 4732 if (!call_data_undefined) { |
4736 // return value | 4733 // return value |
4737 __ push(Immediate(isolate()->factory()->undefined_value())); | 4734 __ push(Immediate(masm->isolate()->factory()->undefined_value())); |
4738 // return value default | 4735 // return value default |
4739 __ push(Immediate(isolate()->factory()->undefined_value())); | 4736 __ push(Immediate(masm->isolate()->factory()->undefined_value())); |
4740 } else { | 4737 } else { |
4741 // return value | 4738 // return value |
4742 __ push(scratch); | 4739 __ push(scratch); |
4743 // return value default | 4740 // return value default |
4744 __ push(scratch); | 4741 __ push(scratch); |
4745 } | 4742 } |
4746 // isolate | 4743 // isolate |
4747 __ push(Immediate(reinterpret_cast<int>(isolate()))); | 4744 __ push(Immediate(reinterpret_cast<int>(masm->isolate()))); |
4748 // holder | 4745 // holder |
4749 __ push(holder); | 4746 __ push(holder); |
4750 | 4747 |
4751 __ mov(scratch, esp); | 4748 __ mov(scratch, esp); |
4752 | 4749 |
4753 // return address | 4750 // push return address |
4754 __ push(return_address); | 4751 __ push(context); |
| 4752 |
| 4753 // load context from callee |
| 4754 __ mov(context, FieldOperand(callee, JSFunction::kContextOffset)); |
4755 | 4755 |
4756 // API function gets reference to the v8::Arguments. If CPU profiler | 4756 // API function gets reference to the v8::Arguments. If CPU profiler |
4757 // is enabled wrapper function will be called and we need to pass | 4757 // is enabled wrapper function will be called and we need to pass |
4758 // address of the callback as additional parameter, always allocate | 4758 // address of the callback as additional parameter, always allocate |
4759 // space for it. | 4759 // space for it. |
4760 const int kApiArgc = 1 + 1; | 4760 const int kApiArgc = 1 + 1; |
4761 | 4761 |
4762 // Allocate the v8::Arguments structure in the arguments' space since | 4762 // Allocate the v8::Arguments structure in the arguments' space since |
4763 // it's not controlled by GC. | 4763 // it's not controlled by GC. |
4764 const int kApiStackSpace = 4; | 4764 const int kApiStackSpace = 4; |
4765 | 4765 |
4766 __ PrepareCallApiFunction(kApiArgc + kApiStackSpace); | 4766 __ PrepareCallApiFunction(kApiArgc + kApiStackSpace); |
4767 | 4767 |
4768 // FunctionCallbackInfo::implicit_args_. | 4768 // FunctionCallbackInfo::implicit_args_. |
4769 __ mov(ApiParameterOperand(2), scratch); | 4769 __ mov(ApiParameterOperand(2), scratch); |
4770 __ add(scratch, Immediate((argc + FCA::kArgsLength - 1) * kPointerSize)); | 4770 if (argc.is_immediate()) { |
4771 // FunctionCallbackInfo::values_. | 4771 __ add(scratch, |
4772 __ mov(ApiParameterOperand(3), scratch); | 4772 Immediate((argc.immediate() + FCA::kArgsLength - 1) * kPointerSize)); |
4773 // FunctionCallbackInfo::length_. | 4773 // FunctionCallbackInfo::values_. |
4774 __ Move(ApiParameterOperand(4), Immediate(argc)); | 4774 __ mov(ApiParameterOperand(3), scratch); |
4775 // FunctionCallbackInfo::is_construct_call_. | 4775 // FunctionCallbackInfo::length_. |
4776 __ Move(ApiParameterOperand(5), Immediate(0)); | 4776 __ Move(ApiParameterOperand(4), Immediate(argc.immediate())); |
| 4777 // FunctionCallbackInfo::is_construct_call_. |
| 4778 __ Move(ApiParameterOperand(5), Immediate(0)); |
| 4779 } else { |
| 4780 __ lea(scratch, Operand(scratch, argc.reg(), times_pointer_size, |
| 4781 (FCA::kArgsLength - 1) * kPointerSize)); |
| 4782 // FunctionCallbackInfo::values_. |
| 4783 __ mov(ApiParameterOperand(3), scratch); |
| 4784 // FunctionCallbackInfo::length_. |
| 4785 __ mov(ApiParameterOperand(4), argc.reg()); |
| 4786 // FunctionCallbackInfo::is_construct_call_. |
| 4787 __ lea(argc.reg(), Operand(argc.reg(), times_pointer_size, |
| 4788 (FCA::kArgsLength + 1) * kPointerSize)); |
| 4789 __ mov(ApiParameterOperand(5), argc.reg()); |
| 4790 } |
4777 | 4791 |
4778 // v8::InvocationCallback's argument. | 4792 // v8::InvocationCallback's argument. |
4779 __ lea(scratch, ApiParameterOperand(2)); | 4793 __ lea(scratch, ApiParameterOperand(2)); |
4780 __ mov(ApiParameterOperand(0), scratch); | 4794 __ mov(ApiParameterOperand(0), scratch); |
4781 | 4795 |
4782 ExternalReference thunk_ref = | 4796 ExternalReference thunk_ref = |
4783 ExternalReference::invoke_function_callback(isolate()); | 4797 ExternalReference::invoke_function_callback(masm->isolate()); |
4784 | 4798 |
4785 Operand context_restore_operand(ebp, | 4799 Operand context_restore_operand(ebp, |
4786 (2 + FCA::kContextSaveIndex) * kPointerSize); | 4800 (2 + FCA::kContextSaveIndex) * kPointerSize); |
4787 // Stores return the first js argument | 4801 // Stores return the first js argument |
4788 int return_value_offset = 0; | 4802 int return_value_offset = 0; |
4789 if (is_store) { | 4803 if (return_first_arg) { |
4790 return_value_offset = 2 + FCA::kArgsLength; | 4804 return_value_offset = 2 + FCA::kArgsLength; |
4791 } else { | 4805 } else { |
4792 return_value_offset = 2 + FCA::kReturnValueOffset; | 4806 return_value_offset = 2 + FCA::kReturnValueOffset; |
4793 } | 4807 } |
4794 Operand return_value_operand(ebp, return_value_offset * kPointerSize); | 4808 Operand return_value_operand(ebp, return_value_offset * kPointerSize); |
4795 __ CallApiFunctionAndReturn(api_function_address, | 4809 int stack_space = 0; |
4796 thunk_ref, | 4810 Operand is_construct_call_operand = ApiParameterOperand(5); |
4797 ApiParameterOperand(1), | 4811 Operand* stack_space_operand = &is_construct_call_operand; |
4798 argc + FCA::kArgsLength + 1, | 4812 if (argc.is_immediate()) { |
4799 return_value_operand, | 4813 stack_space = argc.immediate() + FCA::kArgsLength + 1; |
4800 &context_restore_operand); | 4814 stack_space_operand = nullptr; |
| 4815 } |
| 4816 __ CallApiFunctionAndReturn( |
| 4817 api_function_address, thunk_ref, ApiParameterOperand(1), stack_space, |
| 4818 stack_space_operand, return_value_operand, &context_restore_operand); |
4801 } | 4819 } |
4802 | 4820 |
4803 | 4821 |
| 4822 void CallApiFunctionStub::Generate(MacroAssembler* masm) { |
| 4823 // TODO(dcarney): make eax contain the function address. |
| 4824 bool call_data_undefined = this->call_data_undefined(); |
| 4825 CallApiFunctionStubHelper(masm, ParameterCount(edi), false, |
| 4826 call_data_undefined); |
| 4827 } |
| 4828 |
| 4829 |
| 4830 void CallApiAccessorStub::Generate(MacroAssembler* masm) { |
| 4831 bool is_store = this->is_store(); |
| 4832 int argc = is_store ? 1 : 0; |
| 4833 bool call_data_undefined = this->call_data_undefined(); |
| 4834 CallApiFunctionStubHelper(masm, ParameterCount(argc), is_store, |
| 4835 call_data_undefined); |
| 4836 } |
| 4837 |
| 4838 |
4804 void CallApiGetterStub::Generate(MacroAssembler* masm) { | 4839 void CallApiGetterStub::Generate(MacroAssembler* masm) { |
4805 // ----------- S t a t e ------------- | 4840 // ----------- S t a t e ------------- |
4806 // -- esp[0] : return address | 4841 // -- esp[0] : return address |
4807 // -- esp[4] : name | 4842 // -- esp[4] : name |
4808 // -- esp[8 - kArgsLength*4] : PropertyCallbackArguments object | 4843 // -- esp[8 - kArgsLength*4] : PropertyCallbackArguments object |
4809 // -- ... | 4844 // -- ... |
4810 // -- edx : api_function_address | 4845 // -- edx : api_function_address |
4811 // ----------------------------------- | 4846 // ----------------------------------- |
4812 DCHECK(edx.is(ApiGetterDescriptor::function_address())); | 4847 DCHECK(edx.is(ApiGetterDescriptor::function_address())); |
4813 | 4848 |
(...skipping 11 matching lines...) Expand all Loading... |
4825 __ lea(scratch, Operand(esp, 1 * kPointerSize)); | 4860 __ lea(scratch, Operand(esp, 1 * kPointerSize)); |
4826 | 4861 |
4827 __ PrepareCallApiFunction(kApiArgc); | 4862 __ PrepareCallApiFunction(kApiArgc); |
4828 __ mov(ApiParameterOperand(0), scratch); // name. | 4863 __ mov(ApiParameterOperand(0), scratch); // name. |
4829 __ add(scratch, Immediate(kPointerSize)); | 4864 __ add(scratch, Immediate(kPointerSize)); |
4830 __ mov(ApiParameterOperand(1), scratch); // arguments pointer. | 4865 __ mov(ApiParameterOperand(1), scratch); // arguments pointer. |
4831 | 4866 |
4832 ExternalReference thunk_ref = | 4867 ExternalReference thunk_ref = |
4833 ExternalReference::invoke_accessor_getter_callback(isolate()); | 4868 ExternalReference::invoke_accessor_getter_callback(isolate()); |
4834 | 4869 |
4835 __ CallApiFunctionAndReturn(api_function_address, | 4870 __ CallApiFunctionAndReturn(api_function_address, thunk_ref, |
4836 thunk_ref, | 4871 ApiParameterOperand(2), kStackSpace, nullptr, |
4837 ApiParameterOperand(2), | 4872 Operand(ebp, 7 * kPointerSize), NULL); |
4838 kStackSpace, | |
4839 Operand(ebp, 7 * kPointerSize), | |
4840 NULL); | |
4841 } | 4873 } |
4842 | 4874 |
4843 | 4875 |
4844 #undef __ | 4876 #undef __ |
4845 | 4877 |
4846 } } // namespace v8::internal | 4878 } } // namespace v8::internal |
4847 | 4879 |
4848 #endif // V8_TARGET_ARCH_IA32 | 4880 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |