| Index: src/builtins/arm64/builtins-arm64.cc
|
| diff --git a/src/builtins/arm64/builtins-arm64.cc b/src/builtins/arm64/builtins-arm64.cc
|
| index 5a4e4c9e0086dd2d49e3dd585d9eb7ad0b61bc04..895ea5002c44ef246a5a039287fe963f9c8d0a1a 100644
|
| --- a/src/builtins/arm64/builtins-arm64.cc
|
| +++ b/src/builtins/arm64/builtins-arm64.cc
|
| @@ -4,6 +4,7 @@
|
|
|
| #if V8_TARGET_ARCH_ARM64
|
|
|
| +#include "src/api-arguments.h"
|
| #include "src/arm64/frames-arm64.h"
|
| #include "src/arm64/macro-assembler-arm64-inl.h"
|
| #include "src/codegen.h"
|
| @@ -2790,6 +2791,162 @@ static void CheckSpreadAndPushToStack(MacroAssembler* masm) {
|
| }
|
|
|
| // static
|
| +void Builtins::Generate_CallFunctionCallback(MacroAssembler* masm) {
|
| + ASM_LOCATION("Builtins::Generate_CallFunctionCallback");
|
| + // ----------- S t a t e -------------
|
| + // -- x0 : the number of arguments (not incl. the receiver)
|
| + // -- x1 : api function address
|
| + // -- sp[0] : holder
|
| + // -- sp[8] : isolate
|
| + // -- sp[16] : return value default
|
| + // -- sp[24] : return value
|
| + // -- sp[32] : call data
|
| + // -- sp[40] : target
|
| + // -- sp[48] : context save
|
| + // -- sp[56] : new.target
|
| + // -- sp[64] : last argument
|
| + // -- sp[56 + argc * 4] : first argument
|
| + // -- sp[64 + 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(x6, masm->StackPointer());
|
| +
|
| + // Allocate space for CallApiFunctionAndReturn can store some scratch
|
| + // registeres on the stack.
|
| + const int kCallApiFunctionSpillSpace = 4;
|
| +
|
| + // 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, x10, kApiStackSpace + kCallApiFunctionSpillSpace);
|
| + // x3 = FunctionCallbackInfo&
|
| + // Arguments is after the return address.
|
| + __ Add(x3, masm->StackPointer(), 1 * kPointerSize);
|
| + // Initialize FunctionCallbackInfo::implicit_args_ and
|
| + // FunctionCallbackInfo::values_.
|
| + __ Add(x10, x6, Operand(x0, LSL, kPointerSizeLog2));
|
| + __ Add(x10, x10, Operand((FCA::kArgsLength - 1) * kPointerSize));
|
| + __ Stp(x6, x10, MemOperand(x3, 0 * kPointerSize));
|
| + // FunctionCallbackInfo::length_ = argc
|
| + __ Str(x0, MemOperand(x3, 2 * kPointerSize));
|
| +
|
| + // Load first argument with pointer to FunctionCallbackInfo.
|
| + __ Mov(x0, x3);
|
| +
|
| + // 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.
|
| + // We will need to restore the HandleScope after the call to the API function,
|
| + // by allocating it in callee-save registers they will be preserved by C code.
|
| + Register handle_scope_base = x22;
|
| + Register next_address_reg = x19;
|
| + Register limit_reg = x20;
|
| + Register level_reg = w21;
|
| + __ Mov(handle_scope_base,
|
| + ExternalReference::handle_scope_next_address(masm->isolate()));
|
| + __ Ldr(next_address_reg, MemOperand(handle_scope_base, kNextOffset));
|
| + __ Ldr(limit_reg, MemOperand(handle_scope_base, kLimitOffset));
|
| + __ Ldr(level_reg, MemOperand(handle_scope_base, kLevelOffset));
|
| + __ Add(level_reg, level_reg, 1);
|
| + __ Str(level_reg, MemOperand(handle_scope_base, kLevelOffset));
|
| +
|
| + // Check if profiling is active, and if so call the function indirectly
|
| + // via the invoke_function_callback helper.
|
| + Label call_indirect, done_call;
|
| + __ Mov(x10, ExternalReference::is_profiling_address(masm->isolate()));
|
| + __ Ldrb(w10, MemOperand(x10));
|
| + __ Cbnz(w10, &call_indirect);
|
| + {
|
| + // 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, x1);
|
| + }
|
| + __ 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());
|
| + __ Mov(x3, ExternalReference::invoke_function_callback(masm->isolate()));
|
| + stub.GenerateCall(masm, x3);
|
| + }
|
| + __ Bind(&done_call);
|
| +
|
| + // No more valid handles (the result handle was the last one). Restore
|
| + // previous handle scope.
|
| + Label delete_allocated_handles;
|
| + __ Str(next_address_reg, MemOperand(handle_scope_base, kNextOffset));
|
| + __ Sub(level_reg, level_reg, 1);
|
| + __ Str(level_reg, MemOperand(handle_scope_base, kLevelOffset));
|
| + __ Ldr(x1, MemOperand(handle_scope_base, kLimitOffset));
|
| + __ Cmp(limit_reg, x1);
|
| + __ B(ne, &delete_allocated_handles);
|
| +
|
| + // Leave the API exit frame.
|
| + Label leave_exit_frame;
|
| + __ Bind(&leave_exit_frame);
|
| + __ Ldr(x0, MemOperand(fp, (2 + FCA::kReturnValueOffset) * kPointerSize));
|
| + __ Ldr(cp, MemOperand(fp, (2 + FCA::kContextSaveIndex) * kPointerSize));
|
| + __ Ldr(w2, MemOperand(masm->StackPointer(), 3 * kPointerSize));
|
| + __ LeaveExitFrame(false, x1, false);
|
| +
|
| + // Check if the function scheduled an exception.
|
| + Label promote_scheduled_exception;
|
| + __ Mov(x5, ExternalReference::scheduled_exception_address(masm->isolate()));
|
| + __ Ldr(x5, MemOperand(x5));
|
| + __ JumpIfNotRoot(x5, Heap::kTheHoleValueRootIndex,
|
| + &promote_scheduled_exception);
|
| +
|
| + // Check if the function returned a valid JavaScript value.
|
| + __ AssertApiCallResult(x0);
|
| +
|
| + // Drop the arguments and return.
|
| + __ Drop(x2);
|
| + __ Drop((FCA::kArgsLength + 1));
|
| + __ 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);
|
| + {
|
| + __ Str(limit_reg, MemOperand(handle_scope_base, kLimitOffset));
|
| + // Save the return value in a callee-save register.
|
| + __ Mov(x0, ExternalReference::isolate_address(masm->isolate()));
|
| + __ CallCFunction(
|
| + ExternalReference::delete_handle_scope_extensions(masm->isolate()), 1);
|
| + }
|
| + __ B(&leave_exit_frame);
|
| +}
|
| +
|
| +// static
|
| void Builtins::Generate_CallWithSpread(MacroAssembler* masm) {
|
| // ----------- S t a t e -------------
|
| // -- x0 : the number of arguments (not including the receiver)
|
|
|