// 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());
__ 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);
}
// 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());
__ 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);
}
}
-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
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);
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.
}
// 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);
__ 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
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);
}
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
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());
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);
{
}
-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.
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) {
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();
// - 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);
}
-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
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);
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.
}
// 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);
__ 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
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);
}
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
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());
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);
}
-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.
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) {
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();
// - 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);