Commit e5a534f3 authored by palfia@homejinni.com's avatar palfia@homejinni.com

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
parent fd4a006e
...@@ -5692,6 +5692,109 @@ void InternalArrayConstructorStub::Generate(MacroAssembler* masm) { ...@@ -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 __ #undef __
} } // namespace v8::internal } } // namespace v8::internal
......
...@@ -3872,8 +3872,7 @@ static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { ...@@ -3872,8 +3872,7 @@ static int AddressOffset(ExternalReference ref0, ExternalReference ref1) {
void MacroAssembler::CallApiFunctionAndReturn( void MacroAssembler::CallApiFunctionAndReturn(
ExternalReference function, Register function_address,
Address function_address,
ExternalReference thunk_ref, ExternalReference thunk_ref,
Register thunk_last_arg, Register thunk_last_arg,
int stack_space, int stack_space,
...@@ -3889,6 +3888,26 @@ void MacroAssembler::CallApiFunctionAndReturn( ...@@ -3889,6 +3888,26 @@ void MacroAssembler::CallApiFunctionAndReturn(
ExternalReference::handle_scope_level_address(isolate()), ExternalReference::handle_scope_level_address(isolate()),
next_address); 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<int32_t>(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. // Allocate HandleScope in callee-save registers.
li(s3, Operand(next_address)); li(s3, Operand(next_address));
lw(s0, MemOperand(s3, kNextOffset)); lw(s0, MemOperand(s3, kNextOffset));
...@@ -3906,25 +3925,6 @@ void MacroAssembler::CallApiFunctionAndReturn( ...@@ -3906,25 +3925,6 @@ void MacroAssembler::CallApiFunctionAndReturn(
PopSafepointRegisters(); 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<int32_t>(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<int32_t>(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 // Native call returns to the DirectCEntry stub which redirects to the
// return address pushed on stack (could have moved after GC). // return address pushed on stack (could have moved after GC).
// DirectCEntry stub itself is generated early and never moves. // DirectCEntry stub itself is generated early and never moves.
......
...@@ -1276,8 +1276,7 @@ const Operand& rt = Operand(zero_reg), BranchDelaySlot bd = PROTECT ...@@ -1276,8 +1276,7 @@ const Operand& rt = Operand(zero_reg), BranchDelaySlot bd = PROTECT
// from handle and propagates exceptions. Restores context. stack_space // from handle and propagates exceptions. Restores context. stack_space
// - space to be unwound on exit (includes the call JS arguments space and // - space to be unwound on exit (includes the call JS arguments space and
// the additional space allocated for the fast call). // the additional space allocated for the fast call).
void CallApiFunctionAndReturn(ExternalReference function, void CallApiFunctionAndReturn(Register function_address,
Address function_address,
ExternalReference thunk_ref, ExternalReference thunk_ref,
Register thunk_last_arg, Register thunk_last_arg,
int stack_space, int stack_space,
......
...@@ -765,98 +765,43 @@ static void CompileCallLoadPropertyWithInterceptor( ...@@ -765,98 +765,43 @@ static void CompileCallLoadPropertyWithInterceptor(
} }
static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength;
static void GenerateFastApiCallBody(MacroAssembler* masm, static void GenerateFastApiCallBody(MacroAssembler* masm,
const CallOptimization& optimization, const CallOptimization& optimization,
int argc, int argc,
Register holder, Register holder_in,
Register scratch1,
Register scratch2,
Register scratch3,
bool restore_context) { 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()); ASSERT(optimization.is_simple_api_call());
typedef FunctionCallbackArguments FCA; // Abi for CallApiFunctionStub.
Register callee = a0;
STATIC_ASSERT(FCA::kHolderIndex == 0); Register call_data = t0;
STATIC_ASSERT(FCA::kIsolateIndex == 1); Register holder = a2;
STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); Register api_function_address = a3;
STATIC_ASSERT(FCA::kReturnValueOffset == 3); Register thunk_arg = a1;
STATIC_ASSERT(FCA::kDataIndex == 4);
STATIC_ASSERT(FCA::kCalleeIndex == 5);
STATIC_ASSERT(FCA::kContextSaveIndex == 6);
STATIC_ASSERT(FCA::kArgsLength == 7);
ASSERT(!holder.is(cp)); // Put holder in place.
__ mov(holder, holder_in);
// Save calling context. Isolate* isolate = masm->isolate();
__ push(cp);
// Get the function and setup the context.
Handle<JSFunction> function = optimization.constant_function(); Handle<JSFunction> function = optimization.constant_function();
__ li(scratch1, function);
__ lw(cp, FieldMemOperand(scratch1, JSFunction::kContextOffset));
__ push(scratch1);
// Construct the FunctionCallbackInfo.
Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
Handle<Object> call_data(api_call_info->data(), masm->isolate()); Handle<Object> call_data_obj(api_call_info->data(), isolate);
// Put callee in place.
__ li(callee, function);
bool call_data_undefined = false; bool call_data_undefined = false;
if (masm->isolate()->heap()->InNewSpace(*call_data)) { // Put call_data in place.
__ li(scratch1, api_call_info); if (isolate->heap()->InNewSpace(*call_data_obj)) {
__ lw(scratch1, FieldMemOperand(scratch1, CallHandlerInfo::kDataOffset)); __ li(call_data, api_call_info);
} else if (call_data->IsUndefined()) { __ lw(call_data, FieldMemOperand(call_data, CallHandlerInfo::kDataOffset));
} else if (call_data_obj->IsUndefined()) {
call_data_undefined = true; call_data_undefined = true;
__ LoadRoot(scratch3, Heap::kUndefinedValueRootIndex); __ LoadRoot(call_data, Heap::kUndefinedValueRootIndex);
} else { } else {
__ li(scratch1, call_data); __ li(call_data, call_data_obj);
}
// Store call data.
__ push(scratch1);
if (!call_data_undefined) {
__ LoadRoot(scratch1, Heap::kUndefinedValueRootIndex);
} }
// Store ReturnValue default and ReturnValue. // Put api_function_address in place.
__ 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;
Address function_address = v8::ToCData<Address>(api_call_info->callback()); Address function_address = v8::ToCData<Address>(api_call_info->callback());
ApiFunction fun(function_address); ApiFunction fun(function_address);
ExternalReference::Type type = ExternalReference::DIRECT_API_CALL; ExternalReference::Type type = ExternalReference::DIRECT_API_CALL;
...@@ -864,26 +809,12 @@ static void GenerateFastApiCallBody(MacroAssembler* masm, ...@@ -864,26 +809,12 @@ static void GenerateFastApiCallBody(MacroAssembler* masm,
ExternalReference(&fun, ExternalReference(&fun,
type, type,
masm->isolate()); masm->isolate());
Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback); __ li(api_function_address, Operand(ref));
ExternalReference::Type thunk_type = ExternalReference::PROFILING_API_CALL; __ li(thunk_arg, Operand(reinterpret_cast<int32_t>(function_address)));
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(ref, // Jump to stub.
function_address, CallApiFunctionStub stub(restore_context, call_data_undefined, argc);
thunk_ref, __ TailCallStub(&stub);
a1,
kStackUnwindSpace,
return_value_operand,
restore_context ?
&context_restore_operand : NULL);
} }
...@@ -897,7 +828,7 @@ static void GenerateFastApiCall(MacroAssembler* masm, ...@@ -897,7 +828,7 @@ static void GenerateFastApiCall(MacroAssembler* masm,
__ IncrementCounter(counters->call_const_fast_api(), 1, a0, a1); __ IncrementCounter(counters->call_const_fast_api(), 1, a0, a1);
// Move holder to a register. // Move holder to a register.
Register holder_reg = a0; Register holder_reg = a2;
switch (holder_lookup) { switch (holder_lookup) {
case CallOptimization::kHolderIsReceiver: case CallOptimization::kHolderIsReceiver:
{ {
...@@ -924,9 +855,6 @@ static void GenerateFastApiCall(MacroAssembler* masm, ...@@ -924,9 +855,6 @@ static void GenerateFastApiCall(MacroAssembler* masm,
optimization, optimization,
argc, argc,
holder_reg, holder_reg,
a1,
a2,
a3,
false); false);
} }
...@@ -948,21 +876,11 @@ static void GenerateFastApiCall(MacroAssembler* masm, ...@@ -948,21 +876,11 @@ static void GenerateFastApiCall(MacroAssembler* masm,
__ push(arg); __ 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. // Stack now matches JSFunction abi.
GenerateFastApiCallBody(masm, GenerateFastApiCallBody(masm,
optimization, optimization,
argc, argc,
receiver, receiver,
scratch1,
scratch2,
scratch3,
true); true);
} }
...@@ -1412,6 +1330,10 @@ void LoadStubCompiler::GenerateLoadCallback( ...@@ -1412,6 +1330,10 @@ void LoadStubCompiler::GenerateLoadCallback(
ApiFunction fun(getter_address); ApiFunction fun(getter_address);
ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL; ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL;
ExternalReference ref = ExternalReference(&fun, type, isolate()); 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<int32_t>(getter_address)));
Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback); Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback);
ExternalReference::Type thunk_type = ExternalReference::Type thunk_type =
...@@ -1419,10 +1341,9 @@ void LoadStubCompiler::GenerateLoadCallback( ...@@ -1419,10 +1341,9 @@ void LoadStubCompiler::GenerateLoadCallback(
ApiFunction thunk_fun(thunk_address); ApiFunction thunk_fun(thunk_address);
ExternalReference thunk_ref = ExternalReference(&thunk_fun, thunk_type, ExternalReference thunk_ref = ExternalReference(&thunk_fun, thunk_type,
isolate()); isolate());
__ CallApiFunctionAndReturn(ref, __ CallApiFunctionAndReturn(getter_address_reg,
getter_address,
thunk_ref, thunk_ref,
a2, thunk_last_arg,
kStackUnwindSpace, kStackUnwindSpace,
MemOperand(fp, 6 * kPointerSize), MemOperand(fp, 6 * kPointerSize),
NULL); NULL);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment