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) {
}
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
......
......@@ -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<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.
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<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
// return address pushed on stack (could have moved after GC).
// DirectCEntry stub itself is generated early and never moves.
......
......@@ -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,
......
......@@ -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<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<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;
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<Address>(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<int32_t>(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<int32_t>(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);
......
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