From d047afb4fef8c0aaa3d98cf33f16e3e4803617e7 Mon Sep 17 00:00:00 2001 From: "plind44@gmail.com" Date: Tue, 17 Sep 2013 19:10:48 +0000 Subject: [PATCH] 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 . git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16778 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/mips/code-stubs-mips.cc | 4 +-- src/mips/macro-assembler-mips.cc | 44 +++++++++++++++++-------- src/mips/macro-assembler-mips.h | 12 +++++-- src/mips/stub-cache-mips.cc | 69 +++++++++++++++++++++++++--------------- 4 files changed, 85 insertions(+), 44 deletions(-) diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc index e4f68f9..ee49b25 100644 --- a/src/mips/code-stubs-mips.cc +++ b/src/mips/code-stubs-mips.cc @@ -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) diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc index a85b0d8..465e8ab 100644 --- a/src/mips/macro-assembler-mips.cc +++ b/src/mips/macro-assembler-mips.cc @@ -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 diff --git a/src/mips/macro-assembler-mips.h b/src/mips/macro-assembler-mips.h index 75ded88..2d9c950 100644 --- a/src/mips/macro-assembler-mips.h +++ b/src/mips/macro-assembler-mips.h @@ -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, diff --git a/src/mips/stub-cache-mips.cc b/src/mips/stub-cache-mips.cc index 97bd872..e0cf1b6 100644 --- a/src/mips/stub-cache-mips.cc +++ b/src/mips/stub-cache-mips.cc @@ -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 function = optimization.constant_function(); __ LoadHeapObject(t1, function); __ lw(cp, FieldMemOperand(t1, JSFunction::kContextOffset)); + __ sw(t1, MemOperand(sp, 2 * kPointerSize)); // Pass the additional arguments. Handle 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 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(object->map()))); @@ -1196,7 +1212,7 @@ Register StubCompiler::CheckPrototypes(Handle 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 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
(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 CallStubCompiler::CompileFastApiCall( CheckPrototypes(Handle::cast(object), a1, holder, a0, a3, t0, name, depth, &miss); - GenerateFastApiDirectCall(masm(), optimization, argc); + GenerateFastApiDirectCall(masm(), optimization, argc, false); __ bind(&miss); FreeSpaceForFastApiCall(masm()); -- 2.7.4