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:
parent
bef13f739c
commit
71971764fe
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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(®ular_invoke);
|
__ bind(®ular_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
|
||||||
|
Loading…
Reference in New Issue
Block a user