Index: src/ia32/code-stubs-ia32.cc |
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc |
index 48b59996e9350e1a6dec91aad205d62f2f3edb76..a935e12b6ca6f18d659ec99ef84a3edfd47efb5c 100644 |
--- a/src/ia32/code-stubs-ia32.cc |
+++ b/src/ia32/code-stubs-ia32.cc |
@@ -5382,6 +5382,122 @@ void InternalArrayConstructorStub::Generate(MacroAssembler* masm) { |
} |
+void CallApiFunctionStub::Generate(MacroAssembler* masm) { |
+ // ----------- S t a t e ------------- |
+ // -- eax : callee |
+ // -- ebx : call_data |
+ // -- ecx : holder |
+ // -- edx : api_function_address |
+ // -- esi : context |
+ // -- |
+ // -- esp[0] : return address |
+ // -- esp[4] : last argument |
+ // -- ... |
+ // -- esp[argc * 4] : first argument |
+ // -- esp[(argc + 1) * 4] : receiver |
+ // ----------------------------------- |
+ |
+ Register callee = eax; |
+ Register call_data = ebx; |
+ Register holder = ecx; |
+ Register api_function_address = edx; |
+ Register return_address = edi; |
+ Register context = esi; |
+ |
+ 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(); |
+ |
+ __ pop(return_address); |
+ |
+ // context save |
+ __ push(context); |
+ // load context from callee |
+ __ mov(context, FieldOperand(callee, JSFunction::kContextOffset)); |
+ |
+ // callee |
+ __ push(callee); |
+ |
+ // call data |
+ __ push(call_data); |
+ |
+ Register scratch = call_data; |
+ if (!call_data_undefined) { |
+ // return value |
+ __ push(Immediate(isolate->factory()->undefined_value())); |
+ // return value default |
+ __ push(Immediate(isolate->factory()->undefined_value())); |
+ } else { |
+ // return value |
+ __ push(scratch); |
+ // return value default |
+ __ push(scratch); |
+ } |
+ // isolate |
+ __ push(Immediate(reinterpret_cast<int>(isolate))); |
+ // holder |
+ __ push(holder); |
+ |
+ __ mov(scratch, esp); |
+ |
+ // return address |
+ __ push(return_address); |
+ |
+ // API function gets reference to the v8::Arguments. If CPU profiler |
+ // is enabled wrapper function will be called and we need to pass |
+ // address of the callback as additional parameter, always allocate |
+ // space for it. |
+ const int kApiArgc = 1 + 1; |
+ |
+ // Allocate the v8::Arguments structure in the arguments' space since |
+ // it's not controlled by GC. |
+ const int kApiStackSpace = 4; |
+ |
+ __ PrepareCallApiFunction(kApiArgc + kApiStackSpace); |
+ |
+ // FunctionCallbackInfo::implicit_args_. |
+ __ mov(ApiParameterOperand(2), scratch); |
+ __ add(scratch, Immediate((argc + FCA::kArgsLength - 1) * kPointerSize)); |
+ // FunctionCallbackInfo::values_. |
+ __ mov(ApiParameterOperand(3), scratch); |
+ // FunctionCallbackInfo::length_. |
+ __ Set(ApiParameterOperand(4), Immediate(argc)); |
+ // FunctionCallbackInfo::is_construct_call_. |
+ __ Set(ApiParameterOperand(5), Immediate(0)); |
+ |
+ // v8::InvocationCallback's argument. |
+ __ lea(scratch, ApiParameterOperand(2)); |
+ __ mov(ApiParameterOperand(0), scratch); |
+ |
+ Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback); |
+ |
+ Operand context_restore_operand(ebp, |
+ (2 + FCA::kContextSaveIndex) * kPointerSize); |
+ Operand return_value_operand(ebp, |
+ (2 + FCA::kReturnValueOffset) * kPointerSize); |
+ __ CallApiFunctionAndReturn(api_function_address, |
+ thunk_address, |
+ ApiParameterOperand(1), |
+ argc + FCA::kArgsLength + 1, |
+ return_value_operand, |
+ restore_context ? |
+ &context_restore_operand : NULL); |
+} |
+ |
+ |
#undef __ |
} } // namespace v8::internal |