Index: src/mips/code-stubs-mips.cc |
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc |
index 29475eb9ab23fd288767745a205a1eb7db72f926..0d4844a982bc0c2096c8a7d4ccd75c5f9009962a 100644 |
--- a/src/mips/code-stubs-mips.cc |
+++ b/src/mips/code-stubs-mips.cc |
@@ -4833,6 +4833,145 @@ void InternalArrayConstructorStub::Generate(MacroAssembler* masm) { |
} |
+static int AddressOffset(ExternalReference ref0, ExternalReference ref1) { |
+ return ref0.address() - ref1.address(); |
+} |
+ |
+ |
+// Calls an API function. Allocates HandleScope, extracts returned value |
+// from handle and propagates exceptions. Restores context. stack_space |
+// - space to be unwound on exit (includes the call JS arguments space and |
+// the additional space allocated for the fast call). |
+static void CallApiFunctionAndReturn(MacroAssembler* masm, |
+ Register function_address, |
+ ExternalReference thunk_ref, |
+ int stack_space, |
+ MemOperand* stack_space_operand, |
+ MemOperand return_value_operand, |
+ MemOperand* context_restore_operand) { |
+ Isolate* isolate = masm->isolate(); |
+ ExternalReference next_address = |
+ ExternalReference::handle_scope_next_address(isolate); |
+ const int kNextOffset = 0; |
+ const int kLimitOffset = AddressOffset( |
+ ExternalReference::handle_scope_limit_address(isolate), next_address); |
+ const int kLevelOffset = AddressOffset( |
+ ExternalReference::handle_scope_level_address(isolate), next_address); |
+ |
+ DCHECK(function_address.is(a1) || function_address.is(a2)); |
+ |
+ Label profiler_disabled; |
+ Label end_profiler_check; |
+ __ li(t9, Operand(ExternalReference::is_profiling_address(isolate))); |
+ __ lb(t9, MemOperand(t9, 0)); |
+ __ Branch(&profiler_disabled, eq, t9, Operand(zero_reg)); |
+ |
+ // Additional parameter is the address of the actual callback. |
+ __ li(t9, Operand(thunk_ref)); |
+ __ jmp(&end_profiler_check); |
+ |
+ __ bind(&profiler_disabled); |
+ __ mov(t9, function_address); |
+ __ bind(&end_profiler_check); |
+ |
+ // Allocate HandleScope in callee-save registers. |
+ __ li(s3, Operand(next_address)); |
+ __ lw(s0, MemOperand(s3, kNextOffset)); |
+ __ lw(s1, MemOperand(s3, kLimitOffset)); |
+ __ lw(s2, MemOperand(s3, kLevelOffset)); |
+ __ Addu(s2, s2, Operand(1)); |
+ __ sw(s2, MemOperand(s3, kLevelOffset)); |
+ |
+ if (FLAG_log_timer_events) { |
+ FrameScope frame(masm, StackFrame::MANUAL); |
+ __ PushSafepointRegisters(); |
+ __ PrepareCallCFunction(1, a0); |
+ __ li(a0, Operand(ExternalReference::isolate_address(isolate))); |
+ __ CallCFunction(ExternalReference::log_enter_external_function(isolate), |
+ 1); |
+ __ PopSafepointRegisters(); |
+ } |
+ |
+ // Native call returns to the DirectCEntry stub which redirects to the |
+ // return address pushed on stack (could have moved after GC). |
+ // DirectCEntry stub itself is generated early and never moves. |
+ DirectCEntryStub stub(isolate); |
+ stub.GenerateCall(masm, t9); |
+ |
+ if (FLAG_log_timer_events) { |
+ FrameScope frame(masm, StackFrame::MANUAL); |
+ __ PushSafepointRegisters(); |
+ __ PrepareCallCFunction(1, a0); |
+ __ li(a0, Operand(ExternalReference::isolate_address(isolate))); |
+ __ CallCFunction(ExternalReference::log_leave_external_function(isolate), |
+ 1); |
+ __ PopSafepointRegisters(); |
+ } |
+ |
+ 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, return_value_operand); |
+ __ bind(&return_value_loaded); |
+ |
+ // No more valid handles (the result handle was the last one). Restore |
+ // previous handle scope. |
+ __ sw(s0, MemOperand(s3, kNextOffset)); |
+ if (__ emit_debug_code()) { |
+ __ lw(a1, MemOperand(s3, kLevelOffset)); |
+ __ Check(eq, kUnexpectedLevelAfterReturnFromApiCall, a1, Operand(s2)); |
+ } |
+ __ Subu(s2, s2, Operand(1)); |
+ __ sw(s2, MemOperand(s3, kLevelOffset)); |
+ __ lw(at, MemOperand(s3, kLimitOffset)); |
+ __ Branch(&delete_allocated_handles, ne, s1, Operand(at)); |
+ |
+ // Check if the function scheduled an exception. |
+ __ bind(&leave_exit_frame); |
+ __ LoadRoot(t0, Heap::kTheHoleValueRootIndex); |
+ __ 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); |
+ } |
+ 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(masm, StackFrame::INTERNAL); |
+ __ CallExternalReference( |
+ ExternalReference(Runtime::kPromoteScheduledException, isolate), 0); |
+ } |
+ __ jmp(&exception_handled); |
+ |
+ // HandleScope limit has changed. Delete allocated extensions. |
+ __ bind(&delete_allocated_handles); |
+ __ sw(s1, MemOperand(s3, kLimitOffset)); |
+ __ mov(s0, v0); |
+ __ mov(a0, v0); |
+ __ PrepareCallCFunction(1, s1); |
+ __ li(a0, Operand(ExternalReference::isolate_address(isolate))); |
+ __ CallCFunction(ExternalReference::delete_handle_scope_extensions(isolate), |
+ 1); |
+ __ mov(v0, s0); |
+ __ jmp(&leave_exit_frame); |
+} |
+ |
+ |
static void CallApiFunctionStubHelper(MacroAssembler* masm, |
const ParameterCount& argc, |
bool return_first_arg, |
@@ -4947,9 +5086,9 @@ static void CallApiFunctionStubHelper(MacroAssembler* masm, |
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); |
+ CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, stack_space, |
+ stack_space_operand, return_value_operand, |
+ &context_restore_operand); |
} |
@@ -4996,9 +5135,9 @@ void CallApiGetterStub::Generate(MacroAssembler* masm) { |
ExternalReference thunk_ref = |
ExternalReference::invoke_accessor_getter_callback(isolate()); |
- __ CallApiFunctionAndReturn(api_function_address, thunk_ref, |
- kStackUnwindSpace, NULL, |
- MemOperand(fp, 6 * kPointerSize), NULL); |
+ CallApiFunctionAndReturn(masm, api_function_address, thunk_ref, |
+ kStackUnwindSpace, NULL, |
+ MemOperand(fp, 6 * kPointerSize), NULL); |
} |