Commit ec52f8df authored by akos.palfi's avatar akos.palfi Committed by Commit bot

MIPS: split api call stubs into accessor and function call stubs

Port 6950ead0

Note: This port has known issues, there are about 40 test failures. The purpose of this commit is to unbreak the MIPS build.

BUG=

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

Cr-Commit-Position: refs/heads/master@{#26116}
parent e9e77212
......@@ -222,20 +222,17 @@ static void CompileCallLoadPropertyWithInterceptor(
// Generate call to api function.
void PropertyHandlerCompiler::GenerateFastApiCall(
void PropertyHandlerCompiler::GenerateApiAccessorCall(
MacroAssembler* masm, const CallOptimization& optimization,
Handle<Map> receiver_map, Register receiver, Register scratch_in,
bool is_store, int argc, Register* values) {
bool is_store, Register store_parameter) {
DCHECK(!receiver.is(scratch_in));
// Preparing to push, adjust sp.
__ Subu(sp, sp, Operand((argc + 1) * kPointerSize));
__ sw(receiver, MemOperand(sp, argc * kPointerSize)); // Push receiver.
__ push(receiver);
// Write the arguments to stack frame.
for (int i = 0; i < argc; i++) {
Register arg = values[argc - 1 - i];
DCHECK(!receiver.is(arg));
DCHECK(!scratch_in.is(arg));
__ sw(arg, MemOperand(sp, (argc - 1 - i) * kPointerSize)); // Push arg.
if (is_store) {
DCHECK(!receiver.is(store_parameter));
DCHECK(!scratch_in.is(store_parameter));
__ push(store_parameter);
}
DCHECK(optimization.is_simple_api_call());
......@@ -288,7 +285,7 @@ void PropertyHandlerCompiler::GenerateFastApiCall(
__ li(api_function_address, Operand(ref));
// Jump to stub.
CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc);
CallApiAccessorStub stub(isolate, is_store, call_data_undefined);
__ TailCallStub(&stub);
}
......
......@@ -223,20 +223,17 @@ static void CompileCallLoadPropertyWithInterceptor(
// Generate call to api function.
void PropertyHandlerCompiler::GenerateFastApiCall(
void PropertyHandlerCompiler::GenerateApiAccessorCall(
MacroAssembler* masm, const CallOptimization& optimization,
Handle<Map> receiver_map, Register receiver, Register scratch_in,
bool is_store, int argc, Register* values) {
bool is_store, Register store_parameter) {
DCHECK(!receiver.is(scratch_in));
// Preparing to push, adjust sp.
__ Dsubu(sp, sp, Operand((argc + 1) * kPointerSize));
__ sd(receiver, MemOperand(sp, argc * kPointerSize)); // Push receiver.
__ push(receiver);
// Write the arguments to stack frame.
for (int i = 0; i < argc; i++) {
Register arg = values[argc - 1 - i];
DCHECK(!receiver.is(arg));
DCHECK(!scratch_in.is(arg));
__ sd(arg, MemOperand(sp, (argc - 1 - i) * kPointerSize)); // Push arg.
if (is_store) {
DCHECK(!receiver.is(store_parameter));
DCHECK(!scratch_in.is(store_parameter));
__ push(store_parameter);
}
DCHECK(optimization.is_simple_api_call());
......@@ -289,7 +286,7 @@ void PropertyHandlerCompiler::GenerateFastApiCall(
__ li(api_function_address, Operand(ref));
// Jump to stub.
CallApiFunctionStub stub(isolate, is_store, call_data_undefined, argc);
CallApiAccessorStub stub(isolate, is_store, call_data_undefined);
__ TailCallStub(&stub);
}
......
......@@ -4833,12 +4833,16 @@ void InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
}
void CallApiFunctionStub::Generate(MacroAssembler* masm) {
static void CallApiFunctionStubHelper(MacroAssembler* masm,
const ParameterCount& argc,
bool return_first_arg,
bool call_data_undefined) {
// ----------- S t a t e -------------
// -- a0 : callee
// -- t0 : call_data
// -- a2 : holder
// -- a1 : api_function_address
// -- a3 : number of arguments if argc is a register
// -- cp : context
// --
// -- sp[0] : last argument
......@@ -4853,10 +4857,6 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) {
Register api_function_address = a1;
Register context = cp;
int argc = this->argc();
bool is_store = this->is_store();
bool call_data_undefined = this->call_data_undefined();
typedef FunctionCallbackArguments FCA;
STATIC_ASSERT(FCA::kContextSaveIndex == 6);
......@@ -4868,6 +4868,8 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) {
STATIC_ASSERT(FCA::kHolderIndex == 0);
STATIC_ASSERT(FCA::kArgsLength == 7);
DCHECK(argc.is_immediate() || a3.is(argc.reg()));
// Save context, callee and call data.
__ Push(context, callee, call_data);
// Load context from callee.
......@@ -4879,8 +4881,7 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) {
}
// Push return value and default return value.
__ Push(scratch, scratch);
__ li(scratch,
Operand(ExternalReference::isolate_address(isolate())));
__ li(scratch, Operand(ExternalReference::isolate_address(masm->isolate())));
// Push isolate and holder.
__ Push(scratch, holder);
......@@ -4900,39 +4901,73 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) {
__ 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;
if (argc.is_immediate()) {
// FunctionCallbackInfo::values_
__ Addu(at, scratch,
Operand((FCA::kArgsLength - 1 + argc.immediate()) * kPointerSize));
__ sw(at, MemOperand(a0, 1 * kPointerSize));
// FunctionCallbackInfo::length_ = argc
__ li(at, Operand(argc.immediate()));
__ sw(at, MemOperand(a0, 2 * kPointerSize));
// FunctionCallbackInfo::is_construct_call_ = 0
__ sw(zero_reg, MemOperand(a0, 3 * kPointerSize));
} else {
// FunctionCallbackInfo::values_
__ sll(at, argc.reg(), kPointerSizeLog2);
__ Addu(at, at, scratch);
__ Addu(at, at, Operand((FCA::kArgsLength - 1) * kPointerSize));
__ sw(at, MemOperand(a0, 1 * kPointerSize));
// FunctionCallbackInfo::length_ = argc
__ sw(argc.reg(), MemOperand(a0, 2 * kPointerSize));
// FunctionCallbackInfo::is_construct_call_
__ Addu(argc.reg(), argc.reg(), Operand(FCA::kArgsLength + 1));
__ sll(at, argc.reg(), kPointerSizeLog2);
__ sw(at, MemOperand(a0, 3 * kPointerSize));
}
ExternalReference thunk_ref =
ExternalReference::invoke_function_callback(isolate());
ExternalReference::invoke_function_callback(masm->isolate());
AllowExternalCallThatCantCauseGC scope(masm);
MemOperand context_restore_operand(
fp, (2 + FCA::kContextSaveIndex) * kPointerSize);
// Stores return the first js argument.
int return_value_offset = 0;
if (is_store) {
if (return_first_arg) {
return_value_offset = 2 + FCA::kArgsLength;
} else {
return_value_offset = 2 + FCA::kReturnValueOffset;
}
MemOperand return_value_operand(fp, return_value_offset * kPointerSize);
__ CallApiFunctionAndReturn(api_function_address,
thunk_ref,
kStackUnwindSpace,
return_value_operand,
int stack_space = 0;
MemOperand is_construct_call_operand = MemOperand(sp, 4 * kPointerSize);
MemOperand* stack_space_operand = &is_construct_call_operand;
if (argc.is_immediate()) {
stack_space = argc.immediate() + FCA::kArgsLength + 1;
stack_space_operand = NULL;
}
__ CallApiFunctionAndReturn(api_function_address, thunk_ref, stack_space,
stack_space_operand, return_value_operand,
&context_restore_operand);
}
void CallApiFunctionStub::Generate(MacroAssembler* masm) {
bool call_data_undefined = this->call_data_undefined();
CallApiFunctionStubHelper(masm, ParameterCount(a3), false,
call_data_undefined);
}
void CallApiAccessorStub::Generate(MacroAssembler* masm) {
bool is_store = this->is_store();
int argc = is_store ? 1 : 0;
bool call_data_undefined = this->call_data_undefined();
CallApiFunctionStubHelper(masm, ParameterCount(argc), is_store,
call_data_undefined);
}
void CallApiGetterStub::Generate(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- sp[0] : name
......@@ -4960,11 +4995,9 @@ void CallApiGetterStub::Generate(MacroAssembler* masm) {
ExternalReference thunk_ref =
ExternalReference::invoke_accessor_getter_callback(isolate());
__ CallApiFunctionAndReturn(api_function_address,
thunk_ref,
kStackUnwindSpace,
MemOperand(fp, 6 * kPointerSize),
NULL);
__ CallApiFunctionAndReturn(api_function_address, thunk_ref,
kStackUnwindSpace, NULL,
MemOperand(fp, 6 * kPointerSize), NULL);
}
......
......@@ -293,6 +293,27 @@ void ArgumentAdaptorDescriptor::Initialize(CallInterfaceDescriptorData* data) {
void ApiFunctionDescriptor::Initialize(CallInterfaceDescriptorData* data) {
Register registers[] = {
cp, // context
a0, // callee
t0, // call_data
a2, // holder
a1, // api_function_address
a3, // actual number of arguments
};
Representation representations[] = {
Representation::Tagged(), // context
Representation::Tagged(), // callee
Representation::Tagged(), // call_data
Representation::Tagged(), // holder
Representation::External(), // api_function_address
Representation::Integer32(), // actual number of arguments
};
data->Initialize(arraysize(registers), registers, representations);
}
void ApiAccessorDescriptor::Initialize(CallInterfaceDescriptorData* data) {
Register registers[] = {
cp, // context
a0, // callee
......
......@@ -4419,10 +4419,8 @@ static int AddressOffset(ExternalReference ref0, ExternalReference ref1) {
void MacroAssembler::CallApiFunctionAndReturn(
Register function_address,
ExternalReference thunk_ref,
int stack_space,
MemOperand return_value_operand,
Register function_address, ExternalReference thunk_ref, int stack_space,
MemOperand* stack_space_operand, MemOperand return_value_operand,
MemOperand* context_restore_operand) {
ExternalReference next_address =
ExternalReference::handle_scope_next_address(isolate());
......@@ -4516,8 +4514,13 @@ void MacroAssembler::CallApiFunctionAndReturn(
if (restore_context) {
lw(cp, *context_restore_operand);
}
li(s0, Operand(stack_space));
LeaveExitFrame(false, s0, !restore_context, EMIT_RETURN);
if (stack_space_operand != NULL) {
lw(s0, *stack_space_operand);
} else {
li(s0, Operand(stack_space));
}
LeaveExitFrame(false, s0, !restore_context, EMIT_RETURN,
stack_space_operand != NULL);
bind(&promote_scheduled_exception);
{
......@@ -5166,10 +5169,9 @@ void MacroAssembler::EnterExitFrame(bool save_doubles,
}
void MacroAssembler::LeaveExitFrame(bool save_doubles,
Register argument_count,
bool restore_context,
bool do_return) {
void MacroAssembler::LeaveExitFrame(bool save_doubles, Register argument_count,
bool restore_context, bool do_return,
bool argument_count_is_length) {
// Optionally restore all double registers.
if (save_doubles) {
// Remember: we only need to restore every 2nd double FPU value.
......@@ -5200,8 +5202,12 @@ void MacroAssembler::LeaveExitFrame(bool save_doubles,
lw(ra, MemOperand(sp, ExitFrameConstants::kCallerPCOffset));
if (argument_count.is_valid()) {
sll(t8, argument_count, kPointerSizeLog2);
addu(sp, sp, t8);
if (argument_count_is_length) {
addu(sp, sp, argument_count);
} else {
sll(t8, argument_count, kPointerSizeLog2);
addu(sp, sp, t8);
}
}
if (do_return) {
......
......@@ -871,10 +871,9 @@ class MacroAssembler: public Assembler {
int stack_space = 0);
// Leave the current exit frame.
void LeaveExitFrame(bool save_doubles,
Register arg_count,
bool restore_context,
bool do_return = NO_EMIT_RETURN);
void LeaveExitFrame(bool save_doubles, Register arg_count,
bool restore_context, bool do_return = NO_EMIT_RETURN,
bool argument_count_is_length = false);
// Get the actual activation frame alignment for target environment.
static int ActivationFrameAlignment();
......@@ -1291,8 +1290,8 @@ const Operand& rt = Operand(zero_reg), BranchDelaySlot bd = PROTECT
// - space to be unwound on exit (includes the call JS arguments space and
// the additional space allocated for the fast call).
void CallApiFunctionAndReturn(Register function_address,
ExternalReference thunk_ref,
int stack_space,
ExternalReference thunk_ref, int stack_space,
MemOperand* stack_space_operand,
MemOperand return_value_operand,
MemOperand* context_restore_operand);
......
......@@ -4873,12 +4873,16 @@ void InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
}
void CallApiFunctionStub::Generate(MacroAssembler* masm) {
static void CallApiFunctionStubHelper(MacroAssembler* masm,
const ParameterCount& argc,
bool return_first_arg,
bool call_data_undefined) {
// ----------- S t a t e -------------
// -- a0 : callee
// -- a4 : call_data
// -- a2 : holder
// -- a1 : api_function_address
// -- a3 : number of arguments if argc is a register
// -- cp : context
// --
// -- sp[0] : last argument
......@@ -4893,10 +4897,6 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) {
Register api_function_address = a1;
Register context = cp;
int argc = this->argc();
bool is_store = this->is_store();
bool call_data_undefined = this->call_data_undefined();
typedef FunctionCallbackArguments FCA;
STATIC_ASSERT(FCA::kContextSaveIndex == 6);
......@@ -4908,6 +4908,8 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) {
STATIC_ASSERT(FCA::kHolderIndex == 0);
STATIC_ASSERT(FCA::kArgsLength == 7);
DCHECK(argc.is_immediate() || a3.is(argc.reg()));
// Save context, callee and call data.
__ Push(context, callee, call_data);
// Load context from callee.
......@@ -4919,8 +4921,7 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) {
}
// Push return value and default return value.
__ Push(scratch, scratch);
__ li(scratch,
Operand(ExternalReference::isolate_address(isolate())));
__ li(scratch, Operand(ExternalReference::isolate_address(masm->isolate())));
// Push isolate and holder.
__ Push(scratch, holder);
......@@ -4940,39 +4941,73 @@ void CallApiFunctionStub::Generate(MacroAssembler* masm) {
__ Daddu(a0, sp, Operand(1 * kPointerSize));
// FunctionCallbackInfo::implicit_args_
__ sd(scratch, MemOperand(a0, 0 * kPointerSize));
// FunctionCallbackInfo::values_
__ Daddu(at, scratch, Operand((FCA::kArgsLength - 1 + argc) * kPointerSize));
__ sd(at, MemOperand(a0, 1 * kPointerSize));
// FunctionCallbackInfo::length_ = argc
__ li(at, Operand(argc));
__ sd(at, MemOperand(a0, 2 * kPointerSize));
// FunctionCallbackInfo::is_construct_call = 0
__ sd(zero_reg, MemOperand(a0, 3 * kPointerSize));
const int kStackUnwindSpace = argc + FCA::kArgsLength + 1;
if (argc.is_immediate()) {
// FunctionCallbackInfo::values_
__ Daddu(at, scratch,
Operand((FCA::kArgsLength - 1 + argc.immediate()) * kPointerSize));
__ sd(at, MemOperand(a0, 1 * kPointerSize));
// FunctionCallbackInfo::length_ = argc
__ li(at, Operand(argc.immediate()));
__ sd(at, MemOperand(a0, 2 * kPointerSize));
// FunctionCallbackInfo::is_construct_call_ = 0
__ sd(zero_reg, MemOperand(a0, 3 * kPointerSize));
} else {
// FunctionCallbackInfo::values_
__ dsll(at, argc.reg(), kPointerSizeLog2);
__ Daddu(at, at, scratch);
__ Daddu(at, at, Operand((FCA::kArgsLength - 1) * kPointerSize));
__ sd(at, MemOperand(a0, 1 * kPointerSize));
// FunctionCallbackInfo::length_ = argc
__ sd(argc.reg(), MemOperand(a0, 2 * kPointerSize));
// FunctionCallbackInfo::is_construct_call_
__ Daddu(argc.reg(), argc.reg(), Operand(FCA::kArgsLength + 1));
__ dsll(at, argc.reg(), kPointerSizeLog2);
__ sd(at, MemOperand(a0, 3 * kPointerSize));
}
ExternalReference thunk_ref =
ExternalReference::invoke_function_callback(isolate());
ExternalReference::invoke_function_callback(masm->isolate());
AllowExternalCallThatCantCauseGC scope(masm);
MemOperand context_restore_operand(
fp, (2 + FCA::kContextSaveIndex) * kPointerSize);
// Stores return the first js argument.
int return_value_offset = 0;
if (is_store) {
if (return_first_arg) {
return_value_offset = 2 + FCA::kArgsLength;
} else {
return_value_offset = 2 + FCA::kReturnValueOffset;
}
MemOperand return_value_operand(fp, return_value_offset * kPointerSize);
__ CallApiFunctionAndReturn(api_function_address,
thunk_ref,
kStackUnwindSpace,
return_value_operand,
int stack_space = 0;
MemOperand is_construct_call_operand = MemOperand(sp, 4 * kPointerSize);
MemOperand* stack_space_operand = &is_construct_call_operand;
if (argc.is_immediate()) {
stack_space = argc.immediate() + FCA::kArgsLength + 1;
stack_space_operand = NULL;
}
__ CallApiFunctionAndReturn(api_function_address, thunk_ref, stack_space,
stack_space_operand, return_value_operand,
&context_restore_operand);
}
void CallApiFunctionStub::Generate(MacroAssembler* masm) {
bool call_data_undefined = this->call_data_undefined();
CallApiFunctionStubHelper(masm, ParameterCount(a3), false,
call_data_undefined);
}
void CallApiAccessorStub::Generate(MacroAssembler* masm) {
bool is_store = this->is_store();
int argc = is_store ? 1 : 0;
bool call_data_undefined = this->call_data_undefined();
CallApiFunctionStubHelper(masm, ParameterCount(argc), is_store,
call_data_undefined);
}
void CallApiGetterStub::Generate(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- sp[0] : name
......@@ -5000,11 +5035,9 @@ void CallApiGetterStub::Generate(MacroAssembler* masm) {
ExternalReference thunk_ref =
ExternalReference::invoke_accessor_getter_callback(isolate());
__ CallApiFunctionAndReturn(api_function_address,
thunk_ref,
kStackUnwindSpace,
MemOperand(fp, 6 * kPointerSize),
NULL);
__ CallApiFunctionAndReturn(api_function_address, thunk_ref,
kStackUnwindSpace, NULL,
MemOperand(fp, 6 * kPointerSize), NULL);
}
......
......@@ -293,6 +293,27 @@ void ArgumentAdaptorDescriptor::Initialize(CallInterfaceDescriptorData* data) {
void ApiFunctionDescriptor::Initialize(CallInterfaceDescriptorData* data) {
Register registers[] = {
cp, // context
a0, // callee
a4, // call_data
a2, // holder
a1, // api_function_address
a3, // actual number of arguments
};
Representation representations[] = {
Representation::Tagged(), // context
Representation::Tagged(), // callee
Representation::Tagged(), // call_data
Representation::Tagged(), // holder
Representation::External(), // api_function_address
Representation::Integer32(), // actual number of arguments
};
data->Initialize(arraysize(registers), registers, representations);
}
void ApiAccessorDescriptor::Initialize(CallInterfaceDescriptorData* data) {
Register registers[] = {
cp, // context
a0, // callee
......
......@@ -4367,10 +4367,8 @@ static int AddressOffset(ExternalReference ref0, ExternalReference ref1) {
void MacroAssembler::CallApiFunctionAndReturn(
Register function_address,
ExternalReference thunk_ref,
int stack_space,
MemOperand return_value_operand,
Register function_address, ExternalReference thunk_ref, int stack_space,
MemOperand* stack_space_operand, MemOperand return_value_operand,
MemOperand* context_restore_operand) {
ExternalReference next_address =
ExternalReference::handle_scope_next_address(isolate());
......@@ -4464,9 +4462,13 @@ void MacroAssembler::CallApiFunctionAndReturn(
if (restore_context) {
ld(cp, *context_restore_operand);
}
li(s0, Operand(stack_space));
LeaveExitFrame(false, s0, !restore_context, EMIT_RETURN);
if (stack_space_operand != NULL) {
lw(s0, *stack_space_operand);
} else {
li(s0, Operand(stack_space));
}
LeaveExitFrame(false, s0, !restore_context, EMIT_RETURN,
stack_space_operand != NULL);
bind(&promote_scheduled_exception);
{
FrameScope frame(this, StackFrame::INTERNAL);
......@@ -5116,10 +5118,9 @@ void MacroAssembler::EnterExitFrame(bool save_doubles,
}
void MacroAssembler::LeaveExitFrame(bool save_doubles,
Register argument_count,
bool restore_context,
bool do_return) {
void MacroAssembler::LeaveExitFrame(bool save_doubles, Register argument_count,
bool restore_context, bool do_return,
bool argument_count_is_length) {
// Optionally restore all double registers.
if (save_doubles) {
// Remember: we only need to restore every 2nd double FPU value.
......@@ -5152,8 +5153,12 @@ void MacroAssembler::LeaveExitFrame(bool save_doubles,
ld(ra, MemOperand(sp, ExitFrameConstants::kCallerPCOffset));
if (argument_count.is_valid()) {
dsll(t8, argument_count, kPointerSizeLog2);
daddu(sp, sp, t8);
if (argument_count_is_length) {
daddu(sp, sp, argument_count);
} else {
dsll(t8, argument_count, kPointerSizeLog2);
daddu(sp, sp, t8);
}
}
if (do_return) {
......
......@@ -901,10 +901,9 @@ class MacroAssembler: public Assembler {
int stack_space = 0);
// Leave the current exit frame.
void LeaveExitFrame(bool save_doubles,
Register arg_count,
bool restore_context,
bool do_return = NO_EMIT_RETURN);
void LeaveExitFrame(bool save_doubles, Register arg_count,
bool restore_context, bool do_return = NO_EMIT_RETURN,
bool argument_count_is_length = false);
// Get the actual activation frame alignment for target environment.
static int ActivationFrameAlignment();
......@@ -1321,8 +1320,8 @@ const Operand& rt = Operand(zero_reg), BranchDelaySlot bd = PROTECT
// - space to be unwound on exit (includes the call JS arguments space and
// the additional space allocated for the fast call).
void CallApiFunctionAndReturn(Register function_address,
ExternalReference thunk_ref,
int stack_space,
ExternalReference thunk_ref, int stack_space,
MemOperand* stack_space_operand,
MemOperand return_value_operand,
MemOperand* context_restore_operand);
......
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