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 |