From f7e92b037bdcfb9b8108b86f938e700e6e0a8c12 Mon Sep 17 00:00:00 2001 From: "chunyang.dai" Date: Sun, 18 Jan 2015 21:06:29 -0800 Subject: [PATCH] X87: split api call stubs into accessor and function call stubs port 6950ead0b0a8373441dc8f8d3b2c316e82549ce9 original commit message: split api call stubs into accessor and function call stubs BUG= Review URL: https://codereview.chromium.org/860593002 Cr-Commit-Position: refs/heads/master@{#26122} --- src/ic/x87/handler-compiler-x87.cc | 15 ++-- src/x87/code-stubs-x87.cc | 106 +++++++++++++++++---------- src/x87/interface-descriptors-x87.cc | 21 ++++++ src/x87/macro-assembler-x87.cc | 21 ++++-- src/x87/macro-assembler-x87.h | 4 +- 5 files changed, 113 insertions(+), 54 deletions(-) diff --git a/src/ic/x87/handler-compiler-x87.cc b/src/ic/x87/handler-compiler-x87.cc index f3c87448c..0540fafb2 100644 --- a/src/ic/x87/handler-compiler-x87.cc +++ b/src/ic/x87/handler-compiler-x87.cc @@ -137,20 +137,19 @@ void NamedLoadHandlerCompiler::GenerateLoadFunctionPrototype( // This function uses push() to generate smaller, faster code than // the version above. It is an optimization that should will be removed // when api call ICs are generated in hydrogen. -void PropertyHandlerCompiler::GenerateFastApiCall( +void PropertyHandlerCompiler::GenerateApiAccessorCall( MacroAssembler* masm, const CallOptimization& optimization, Handle receiver_map, Register receiver, Register scratch_in, - bool is_store, int argc, Register* values) { + bool is_store, Register store_parameter) { // Copy return value. __ pop(scratch_in); // receiver __ push(receiver); // Write the arguments to stack frame. - for (int i = 0; i < argc; i++) { - Register arg = values[argc - 1 - i]; - DCHECK(!receiver.is(arg)); - DCHECK(!scratch_in.is(arg)); - __ push(arg); + if (is_store) { + DCHECK(!receiver.is(store_parameter)); + DCHECK(!scratch_in.is(store_parameter)); + __ push(store_parameter); } __ push(scratch_in); // Stack now matches JSFunction abi. @@ -204,7 +203,7 @@ void PropertyHandlerCompiler::GenerateFastApiCall( __ mov(api_function_address, Immediate(function_address)); // Jump to stub. - CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc); + CallApiAccessorStub stub(isolate, is_store, call_data_undefined); __ TailCallStub(&stub); } diff --git a/src/x87/code-stubs-x87.cc b/src/x87/code-stubs-x87.cc index 1264dd9b2..fd97a144a 100644 --- a/src/x87/code-stubs-x87.cc +++ b/src/x87/code-stubs-x87.cc @@ -4341,13 +4341,17 @@ void InternalArrayConstructorStub::Generate(MacroAssembler* masm) { } -void CallApiFunctionStub::Generate(MacroAssembler* masm) { +static void CallApiFunctionStubHelper(MacroAssembler* masm, + const ParameterCount& argc, + bool return_first_arg, + bool call_data_undefined) { // ----------- S t a t e ------------- // -- eax : callee // -- ebx : call_data // -- ecx : holder // -- edx : api_function_address // -- esi : context + // -- edi : number of arguments if argc is a register // -- // -- esp[0] : return address // -- esp[4] : last argument @@ -4360,13 +4364,8 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) { Register call_data = ebx; Register holder = ecx; Register api_function_address = edx; - Register return_address = edi; Register context = esi; - int argc = this->argc(); - bool is_store = this->is_store(); - bool call_data_undefined = this->call_data_undefined(); - typedef FunctionCallbackArguments FCA; STATIC_ASSERT(FCA::kContextSaveIndex == 6); @@ -4378,12 +4377,10 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) { STATIC_ASSERT(FCA::kHolderIndex == 0); STATIC_ASSERT(FCA::kArgsLength == 7); - __ pop(return_address); + DCHECK(argc.is_immediate() || edi.is(argc.reg())); - // context save - __ push(context); - // load context from callee - __ mov(context, FieldOperand(callee, JSFunction::kContextOffset)); + // pop return address and save context + __ xchg(context, Operand(esp, 0)); // callee __ push(callee); @@ -4394,9 +4391,9 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) { Register scratch = call_data; if (!call_data_undefined) { // return value - __ push(Immediate(isolate()->factory()->undefined_value())); + __ push(Immediate(masm->isolate()->factory()->undefined_value())); // return value default - __ push(Immediate(isolate()->factory()->undefined_value())); + __ push(Immediate(masm->isolate()->factory()->undefined_value())); } else { // return value __ push(scratch); @@ -4404,14 +4401,17 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) { __ push(scratch); } // isolate - __ push(Immediate(reinterpret_cast(isolate()))); + __ push(Immediate(reinterpret_cast(masm->isolate()))); // holder __ push(holder); __ mov(scratch, esp); - // return address - __ push(return_address); + // push return address + __ push(context); + + // load context from callee + __ mov(context, FieldOperand(callee, JSFunction::kContextOffset)); // API function gets reference to the v8::Arguments. If CPU profiler // is enabled wrapper function will be called and we need to pass @@ -4427,37 +4427,72 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) { // FunctionCallbackInfo::implicit_args_. __ mov(ApiParameterOperand(2), scratch); - __ add(scratch, Immediate((argc + FCA::kArgsLength - 1) * kPointerSize)); - // FunctionCallbackInfo::values_. - __ mov(ApiParameterOperand(3), scratch); - // FunctionCallbackInfo::length_. - __ Move(ApiParameterOperand(4), Immediate(argc)); - // FunctionCallbackInfo::is_construct_call_. - __ Move(ApiParameterOperand(5), Immediate(0)); + if (argc.is_immediate()) { + __ add(scratch, + Immediate((argc.immediate() + FCA::kArgsLength - 1) * kPointerSize)); + // FunctionCallbackInfo::values_. + __ mov(ApiParameterOperand(3), scratch); + // FunctionCallbackInfo::length_. + __ Move(ApiParameterOperand(4), Immediate(argc.immediate())); + // FunctionCallbackInfo::is_construct_call_. + __ Move(ApiParameterOperand(5), Immediate(0)); + } else { + __ lea(scratch, Operand(scratch, argc.reg(), times_pointer_size, + (FCA::kArgsLength - 1) * kPointerSize)); + // FunctionCallbackInfo::values_. + __ mov(ApiParameterOperand(3), scratch); + // FunctionCallbackInfo::length_. + __ mov(ApiParameterOperand(4), argc.reg()); + // FunctionCallbackInfo::is_construct_call_. + __ lea(argc.reg(), Operand(argc.reg(), times_pointer_size, + (FCA::kArgsLength + 1) * kPointerSize)); + __ mov(ApiParameterOperand(5), argc.reg()); + } // v8::InvocationCallback's argument. __ lea(scratch, ApiParameterOperand(2)); __ mov(ApiParameterOperand(0), scratch); ExternalReference thunk_ref = - ExternalReference::invoke_function_callback(isolate()); + ExternalReference::invoke_function_callback(masm->isolate()); Operand context_restore_operand(ebp, (2 + FCA::kContextSaveIndex) * kPointerSize); // Stores return the first js argument int return_value_offset = 0; - if (is_store) { + if (return_first_arg) { return_value_offset = 2 + FCA::kArgsLength; } else { return_value_offset = 2 + FCA::kReturnValueOffset; } Operand return_value_operand(ebp, return_value_offset * kPointerSize); - __ CallApiFunctionAndReturn(api_function_address, - thunk_ref, - ApiParameterOperand(1), - argc + FCA::kArgsLength + 1, - return_value_operand, - &context_restore_operand); + int stack_space = 0; + Operand is_construct_call_operand = ApiParameterOperand(5); + Operand* stack_space_operand = &is_construct_call_operand; + if (argc.is_immediate()) { + stack_space = argc.immediate() + FCA::kArgsLength + 1; + stack_space_operand = nullptr; + } + __ CallApiFunctionAndReturn( + api_function_address, thunk_ref, ApiParameterOperand(1), stack_space, + stack_space_operand, return_value_operand, &context_restore_operand); +} + + +void CallApiFunctionStub::Generate(MacroAssembler* masm) { + // TODO(dcarney): make eax contain the function address. + bool call_data_undefined = this->call_data_undefined(); + CallApiFunctionStubHelper(masm, ParameterCount(edi), false, + call_data_undefined); +} + + +void CallApiAccessorStub::Generate(MacroAssembler* masm) { + bool is_store = this->is_store(); + int argc = is_store ? 1 : 0; + bool call_data_undefined = this->call_data_undefined(); + CallApiFunctionStubHelper(masm, ParameterCount(argc), is_store, + call_data_undefined); } @@ -4492,12 +4527,9 @@ void CallApiGetterStub::Generate(MacroAssembler* masm) { ExternalReference thunk_ref = ExternalReference::invoke_accessor_getter_callback(isolate()); - __ CallApiFunctionAndReturn(api_function_address, - thunk_ref, - ApiParameterOperand(2), - kStackSpace, - Operand(ebp, 7 * kPointerSize), - NULL); + __ CallApiFunctionAndReturn(api_function_address, thunk_ref, + ApiParameterOperand(2), kStackSpace, nullptr, + Operand(ebp, 7 * kPointerSize), NULL); } diff --git a/src/x87/interface-descriptors-x87.cc b/src/x87/interface-descriptors-x87.cc index 26ce4dcb8..b2c4b6b5c 100644 --- a/src/x87/interface-descriptors-x87.cc +++ b/src/x87/interface-descriptors-x87.cc @@ -294,6 +294,27 @@ void ArgumentAdaptorDescriptor::Initialize(CallInterfaceDescriptorData* data) { void ApiFunctionDescriptor::Initialize(CallInterfaceDescriptorData* data) { + Register registers[] = { + esi, // context + eax, // callee + ebx, // call_data + ecx, // holder + edx, // api_function_address + edi, // actual number of arguments + }; + Representation representations[] = { + Representation::Tagged(), // context + Representation::Tagged(), // callee + Representation::Tagged(), // call_data + Representation::Tagged(), // holder + Representation::External(), // api_function_address + Representation::Integer32(), // actual number of arguments + }; + data->Initialize(arraysize(registers), registers, representations); +} + + +void ApiAccessorDescriptor::Initialize(CallInterfaceDescriptorData* data) { Register registers[] = { esi, // context eax, // callee diff --git a/src/x87/macro-assembler-x87.cc b/src/x87/macro-assembler-x87.cc index 96a05908a..2cf6afd23 100644 --- a/src/x87/macro-assembler-x87.cc +++ b/src/x87/macro-assembler-x87.cc @@ -2062,12 +2062,9 @@ void MacroAssembler::PrepareCallApiFunction(int argc) { void MacroAssembler::CallApiFunctionAndReturn( - Register function_address, - ExternalReference thunk_ref, - Operand thunk_last_arg, - int stack_space, - Operand return_value_operand, - Operand* context_restore_operand) { + Register function_address, ExternalReference thunk_ref, + Operand thunk_last_arg, int stack_space, Operand* stack_space_operand, + Operand return_value_operand, Operand* context_restore_operand) { ExternalReference next_address = ExternalReference::handle_scope_next_address(isolate()); ExternalReference limit_address = @@ -2186,8 +2183,18 @@ void MacroAssembler::CallApiFunctionAndReturn( if (restore_context) { mov(esi, *context_restore_operand); } + if (stack_space_operand != nullptr) { + mov(ebx, *stack_space_operand); + } LeaveApiExitFrame(!restore_context); - ret(stack_space * kPointerSize); + if (stack_space_operand != nullptr) { + DCHECK_EQ(0, stack_space); + pop(ecx); + add(esp, ebx); + jmp(ecx); + } else { + ret(stack_space * kPointerSize); + } bind(&promote_scheduled_exception); { diff --git a/src/x87/macro-assembler-x87.h b/src/x87/macro-assembler-x87.h index b7972651d..4a2f8321c 100644 --- a/src/x87/macro-assembler-x87.h +++ b/src/x87/macro-assembler-x87.h @@ -768,8 +768,8 @@ class MacroAssembler: public Assembler { // stack_space * kPointerSize (GCed). void CallApiFunctionAndReturn(Register function_address, ExternalReference thunk_ref, - Operand thunk_last_arg, - int stack_space, + Operand thunk_last_arg, int stack_space, + Operand* stack_space_operand, Operand return_value_operand, Operand* context_restore_operand); -- 2.34.1