From e5a534f389d01bc716264807070a2df7088c6847 Mon Sep 17 00:00:00 2001 From: "palfia@homejinni.com" Date: Tue, 28 Jan 2014 01:35:20 +0000 Subject: [PATCH] MIPS: stub fast api calls Port r18847 (c920fc50) BUG= R=plind44@gmail.com Review URL: https://codereview.chromium.org/145583012 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18863 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/mips/code-stubs-mips.cc | 103 +++++++++++++++++++++ src/mips/macro-assembler-mips.cc | 42 ++++----- src/mips/macro-assembler-mips.h | 3 +- src/mips/stub-cache-mips.cc | 149 ++++++++----------------------- 4 files changed, 160 insertions(+), 137 deletions(-) diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc index 8651b691a..ab1b90ada 100644 --- a/src/mips/code-stubs-mips.cc +++ b/src/mips/code-stubs-mips.cc @@ -5692,6 +5692,109 @@ void InternalArrayConstructorStub::Generate(MacroAssembler* masm) { } +void CallApiFunctionStub::Generate(MacroAssembler* masm) { + // ----------- S t a t e ------------- + // -- a0 : callee + // -- t0 : call_data + // -- a2 : holder + // -- a3 : api_function_address + // -- a1 : thunk_arg + // -- cp : context + // -- + // -- sp[0] : last argument + // -- ... + // -- sp[(argc - 1)* 4] : first argument + // -- sp[argc * 4] : receiver + // ----------------------------------- + + Register callee = a0; + Register call_data = t0; + Register holder = a2; + Register api_function_address = a3; + Register thunk_arg = a1; + Register context = cp; + + int argc = ArgumentBits::decode(bit_field_); + bool restore_context = RestoreContextBits::decode(bit_field_); + bool call_data_undefined = CallDataUndefinedBits::decode(bit_field_); + + typedef FunctionCallbackArguments FCA; + + STATIC_ASSERT(FCA::kContextSaveIndex == 6); + STATIC_ASSERT(FCA::kCalleeIndex == 5); + STATIC_ASSERT(FCA::kDataIndex == 4); + STATIC_ASSERT(FCA::kReturnValueOffset == 3); + STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); + STATIC_ASSERT(FCA::kIsolateIndex == 1); + STATIC_ASSERT(FCA::kHolderIndex == 0); + STATIC_ASSERT(FCA::kArgsLength == 7); + + Isolate* isolate = masm->isolate(); + + // Save context, callee and call data. + __ Push(context, callee, call_data); + // Load context from callee. + __ lw(context, FieldMemOperand(callee, JSFunction::kContextOffset)); + + Register scratch = call_data; + if (!call_data_undefined) { + __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex); + } + // Push return value and default return value. + __ Push(scratch, scratch); + __ li(scratch, + Operand(ExternalReference::isolate_address(isolate))); + // Push isolate and holder. + __ Push(scratch, holder); + + // Prepare arguments. + __ mov(scratch, sp); + + // Allocate the v8::Arguments structure in the arguments' space since + // it's not controlled by GC. + const int kApiStackSpace = 4; + + FrameScope frame_scope(masm, StackFrame::MANUAL); + __ EnterExitFrame(false, kApiStackSpace); + + ASSERT(!thunk_arg.is(a0) && !api_function_address.is(a0) && !scratch.is(a0)); + // a0 = FunctionCallbackInfo& + // Arguments is after the return address. + __ Addu(a0, sp, Operand(1 * kPointerSize)); + // FunctionCallbackInfo::implicit_args_ + __ sw(scratch, MemOperand(a0, 0 * kPointerSize)); + // FunctionCallbackInfo::values_ + __ Addu(at, scratch, Operand((FCA::kArgsLength - 1 + argc) * kPointerSize)); + __ sw(at, MemOperand(a0, 1 * kPointerSize)); + // FunctionCallbackInfo::length_ = argc + __ li(at, Operand(argc)); + __ sw(at, MemOperand(a0, 2 * kPointerSize)); + // FunctionCallbackInfo::is_construct_call = 0 + __ sw(zero_reg, MemOperand(a0, 3 * kPointerSize)); + + const int kStackUnwindSpace = argc + FCA::kArgsLength + 1; + Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback); + ExternalReference::Type thunk_type = ExternalReference::PROFILING_API_CALL; + ApiFunction thunk_fun(thunk_address); + ExternalReference thunk_ref = ExternalReference(&thunk_fun, thunk_type, + masm->isolate()); + + AllowExternalCallThatCantCauseGC scope(masm); + MemOperand context_restore_operand( + fp, (2 + FCA::kContextSaveIndex) * kPointerSize); + MemOperand return_value_operand(fp, + (2 + FCA::kReturnValueOffset) * kPointerSize); + + __ CallApiFunctionAndReturn(api_function_address, + thunk_ref, + thunk_arg, + kStackUnwindSpace, + return_value_operand, + restore_context ? + &context_restore_operand : NULL); +} + + #undef __ } } // namespace v8::internal diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc index f8c037ded..517344857 100644 --- a/src/mips/macro-assembler-mips.cc +++ b/src/mips/macro-assembler-mips.cc @@ -3872,8 +3872,7 @@ static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { void MacroAssembler::CallApiFunctionAndReturn( - ExternalReference function, - Address function_address, + Register function_address, ExternalReference thunk_ref, Register thunk_last_arg, int stack_space, @@ -3889,6 +3888,26 @@ void MacroAssembler::CallApiFunctionAndReturn( ExternalReference::handle_scope_level_address(isolate()), next_address); + ASSERT(function_address.is(a3)); + ASSERT(thunk_last_arg.is(a1) || thunk_last_arg.is(a2)); + + Label profiler_disabled; + Label end_profiler_check; + bool* is_profiling_flag = + isolate()->cpu_profiler()->is_profiling_address(); + STATIC_ASSERT(sizeof(*is_profiling_flag) == 1); + li(t9, reinterpret_cast(is_profiling_flag)); + lb(t9, MemOperand(t9, 0)); + Branch(&profiler_disabled, eq, t9, Operand(zero_reg)); + + // Additional parameter is the address of the actual callback. + li(t9, Operand(thunk_ref)); + jmp(&end_profiler_check); + + bind(&profiler_disabled); + mov(t9, function_address); + bind(&end_profiler_check); + // Allocate HandleScope in callee-save registers. li(s3, Operand(next_address)); lw(s0, MemOperand(s3, kNextOffset)); @@ -3906,25 +3925,6 @@ void MacroAssembler::CallApiFunctionAndReturn( PopSafepointRegisters(); } - Label profiler_disabled; - Label end_profiler_check; - bool* is_profiling_flag = - isolate()->cpu_profiler()->is_profiling_address(); - STATIC_ASSERT(sizeof(*is_profiling_flag) == 1); - li(t9, reinterpret_cast(is_profiling_flag)); - lb(t9, MemOperand(t9, 0)); - beq(t9, zero_reg, &profiler_disabled); - - // Third parameter is the address of the actual getter function. - li(thunk_last_arg, reinterpret_cast(function_address)); - li(t9, Operand(thunk_ref)); - jmp(&end_profiler_check); - - bind(&profiler_disabled); - li(t9, Operand(function)); - - bind(&end_profiler_check); - // Native call returns to the DirectCEntry stub which redirects to the // return address pushed on stack (could have moved after GC). // DirectCEntry stub itself is generated early and never moves. diff --git a/src/mips/macro-assembler-mips.h b/src/mips/macro-assembler-mips.h index 2e380622a..e4e027790 100644 --- a/src/mips/macro-assembler-mips.h +++ b/src/mips/macro-assembler-mips.h @@ -1276,8 +1276,7 @@ const Operand& rt = Operand(zero_reg), BranchDelaySlot bd = PROTECT // from handle and propagates exceptions. Restores context. stack_space // - space to be unwound on exit (includes the call JS arguments space and // the additional space allocated for the fast call). - void CallApiFunctionAndReturn(ExternalReference function, - Address function_address, + void CallApiFunctionAndReturn(Register function_address, ExternalReference thunk_ref, Register thunk_last_arg, int stack_space, diff --git a/src/mips/stub-cache-mips.cc b/src/mips/stub-cache-mips.cc index ef98db59b..f90db7cdc 100644 --- a/src/mips/stub-cache-mips.cc +++ b/src/mips/stub-cache-mips.cc @@ -765,98 +765,43 @@ static void CompileCallLoadPropertyWithInterceptor( } -static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength; - - static void GenerateFastApiCallBody(MacroAssembler* masm, const CallOptimization& optimization, int argc, - Register holder, - Register scratch1, - Register scratch2, - Register scratch3, + Register holder_in, bool restore_context) { - // ----------- S t a t e ------------- - // -- sp[0] : last JS argument - // -- ... - // -- sp[(argc - 1) * 4] : first JS argument - // -- sp[argc * 4] : receiver - // ----------------------------------- ASSERT(optimization.is_simple_api_call()); - typedef FunctionCallbackArguments FCA; - - STATIC_ASSERT(FCA::kHolderIndex == 0); - STATIC_ASSERT(FCA::kIsolateIndex == 1); - STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); - STATIC_ASSERT(FCA::kReturnValueOffset == 3); - STATIC_ASSERT(FCA::kDataIndex == 4); - STATIC_ASSERT(FCA::kCalleeIndex == 5); - STATIC_ASSERT(FCA::kContextSaveIndex == 6); - STATIC_ASSERT(FCA::kArgsLength == 7); + // Abi for CallApiFunctionStub. + Register callee = a0; + Register call_data = t0; + Register holder = a2; + Register api_function_address = a3; + Register thunk_arg = a1; - ASSERT(!holder.is(cp)); + // Put holder in place. + __ mov(holder, holder_in); - // Save calling context. - __ push(cp); - // Get the function and setup the context. + Isolate* isolate = masm->isolate(); Handle function = optimization.constant_function(); - __ li(scratch1, function); - __ lw(cp, FieldMemOperand(scratch1, JSFunction::kContextOffset)); - __ push(scratch1); - - // Construct the FunctionCallbackInfo. Handle api_call_info = optimization.api_call_info(); - Handle call_data(api_call_info->data(), masm->isolate()); + Handle call_data_obj(api_call_info->data(), isolate); + + // Put callee in place. + __ li(callee, function); + bool call_data_undefined = false; - if (masm->isolate()->heap()->InNewSpace(*call_data)) { - __ li(scratch1, api_call_info); - __ lw(scratch1, FieldMemOperand(scratch1, CallHandlerInfo::kDataOffset)); - } else if (call_data->IsUndefined()) { + // Put call_data in place. + if (isolate->heap()->InNewSpace(*call_data_obj)) { + __ li(call_data, api_call_info); + __ lw(call_data, FieldMemOperand(call_data, CallHandlerInfo::kDataOffset)); + } else if (call_data_obj->IsUndefined()) { call_data_undefined = true; - __ LoadRoot(scratch3, Heap::kUndefinedValueRootIndex); + __ LoadRoot(call_data, Heap::kUndefinedValueRootIndex); } else { - __ li(scratch1, call_data); - } - // Store call data. - __ push(scratch1); - if (!call_data_undefined) { - __ LoadRoot(scratch1, Heap::kUndefinedValueRootIndex); + __ li(call_data, call_data_obj); } - // Store ReturnValue default and ReturnValue. - __ LoadRoot(scratch1, Heap::kUndefinedValueRootIndex); - __ Push(scratch1, scratch1); - // Store isolate. - __ li(scratch1, Operand(ExternalReference::isolate_address(masm->isolate()))); - __ push(scratch1); - // Store holder. - __ push(holder); - - // Prepare arguments. - __ Move(a2, sp); - - // Allocate the v8::Arguments structure in the arguments' space since - // it's not controlled by GC. - const int kApiStackSpace = 4; - - FrameScope frame_scope(masm, StackFrame::MANUAL); - __ EnterExitFrame(false, kApiStackSpace); - - // a0 = FunctionCallbackInfo& - // Arguments is built at sp + 1 (sp is a reserved spot for ra). - __ Addu(a0, sp, kPointerSize); - // FunctionCallbackInfo::implicit_args_ - __ sw(a2, MemOperand(a0, 0 * kPointerSize)); - // FunctionCallbackInfo::values_ - __ Addu(t0, a2, Operand((kFastApiCallArguments - 1 + argc) * kPointerSize)); - __ sw(t0, MemOperand(a0, 1 * kPointerSize)); - // FunctionCallbackInfo::length_ = argc - __ li(t0, Operand(argc)); - __ sw(t0, MemOperand(a0, 2 * kPointerSize)); - // FunctionCallbackInfo::is_construct_call = 0 - __ sw(zero_reg, MemOperand(a0, 3 * kPointerSize)); - - const int kStackUnwindSpace = argc + kFastApiCallArguments + 1; + // Put api_function_address in place. Address function_address = v8::ToCData
(api_call_info->callback()); ApiFunction fun(function_address); ExternalReference::Type type = ExternalReference::DIRECT_API_CALL; @@ -864,26 +809,12 @@ static void GenerateFastApiCallBody(MacroAssembler* masm, ExternalReference(&fun, type, masm->isolate()); - Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback); - ExternalReference::Type thunk_type = ExternalReference::PROFILING_API_CALL; - ApiFunction thunk_fun(thunk_address); - ExternalReference thunk_ref = ExternalReference(&thunk_fun, thunk_type, - masm->isolate()); - - AllowExternalCallThatCantCauseGC scope(masm); - MemOperand context_restore_operand( - fp, (2 + FCA::kContextSaveIndex) * kPointerSize); - MemOperand return_value_operand( - fp, (2 + FCA::kReturnValueOffset) * kPointerSize); + __ li(api_function_address, Operand(ref)); + __ li(thunk_arg, Operand(reinterpret_cast(function_address))); - __ CallApiFunctionAndReturn(ref, - function_address, - thunk_ref, - a1, - kStackUnwindSpace, - return_value_operand, - restore_context ? - &context_restore_operand : NULL); + // Jump to stub. + CallApiFunctionStub stub(restore_context, call_data_undefined, argc); + __ TailCallStub(&stub); } @@ -897,7 +828,7 @@ static void GenerateFastApiCall(MacroAssembler* masm, __ IncrementCounter(counters->call_const_fast_api(), 1, a0, a1); // Move holder to a register. - Register holder_reg = a0; + Register holder_reg = a2; switch (holder_lookup) { case CallOptimization::kHolderIsReceiver: { @@ -924,9 +855,6 @@ static void GenerateFastApiCall(MacroAssembler* masm, optimization, argc, holder_reg, - a1, - a2, - a3, false); } @@ -948,21 +876,11 @@ static void GenerateFastApiCall(MacroAssembler* masm, __ push(arg); } - Register scratch1 = a0; - Register scratch2 = a1; - Register scratch3 = a2; - if (!a3.is(receiver)) { - __ mov(a3, receiver); - receiver = a3; - } // Stack now matches JSFunction abi. GenerateFastApiCallBody(masm, optimization, argc, receiver, - scratch1, - scratch2, - scratch3, true); } @@ -1412,6 +1330,10 @@ void LoadStubCompiler::GenerateLoadCallback( ApiFunction fun(getter_address); ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; ExternalReference ref = ExternalReference(&fun, type, isolate()); + Register getter_address_reg = a3; + Register thunk_last_arg = a2; + __ li(getter_address_reg, Operand(ref)); + __ li(thunk_last_arg, Operand(reinterpret_cast(getter_address))); Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback); ExternalReference::Type thunk_type = @@ -1419,10 +1341,9 @@ void LoadStubCompiler::GenerateLoadCallback( ApiFunction thunk_fun(thunk_address); ExternalReference thunk_ref = ExternalReference(&thunk_fun, thunk_type, isolate()); - __ CallApiFunctionAndReturn(ref, - getter_address, + __ CallApiFunctionAndReturn(getter_address_reg, thunk_ref, - a2, + thunk_last_arg, kStackUnwindSpace, MemOperand(fp, 6 * kPointerSize), NULL); -- 2.34.1