| Index: src/arm/code-stubs-arm.cc
|
| diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
|
| index 8e9a3948dd55470453201ae70114070643f17a37..74d13e01961200520d6dc30b89baba56cff8f798 100644
|
| --- a/src/arm/code-stubs-arm.cc
|
| +++ b/src/arm/code-stubs-arm.cc
|
| @@ -5515,6 +5515,120 @@ void InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
|
| }
|
|
|
|
|
| +void CallApiFunctionStub::Generate(MacroAssembler* masm) {
|
| + // ----------- S t a t e -------------
|
| + // -- r0 : callee
|
| + // -- r4 : call_data
|
| + // -- r2 : holder
|
| + // -- r3 : api_function_address
|
| + // -- r1 : thunk_arg
|
| + // -- cp : context
|
| + // --
|
| + // -- esp[0] : last argument
|
| + // -- ...
|
| + // -- esp[(argc - 1)* 4] : first argument
|
| + // -- esp[argc * 4] : receiver
|
| + // -----------------------------------
|
| +
|
| + Register callee = r0;
|
| + Register call_data = r4;
|
| + Register holder = r2;
|
| + Register api_function_address = r3;
|
| + Register thunk_arg = r1;
|
| + Register context = cp;
|
| +
|
| + int argc = ArgumentBits::decode(bit_field_);
|
| + bool restore_context = RestoreContextBits::decode(bit_field_);
|
| + bool call_data_undefined = CallDataUndefinedBits::decode(bit_field_);
|
| +
|
| + typedef FunctionCallbackArguments FCA;
|
| +
|
| + 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 == 7);
|
| +
|
| + Isolate* isolate = masm->isolate();
|
| +
|
| + // context save
|
| + __ push(context);
|
| + // load context from callee
|
| + __ ldr(context, FieldMemOperand(callee, JSFunction::kContextOffset));
|
| +
|
| + // callee
|
| + __ push(callee);
|
| +
|
| + // call data
|
| + __ push(call_data);
|
| +
|
| + Register scratch = call_data;
|
| + if (!call_data_undefined) {
|
| + __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
|
| + }
|
| + // return value
|
| + __ push(scratch);
|
| + // return value default
|
| + __ push(scratch);
|
| + // isolate
|
| + __ mov(scratch,
|
| + Operand(ExternalReference::isolate_address(isolate)));
|
| + __ push(scratch);
|
| + // holder
|
| + __ push(holder);
|
| +
|
| + // Prepare arguments.
|
| + __ mov(scratch, sp);
|
| +
|
| + // Allocate the v8::Arguments structure in the arguments' space since
|
| + // it's not controlled by GC.
|
| + const int kApiStackSpace = 4;
|
| +
|
| + FrameScope frame_scope(masm, StackFrame::MANUAL);
|
| + __ EnterExitFrame(false, kApiStackSpace);
|
| +
|
| + ASSERT(!thunk_arg.is(r0) && !api_function_address.is(r0) && !scratch.is(r0));
|
| + // r0 = FunctionCallbackInfo&
|
| + // Arguments is after the return address.
|
| + __ add(r0, sp, Operand(1 * kPointerSize));
|
| + // FunctionCallbackInfo::implicit_args_
|
| + __ str(scratch, MemOperand(r0, 0 * kPointerSize));
|
| + // FunctionCallbackInfo::values_
|
| + __ add(ip, scratch, Operand((FCA::kArgsLength - 1 + argc) * kPointerSize));
|
| + __ str(ip, MemOperand(r0, 1 * kPointerSize));
|
| + // FunctionCallbackInfo::length_ = argc
|
| + __ mov(ip, Operand(argc));
|
| + __ str(ip, MemOperand(r0, 2 * kPointerSize));
|
| + // FunctionCallbackInfo::is_construct_call = 0
|
| + __ mov(ip, Operand::Zero());
|
| + __ str(ip, MemOperand(r0, 3 * kPointerSize));
|
| +
|
| + const int kStackUnwindSpace = argc + FCA::kArgsLength + 1;
|
| + Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback);
|
| + ExternalReference::Type thunk_type = ExternalReference::PROFILING_API_CALL;
|
| + ApiFunction thunk_fun(thunk_address);
|
| + ExternalReference thunk_ref = ExternalReference(&thunk_fun, thunk_type,
|
| + masm->isolate());
|
| +
|
| + AllowExternalCallThatCantCauseGC scope(masm);
|
| + MemOperand context_restore_operand(
|
| + fp, (2 + FCA::kContextSaveIndex) * kPointerSize);
|
| + MemOperand return_value_operand(fp,
|
| + (2 + FCA::kReturnValueOffset) * kPointerSize);
|
| +
|
| + __ CallApiFunctionAndReturn(api_function_address,
|
| + thunk_ref,
|
| + thunk_arg,
|
| + kStackUnwindSpace,
|
| + return_value_operand,
|
| + restore_context ?
|
| + &context_restore_operand : NULL);
|
| +}
|
| +
|
| +
|
| #undef __
|
|
|
| } } // namespace v8::internal
|
|
|