MIPS: crankshaft support for api method calls

Port r18946 (a152f5ae)

BUG=
R=plind44@gmail.com

Review URL: https://codereview.chromium.org/150913002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18967 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
palfia@homejinni.com 2014-01-31 00:36:19 +00:00
parent bef13f739c
commit 71971764fe
5 changed files with 41 additions and 156 deletions

View File

@ -444,6 +444,26 @@ void CallDescriptors::InitializeForIsolate(Isolate* isolate) {
descriptor->register_params_ = registers; descriptor->register_params_ = registers;
descriptor->param_representations_ = representations; descriptor->param_representations_ = representations;
} }
{
CallInterfaceDescriptor* descriptor =
isolate->call_descriptor(Isolate::ApiFunctionCall);
static Register registers[] = { a0, // callee
t0, // call_data
a2, // holder
a1, // api_function_address
cp, // context
};
static Representation representations[] = {
Representation::Tagged(), // callee
Representation::Tagged(), // call_data
Representation::Tagged(), // holder
Representation::External(), // api_function_address
Representation::Tagged(), // context
};
descriptor->register_param_count_ = 5;
descriptor->register_params_ = registers;
descriptor->param_representations_ = representations;
}
} }
@ -5561,8 +5581,7 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) {
// -- a0 : callee // -- a0 : callee
// -- t0 : call_data // -- t0 : call_data
// -- a2 : holder // -- a2 : holder
// -- a3 : api_function_address // -- a1 : api_function_address
// -- a1 : thunk_arg
// -- cp : context // -- cp : context
// -- // --
// -- sp[0] : last argument // -- sp[0] : last argument
@ -5574,8 +5593,7 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) {
Register callee = a0; Register callee = a0;
Register call_data = t0; Register call_data = t0;
Register holder = a2; Register holder = a2;
Register api_function_address = a3; Register api_function_address = a1;
Register thunk_arg = a1;
Register context = cp; Register context = cp;
int argc = ArgumentBits::decode(bit_field_); int argc = ArgumentBits::decode(bit_field_);
@ -5621,7 +5639,7 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) {
FrameScope frame_scope(masm, StackFrame::MANUAL); FrameScope frame_scope(masm, StackFrame::MANUAL);
__ EnterExitFrame(false, kApiStackSpace); __ EnterExitFrame(false, kApiStackSpace);
ASSERT(!thunk_arg.is(a0) && !api_function_address.is(a0) && !scratch.is(a0)); ASSERT(!api_function_address.is(a0) && !scratch.is(a0));
// a0 = FunctionCallbackInfo& // a0 = FunctionCallbackInfo&
// Arguments is after the return address. // Arguments is after the return address.
__ Addu(a0, sp, Operand(1 * kPointerSize)); __ Addu(a0, sp, Operand(1 * kPointerSize));
@ -5651,7 +5669,6 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) {
__ CallApiFunctionAndReturn(api_function_address, __ CallApiFunctionAndReturn(api_function_address,
thunk_ref, thunk_ref,
thunk_arg,
kStackUnwindSpace, kStackUnwindSpace,
return_value_operand, return_value_operand,
restore_context ? restore_context ?
@ -5664,12 +5681,10 @@ void CallApiGetterStub::Generate(MacroAssembler* masm) {
// -- sp[0] : name // -- sp[0] : name
// -- sp[4 - kArgsLength*4] : PropertyCallbackArguments object // -- sp[4 - kArgsLength*4] : PropertyCallbackArguments object
// -- ... // -- ...
// -- a3 : api_function_address // -- a2 : api_function_address
// -- a2 : thunk_last_arg
// ----------------------------------- // -----------------------------------
Register api_function_address = a3; Register api_function_address = a2;
Register thunk_last_arg = a2;
__ mov(a0, sp); // a0 = Handle<Name> __ mov(a0, sp); // a0 = Handle<Name>
__ Addu(a1, a0, Operand(1 * kPointerSize)); // a1 = PCA __ Addu(a1, a0, Operand(1 * kPointerSize)); // a1 = PCA
@ -5693,7 +5708,6 @@ void CallApiGetterStub::Generate(MacroAssembler* masm) {
masm->isolate()); masm->isolate());
__ CallApiFunctionAndReturn(api_function_address, __ CallApiFunctionAndReturn(api_function_address,
thunk_ref, thunk_ref,
thunk_last_arg,
kStackUnwindSpace, kStackUnwindSpace,
MemOperand(fp, 6 * kPointerSize), MemOperand(fp, 6 * kPointerSize),
NULL); NULL);

View File

@ -3874,7 +3874,6 @@ static int AddressOffset(ExternalReference ref0, ExternalReference ref1) {
void MacroAssembler::CallApiFunctionAndReturn( void MacroAssembler::CallApiFunctionAndReturn(
Register function_address, Register function_address,
ExternalReference thunk_ref, ExternalReference thunk_ref,
Register thunk_last_arg,
int stack_space, int stack_space,
MemOperand return_value_operand, MemOperand return_value_operand,
MemOperand* context_restore_operand) { MemOperand* context_restore_operand) {
@ -3888,8 +3887,7 @@ 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(function_address.is(a1) || function_address.is(a2));
ASSERT(thunk_last_arg.is(a1) || thunk_last_arg.is(a2));
Label profiler_disabled; Label profiler_disabled;
Label end_profiler_check; Label end_profiler_check;

View File

@ -1278,7 +1278,6 @@ const Operand& rt = Operand(zero_reg), BranchDelaySlot bd = PROTECT
// the additional space allocated for the fast call). // the additional space allocated for the fast call).
void CallApiFunctionAndReturn(Register function_address, void CallApiFunctionAndReturn(Register function_address,
ExternalReference thunk_ref, ExternalReference thunk_ref,
Register thunk_last_arg,
int stack_space, int stack_space,
MemOperand return_value_operand, MemOperand return_value_operand,
MemOperand* context_restore_operand); MemOperand* context_restore_operand);

View File

@ -972,6 +972,12 @@ class Redirection {
return reinterpret_cast<Redirection*>(addr_of_redirection); return reinterpret_cast<Redirection*>(addr_of_redirection);
} }
static void* ReverseRedirection(int32_t reg) {
Redirection* redirection = FromSwiInstruction(
reinterpret_cast<Instruction*>(reinterpret_cast<void*>(reg)));
return redirection->external_function();
}
private: private:
void* external_function_; void* external_function_;
uint32_t swi_instruction_; uint32_t swi_instruction_;
@ -1389,12 +1395,12 @@ typedef double (*SimulatorRuntimeFPIntCall)(double darg0, int32_t arg0);
// This signature supports direct call in to API function native callback // This signature supports direct call in to API function native callback
// (refer to InvocationCallback in v8.h). // (refer to InvocationCallback in v8.h).
typedef void (*SimulatorRuntimeDirectApiCall)(int32_t arg0); typedef void (*SimulatorRuntimeDirectApiCall)(int32_t arg0);
typedef void (*SimulatorRuntimeProfilingApiCall)(int32_t arg0, int32_t arg1); typedef void (*SimulatorRuntimeProfilingApiCall)(int32_t arg0, void* arg1);
// This signature supports direct call to accessor getter callback. // This signature supports direct call to accessor getter callback.
typedef void (*SimulatorRuntimeDirectGetterCall)(int32_t arg0, int32_t arg1); typedef void (*SimulatorRuntimeDirectGetterCall)(int32_t arg0, int32_t arg1);
typedef void (*SimulatorRuntimeProfilingGetterCall)( typedef void (*SimulatorRuntimeProfilingGetterCall)(
int32_t arg0, int32_t arg1, int32_t arg2); int32_t arg0, int32_t arg1, void* arg2);
// Software interrupt instructions are used by the simulator to call into the // Software interrupt instructions are used by the simulator to call into the
// C-based V8 runtime. They are also used for debugging with simulator. // C-based V8 runtime. They are also used for debugging with simulator.
@ -1555,7 +1561,7 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
} }
SimulatorRuntimeProfilingApiCall target = SimulatorRuntimeProfilingApiCall target =
reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external); reinterpret_cast<SimulatorRuntimeProfilingApiCall>(external);
target(arg0, arg1); target(arg0, Redirection::ReverseRedirection(arg1));
} else if ( } else if (
redirection->type() == ExternalReference::DIRECT_GETTER_CALL) { redirection->type() == ExternalReference::DIRECT_GETTER_CALL) {
if (::v8::internal::FLAG_trace_sim) { if (::v8::internal::FLAG_trace_sim) {
@ -1573,7 +1579,7 @@ void Simulator::SoftwareInterrupt(Instruction* instr) {
} }
SimulatorRuntimeProfilingGetterCall target = SimulatorRuntimeProfilingGetterCall target =
reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(external); reinterpret_cast<SimulatorRuntimeProfilingGetterCall>(external);
target(arg0, arg1, arg2); target(arg0, arg1, Redirection::ReverseRedirection(arg2));
} else { } else {
SimulatorRuntimeCall target = SimulatorRuntimeCall target =
reinterpret_cast<SimulatorRuntimeCall>(external); reinterpret_cast<SimulatorRuntimeCall>(external);

View File

@ -776,8 +776,7 @@ static void GenerateFastApiCallBody(MacroAssembler* masm,
Register callee = a0; Register callee = a0;
Register call_data = t0; Register call_data = t0;
Register holder = a2; Register holder = a2;
Register api_function_address = a3; Register api_function_address = a1;
Register thunk_arg = a1;
// Put holder in place. // Put holder in place.
__ mov(holder, holder_in); __ mov(holder, holder_in);
@ -810,7 +809,6 @@ static void GenerateFastApiCallBody(MacroAssembler* masm,
type, type,
masm->isolate()); masm->isolate());
__ li(api_function_address, Operand(ref)); __ li(api_function_address, Operand(ref));
__ li(thunk_arg, Operand(reinterpret_cast<int32_t>(function_address)));
// Jump to stub. // Jump to stub.
CallApiFunctionStub stub(restore_context, call_data_undefined, argc); CallApiFunctionStub stub(restore_context, call_data_undefined, argc);
@ -818,47 +816,6 @@ static void GenerateFastApiCallBody(MacroAssembler* masm,
} }
// Generates call to API function.
static void GenerateFastApiCall(MacroAssembler* masm,
const CallOptimization& optimization,
int argc,
Handle<Map> map_to_holder,
CallOptimization::HolderLookup holder_lookup) {
Counters* counters = masm->isolate()->counters();
__ IncrementCounter(counters->call_const_fast_api(), 1, a0, a1);
// Move holder to a register.
Register holder_reg = a2;
switch (holder_lookup) {
case CallOptimization::kHolderIsReceiver:
{
ASSERT(map_to_holder.is_null());
__ lw(holder_reg, MemOperand(sp, argc * kPointerSize));
}
break;
case CallOptimization::kHolderIsPrototypeOfMap:
{
Handle<JSObject> holder(JSObject::cast(map_to_holder->prototype()));
if (!masm->isolate()->heap()->InNewSpace(*holder)) {
__ li(holder_reg, holder);
} else {
__ li(holder_reg, map_to_holder);
__ lw(holder_reg,
FieldMemOperand(holder_reg, Map::kPrototypeOffset));
}
}
break;
case CallOptimization::kHolderNotFound:
UNREACHABLE();
}
GenerateFastApiCallBody(masm,
optimization,
argc,
holder_reg,
false);
}
// Generate call to api function. // Generate call to api function.
static void GenerateFastApiCall(MacroAssembler* masm, static void GenerateFastApiCall(MacroAssembler* masm,
const CallOptimization& optimization, const CallOptimization& optimization,
@ -964,36 +921,9 @@ class CallInterceptorCompiler BASE_EMBEDDED {
name, miss_label); name, miss_label);
} }
Handle<Map> lookup_map; Handle<JSFunction> function = optimization.constant_function();
CallOptimization::HolderLookup holder_lookup = __ Move(a0, receiver);
CallOptimization::kHolderNotFound; stub_compiler_->GenerateJumpFunction(object, function);
if (optimization.is_simple_api_call() &&
!lookup->holder()->IsGlobalObject()) {
lookup_map = optimization.LookupHolderOfExpectedType(
object, object, interceptor_holder, &holder_lookup);
if (holder_lookup == CallOptimization::kHolderNotFound) {
lookup_map =
optimization.LookupHolderOfExpectedType(
object,
interceptor_holder,
Handle<JSObject>(lookup->holder()),
&holder_lookup);
}
}
// Invoke function.
if (holder_lookup != CallOptimization::kHolderNotFound) {
int argc = arguments_.immediate();
GenerateFastApiCall(masm,
optimization,
argc,
lookup_map,
holder_lookup);
} else {
Handle<JSFunction> function = optimization.constant_function();
__ Move(a0, receiver);
stub_compiler_->GenerateJumpFunction(object, function);
}
// Invoke a regular function. // Invoke a regular function.
__ bind(&regular_invoke); __ bind(&regular_invoke);
@ -1314,15 +1244,13 @@ void LoadStubCompiler::GenerateLoadCallback(
__ mov(a2, scratch2()); // Saved in case scratch2 == a1. __ mov(a2, scratch2()); // Saved in case scratch2 == a1.
// Abi for CallApiGetter. // Abi for CallApiGetter.
Register getter_address_reg = a3; Register getter_address_reg = a2;
Register thunk_last_arg = a2;
Address getter_address = v8::ToCData<Address>(callback->getter()); Address getter_address = v8::ToCData<Address>(callback->getter());
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());
__ li(getter_address_reg, Operand(ref)); __ li(getter_address_reg, Operand(ref));
__ li(thunk_last_arg, Operand(reinterpret_cast<int32_t>(getter_address)));
CallApiGetterStub stub; CallApiGetterStub stub;
__ TailCallStub(&stub); __ TailCallStub(&stub);
@ -1485,58 +1413,6 @@ Handle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object,
} }
Handle<Code> CallStubCompiler::CompileFastApiCall(
const CallOptimization& optimization,
Handle<Object> object,
Handle<JSObject> holder,
Handle<Cell> cell,
Handle<JSFunction> function,
Handle<String> name) {
Counters* counters = isolate()->counters();
ASSERT(optimization.is_simple_api_call());
// Bail out if object is a global object as we don't want to
// repatch it to global receiver.
if (object->IsGlobalObject()) return Handle<Code>::null();
if (!cell.is_null()) return Handle<Code>::null();
if (!object->IsJSObject()) return Handle<Code>::null();
Handle<JSObject> receiver = Handle<JSObject>::cast(object);
CallOptimization::HolderLookup holder_lookup =
CallOptimization::kHolderNotFound;
Handle<Map> lookup_map = optimization.LookupHolderOfExpectedType(
receiver, receiver, holder, &holder_lookup);
if (holder_lookup == CallOptimization::kHolderNotFound) {
return Handle<Code>::null();
}
Label miss;
GenerateNameCheck(name, &miss);
// Get the receiver from the stack.
const int argc = arguments().immediate();
__ lw(a1, MemOperand(sp, argc * kPointerSize));
// Check that the receiver isn't a smi.
__ JumpIfSmi(a1, &miss);
__ IncrementCounter(counters->call_const(), 1, a0, a3);
// Check that the maps haven't changed and find a Holder as a side effect.
CheckPrototypes(
IC::CurrentTypeOf(object, isolate()),
a1, holder, a0, a3, t0, name, &miss);
GenerateFastApiCall(
masm(), optimization, argc, lookup_map, holder_lookup);
HandlerFrontendFooter(&miss);
// Return the generated code.
return GetCode(function);
}
void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) { void StubCompiler::GenerateBooleanCheck(Register object, Label* miss) {
Label success; Label success;
// Check that the object is a boolean. // Check that the object is a boolean.
@ -1697,14 +1573,6 @@ Handle<Code> CallStubCompiler::CompileCallGlobal(
Handle<PropertyCell> cell, Handle<PropertyCell> cell,
Handle<JSFunction> function, Handle<JSFunction> function,
Handle<Name> name) { Handle<Name> name) {
if (HasCustomCallGenerator(function)) {
Handle<Code> code = CompileCustomCall(
object, holder, cell, function, Handle<String>::cast(name),
Code::NORMAL);
// A null handle means bail out to the regular compiler code below.
if (!code.is_null()) return code;
}
Label miss; Label miss;
HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss); HandlerFrontendHeader(object, holder, name, RECEIVER_MAP_CHECK, &miss);
// Potentially loads a closure that matches the shared function info of the // Potentially loads a closure that matches the shared function info of the