Index: src/builtins/mips/builtins-mips.cc |
diff --git a/src/builtins/mips/builtins-mips.cc b/src/builtins/mips/builtins-mips.cc |
index 07244013868e82a79cf237e51e4dc00be1264758..7a2b875b67c3028764a348098a58c16b8561b891 100644 |
--- a/src/builtins/mips/builtins-mips.cc |
+++ b/src/builtins/mips/builtins-mips.cc |
@@ -4,6 +4,7 @@ |
#if V8_TARGET_ARCH_MIPS |
+#include "src/api-arguments.h" |
#include "src/codegen.h" |
#include "src/debug/debug.h" |
#include "src/deoptimizer.h" |
@@ -2696,6 +2697,157 @@ void Builtins::Generate_CallWithSpread(MacroAssembler* masm) { |
} |
// static |
+void Builtins::Generate_CallFunctionCallback(MacroAssembler* masm) { |
+ // ----------- S t a t e ------------- |
+ // -- a0 : the number of arguments (not incl. the receiver) |
+ // -- a1 : api function address |
+ // -- sp[0] : holder |
+ // -- sp[4] : isolate |
+ // -- sp[8] : return value default |
+ // -- sp[12] : return value |
+ // -- sp[16] : call data |
+ // -- sp[20] : target |
+ // -- sp[24] : context save |
+ // -- sp[28] : new.target |
+ // -- sp[32] : last argument |
+ // -- sp[28 + argc * 4] : first argument |
+ // -- sp[32 + argc * 4] : receiver |
+ // ----------------------------------- |
+ typedef FunctionCallbackArguments FCA; |
+ |
+ STATIC_ASSERT(FCA::kNewTargetIndex == 7); |
+ STATIC_ASSERT(FCA::kContextSaveIndex == 6); |
+ STATIC_ASSERT(FCA::kCalleeIndex == 5); |
+ STATIC_ASSERT(FCA::kDataIndex == 4); |
+ STATIC_ASSERT(FCA::kReturnValueOffset == 3); |
+ STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2); |
+ STATIC_ASSERT(FCA::kIsolateIndex == 1); |
+ STATIC_ASSERT(FCA::kHolderIndex == 0); |
+ STATIC_ASSERT(FCA::kArgsLength == 8); |
+ |
+ // Compute the pointer to the implicit args on the stack. |
+ __ mov(a2, sp); |
+ |
+ // Allocate the v8::FunctionCallbackInfo structure in the arguments' space |
+ // since it's not controlled by the GC. |
+ const int kApiStackSpace = 3; |
+ FrameScope frame_scope(masm, StackFrame::MANUAL); |
+ __ EnterExitFrame(false, kApiStackSpace); |
+ // a3 = FunctionCallbackInfo& |
+ // Arguments is after the return address. |
+ __ Addu(a3, sp, Operand(1 * kPointerSize)); |
+ // Initialize FunctionCallbackInfo::implicit_args_. |
+ __ sw(a2, MemOperand(a3, 0 * kPointerSize)); |
+ // Initialize FunctionCallbackInfo::values_. |
+ __ Lsa(at, a2, a0, kPointerSizeLog2); |
+ __ Addu(at, at, Operand((FCA::kArgsLength - 1) * kPointerSize)); |
+ __ sw(at, MemOperand(a3, 1 * kPointerSize)); |
+ // Initialize FunctionCallbackInfo::length_. |
+ __ sw(a0, MemOperand(a3, 2 * kPointerSize)); |
+ |
+ // Load first argument with pointer to FunctionCallbackInfo. |
+ __ mov(a0, a3); |
+ |
+ // TODO(bmeurer): Do we need this? |
+ AllowExternalCallThatCantCauseGC scope(masm); |
+ |
+ const int kNextOffset = 0; |
+ const int kLimitOffset = AddressOffset( |
+ ExternalReference::handle_scope_limit_address(masm->isolate()), |
+ ExternalReference::handle_scope_next_address(masm->isolate())); |
+ const int kLevelOffset = AddressOffset( |
+ ExternalReference::handle_scope_level_address(masm->isolate()), |
+ ExternalReference::handle_scope_next_address(masm->isolate())); |
+ |
+ // Allocate HandleScope in callee-save registers. |
+ __ li(s3, |
+ Operand(ExternalReference::handle_scope_next_address(masm->isolate()))); |
+ __ 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)); |
+ |
+ // Check if profiling is active, and if so call the function indirectly |
+ // via the invoke_function_callback helper. |
+ Label call_indirect, done_call; |
+ __ li(t9, Operand(ExternalReference::is_profiling_address(masm->isolate()))); |
+ __ lb(t9, MemOperand(t9, 0)); |
+ __ Branch(&call_indirect, ne, t9, Operand(zero_reg)); |
+ { |
+ // Call the API function directly. |
+ // TODO(all): Deprecate DirectCEntryStub usage here, since this builtin |
+ // is part of the snapshot and thus isn't relocated by the GC ever. |
+ DirectCEntryStub stub(masm->isolate()); |
+ stub.GenerateCall(masm, a1); |
+ } |
+ __ b(&done_call); |
+ __ bind(&call_indirect); |
+ { |
+ // Call the API function indirectly when profiling is on. |
+ // TODO(all): Deprecate DirectCEntryStub usage here, since this builtin |
+ // is part of the snapshot and thus isn't relocated by the GC ever. |
+ DirectCEntryStub stub(masm->isolate()); |
+ __ li( |
+ a3, |
+ Operand(ExternalReference::invoke_function_callback(masm->isolate()))); |
+ stub.GenerateCall(masm, a3); |
+ } |
+ __ bind(&done_call); |
+ |
+ // No more valid handles (the result handle was the last one). Restore |
+ // previous handle scope. |
+ Label delete_allocated_handles; |
+ __ sw(s0, MemOperand(s3, kNextOffset)); |
+ __ Subu(s2, s2, Operand(1)); |
+ __ sw(s2, MemOperand(s3, kLevelOffset)); |
+ __ lw(at, MemOperand(s3, kLimitOffset)); |
+ __ Branch(&delete_allocated_handles, ne, s1, Operand(at)); |
+ |
+ // Leave the API exit frame. |
+ Label leave_exit_frame; |
+ __ bind(&leave_exit_frame); |
+ __ lw(v0, MemOperand(fp, (2 + FCA::kReturnValueOffset) * kPointerSize)); |
+ __ lw(cp, MemOperand(fp, (2 + FCA::kContextSaveIndex) * kPointerSize)); |
+ // ExitFrame contains four MIPS argument slots after DirectCEntryStub call |
+ // so this must be accounted for. |
+ __ lw(s0, MemOperand(sp, 3 * kPointerSize + kCArgsSlotsSize)); |
+ __ LeaveExitFrame(false, no_reg, false); |
+ |
+ // Check if the function scheduled an exception. |
+ Label promote_scheduled_exception; |
+ __ li( |
+ at, |
+ Operand(ExternalReference::scheduled_exception_address(masm->isolate()))); |
+ __ lw(t1, MemOperand(at)); |
+ __ JumpIfNotRoot(t1, Heap::kTheHoleValueRootIndex, |
+ &promote_scheduled_exception); |
+ |
+ // Check if the function returned a valid JavaScript value. |
+ __ AssertApiCallResult(v0); |
+ |
+ // Drop the arguments and return. |
+ __ Addu(sp, sp, Operand((FCA::kArgsLength + 1) * kPointerSize)); |
+ __ Lsa(sp, sp, s0, kPointerSizeLog2); |
+ __ Ret(); |
+ |
+ // Re-throw by promoting a scheduled exception. |
+ __ bind(&promote_scheduled_exception); |
+ __ TailCallRuntime(Runtime::kPromoteScheduledException); |
+ |
+ // HandleScope limit has changed. Delete allocated extensions. |
+ __ bind(&delete_allocated_handles); |
+ { |
+ __ sw(s1, MemOperand(s3, kLimitOffset)); |
+ __ PrepareCallCFunction(1, s1); |
+ __ li(a0, Operand(ExternalReference::isolate_address(masm->isolate()))); |
+ __ CallCFunction( |
+ ExternalReference::delete_handle_scope_extensions(masm->isolate()), 1); |
+ } |
+ __ b(&leave_exit_frame); |
+} |
+ |
+// static |
void Builtins::Generate_ConstructFunction(MacroAssembler* masm) { |
// ----------- S t a t e ------------- |
// -- a0 : the number of arguments (not including the receiver) |