MIPS: reland 16744: add context save for GenerateFastApiCall.

Port r16763 (968acfa)

BUG=
R=plind44@gmail.com

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

Patch from Balazs Kilvady <kilvadyb@homejinni.com>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16778 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
plind44@gmail.com 2013-09-17 19:10:48 +00:00
parent 2974f8e3bb
commit d047afb4fe
4 changed files with 85 additions and 44 deletions

View File

@ -2876,7 +2876,7 @@ void CEntryStub::GenerateCore(MacroAssembler* masm,
// v0:v1: result
// sp: stack pointer
// fp: frame pointer
__ LeaveExitFrame(save_doubles_, s0, true);
__ LeaveExitFrame(save_doubles_, s0, true, EMIT_RETURN);
// Check if we should retry or throw exception.
Label retry;
@ -4156,7 +4156,7 @@ void RegExpExecStub::Generate(MacroAssembler* masm) {
DirectCEntryStub stub;
stub.GenerateCall(masm, t9);
__ LeaveExitFrame(false, no_reg);
__ LeaveExitFrame(false, no_reg, true);
// v0: result
// subject: subject string (callee saved)

View File

@ -3847,12 +3847,14 @@ static int AddressOffset(ExternalReference ref0, ExternalReference ref1) {
}
void MacroAssembler::CallApiFunctionAndReturn(ExternalReference function,
Address function_address,
ExternalReference thunk_ref,
Register thunk_last_arg,
int stack_space,
int return_value_offset_from_fp) {
void MacroAssembler::CallApiFunctionAndReturn(
ExternalReference function,
Address function_address,
ExternalReference thunk_ref,
Register thunk_last_arg,
int stack_space,
MemOperand return_value_operand,
MemOperand* context_restore_operand) {
ExternalReference next_address =
ExternalReference::handle_scope_next_address(isolate());
const int kNextOffset = 0;
@ -3915,12 +3917,13 @@ void MacroAssembler::CallApiFunctionAndReturn(ExternalReference function,
}
Label promote_scheduled_exception;
Label exception_handled;
Label delete_allocated_handles;
Label leave_exit_frame;
Label return_value_loaded;
// Load value from ReturnValue.
lw(v0, MemOperand(fp, return_value_offset_from_fp*kPointerSize));
lw(v0, return_value_operand);
bind(&return_value_loaded);
// No more valid handles (the result handle was the last one). Restore
@ -3941,14 +3944,23 @@ void MacroAssembler::CallApiFunctionAndReturn(ExternalReference function,
li(at, Operand(ExternalReference::scheduled_exception_address(isolate())));
lw(t1, MemOperand(at));
Branch(&promote_scheduled_exception, ne, t0, Operand(t1));
bind(&exception_handled);
bool restore_context = context_restore_operand != NULL;
if (restore_context) {
lw(cp, *context_restore_operand);
}
li(s0, Operand(stack_space));
LeaveExitFrame(false, s0, true);
LeaveExitFrame(false, s0, !restore_context, EMIT_RETURN);
bind(&promote_scheduled_exception);
TailCallExternalReference(
ExternalReference(Runtime::kPromoteScheduledException, isolate()),
0,
1);
{
FrameScope frame(this, StackFrame::INTERNAL);
CallExternalReference(
ExternalReference(Runtime::kPromoteScheduledException, isolate()),
0);
}
jmp(&exception_handled);
// HandleScope limit has changed. Delete allocated extensions.
bind(&delete_allocated_handles);
@ -4684,6 +4696,7 @@ void MacroAssembler::EnterExitFrame(bool save_doubles,
void MacroAssembler::LeaveExitFrame(bool save_doubles,
Register argument_count,
bool restore_context,
bool do_return) {
// Optionally restore all double registers.
if (save_doubles) {
@ -4700,9 +4713,12 @@ void MacroAssembler::LeaveExitFrame(bool save_doubles,
sw(zero_reg, MemOperand(t8));
// Restore current context from top and clear it in debug mode.
li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
lw(cp, MemOperand(t8));
if (restore_context) {
li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
lw(cp, MemOperand(t8));
}
#ifdef DEBUG
li(t8, Operand(ExternalReference(Isolate::kContextAddress, isolate())));
sw(a3, MemOperand(t8));
#endif

View File

@ -51,6 +51,12 @@ class JumpTarget;
// MIPS generated code calls C code, it must be via t9 register.
// Flags used for LeaveExitFrame function.
enum LeaveExitFrameMode {
EMIT_RETURN = true,
NO_EMIT_RETURN = false
};
// Flags used for AllocateHeapNumber
enum TaggingMode {
// Tag the result.
@ -848,7 +854,8 @@ class MacroAssembler: public Assembler {
// Leave the current exit frame.
void LeaveExitFrame(bool save_doubles,
Register arg_count,
bool do_return = false);
bool restore_context,
bool do_return = NO_EMIT_RETURN);
// Get the actual activation frame alignment for target environment.
static int ActivationFrameAlignment();
@ -1271,7 +1278,8 @@ class MacroAssembler: public Assembler {
ExternalReference thunk_ref,
Register thunk_last_arg,
int stack_space,
int return_value_offset_from_fp);
MemOperand return_value_operand,
MemOperand* context_restore_operand);
// Jump to the builtin routine.
void JumpToExternalReference(const ExternalReference& builtin,

View File

@ -829,23 +829,28 @@ static void FreeSpaceForFastApiCall(MacroAssembler* masm) {
static void GenerateFastApiDirectCall(MacroAssembler* masm,
const CallOptimization& optimization,
int argc) {
int argc,
bool restore_context) {
// ----------- S t a t e -------------
// -- sp[0] : holder (set by CheckPrototypes)
// -- sp[4] : callee JS function
// -- sp[8] : call data
// -- sp[12] : isolate
// -- sp[16] : ReturnValue default value
// -- sp[20] : ReturnValue
// -- sp[24] : last JS argument
// -- sp[0] : context
// -- sp[4] : holder (set by CheckPrototypes)
// -- sp[8] : callee JS function
// -- sp[12] : call data
// -- sp[16] : isolate
// -- sp[20] : ReturnValue default value
// -- sp[24] : ReturnValue
// -- sp[28] : last JS argument
// -- ...
// -- sp[(argc + 5) * 4] : first JS argument
// -- sp[(argc + 6) * 4] : receiver
// -- sp[(argc + 6) * 4] : first JS argument
// -- sp[(argc + 7) * 4] : receiver
// -----------------------------------
// Save calling context.
__ sw(cp, MemOperand(sp));
// Get the function and setup the context.
Handle<JSFunction> function = optimization.constant_function();
__ LoadHeapObject(t1, function);
__ lw(cp, FieldMemOperand(t1, JSFunction::kContextOffset));
__ sw(t1, MemOperand(sp, 2 * kPointerSize));
// Pass the additional arguments.
Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
@ -856,18 +861,18 @@ static void GenerateFastApiDirectCall(MacroAssembler* masm,
} else {
__ li(t2, call_data);
}
// Store call data.
__ sw(t2, MemOperand(sp, 3 * kPointerSize));
// Store isolate.
__ li(t3, Operand(ExternalReference::isolate_address(masm->isolate())));
// Store JS function, call data, isolate ReturnValue default and ReturnValue.
__ sw(t1, MemOperand(sp, 1 * kPointerSize));
__ sw(t2, MemOperand(sp, 2 * kPointerSize));
__ sw(t3, MemOperand(sp, 3 * kPointerSize));
__ sw(t3, MemOperand(sp, 4 * kPointerSize));
// Store ReturnValue default and ReturnValue.
__ LoadRoot(t1, Heap::kUndefinedValueRootIndex);
__ sw(t1, MemOperand(sp, 4 * kPointerSize));
__ sw(t1, MemOperand(sp, 5 * kPointerSize));
__ sw(t1, MemOperand(sp, 6 * kPointerSize));
// Prepare arguments.
__ Addu(a2, sp, Operand(5 * kPointerSize));
__ Addu(a2, sp, Operand((kFastApiCallArguments - 1) * kPointerSize));
// Allocate the v8::Arguments structure in the arguments' space since
// it's not controlled by GC.
@ -906,12 +911,18 @@ static void GenerateFastApiDirectCall(MacroAssembler* masm,
masm->isolate());
AllowExternalCallThatCantCauseGC scope(masm);
MemOperand context_restore_operand(
fp, 2 * kPointerSize);
MemOperand return_value_operand(
fp, (kFastApiCallArguments + 1) * kPointerSize);
__ CallApiFunctionAndReturn(ref,
function_address,
thunk_ref,
a1,
kStackUnwindSpace,
kFastApiCallArguments + 1);
return_value_operand,
restore_context ?
&context_restore_operand : NULL);
}
@ -926,10 +937,12 @@ static void GenerateFastApiCall(MacroAssembler* masm,
ASSERT(!receiver.is(scratch));
const int stack_space = kFastApiCallArguments + argc + 1;
const int kHolderIndex = kFastApiCallArguments +
FunctionCallbackArguments::kHolderIndex - 1;
// Assign stack space for the call arguments.
__ Subu(sp, sp, Operand(stack_space * kPointerSize));
// Write holder to stack frame.
__ sw(receiver, MemOperand(sp, 0));
__ sw(receiver, MemOperand(sp, kHolderIndex * kPointerSize));
// Write receiver to stack frame.
int index = stack_space - 1;
__ sw(receiver, MemOperand(sp, index * kPointerSize));
@ -940,7 +953,7 @@ static void GenerateFastApiCall(MacroAssembler* masm,
__ sw(receiver, MemOperand(sp, index-- * kPointerSize));
}
GenerateFastApiDirectCall(masm, optimization, argc);
GenerateFastApiDirectCall(masm, optimization, argc, true);
}
@ -1054,7 +1067,8 @@ class CallInterceptorCompiler BASE_EMBEDDED {
// Invoke function.
if (can_do_fast_api_call) {
GenerateFastApiDirectCall(masm, optimization, arguments_.immediate());
GenerateFastApiDirectCall(
masm, optimization, arguments_.immediate(), false);
} else {
CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_)
? CALL_AS_FUNCTION
@ -1181,6 +1195,8 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
int save_at_depth,
Label* miss,
PrototypeCheckType check) {
const int kHolderIndex = kFastApiCallArguments +
FunctionCallbackArguments::kHolderIndex - 1;
// Make sure that the type feedback oracle harvests the receiver map.
// TODO(svenpanne) Remove this hack when all ICs are reworked.
__ li(scratch1, Operand(Handle<Map>(object->map())));
@ -1196,7 +1212,7 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
int depth = 0;
if (save_at_depth == depth) {
__ sw(reg, MemOperand(sp));
__ sw(reg, MemOperand(sp, kHolderIndex * kPointerSize));
}
// Check the maps in the prototype chain.
@ -1254,7 +1270,7 @@ Register StubCompiler::CheckPrototypes(Handle<JSObject> object,
}
if (save_at_depth == depth) {
__ sw(reg, MemOperand(sp));
__ sw(reg, MemOperand(sp, kHolderIndex * kPointerSize));
}
// Go to the next object in the prototype chain.
@ -1454,7 +1470,7 @@ void BaseLoadStubCompiler::GenerateLoadCallback(
// (second argument - a1) = AccessorInfo&
__ Addu(a1, sp, kPointerSize);
const int kStackUnwindSpace = kFastApiCallArguments + 1;
const int kStackUnwindSpace = PropertyCallbackArguments::kArgsLength + 1;
Address getter_address = v8::ToCData<Address>(callback->getter());
ApiFunction fun(getter_address);
ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL;
@ -1471,7 +1487,8 @@ void BaseLoadStubCompiler::GenerateLoadCallback(
thunk_ref,
a2,
kStackUnwindSpace,
6);
MemOperand(fp, 6 * kPointerSize),
NULL);
}
@ -2554,7 +2571,7 @@ Handle<Code> CallStubCompiler::CompileFastApiCall(
CheckPrototypes(Handle<JSObject>::cast(object), a1, holder, a0, a3, t0, name,
depth, &miss);
GenerateFastApiDirectCall(masm(), optimization, argc);
GenerateFastApiDirectCall(masm(), optimization, argc, false);
__ bind(&miss);
FreeSpaceForFastApiCall(masm());