stub fast api calls
authordcarney@chromium.org <dcarney@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 27 Jan 2014 09:57:54 +0000 (09:57 +0000)
committerdcarney@chromium.org <dcarney@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 27 Jan 2014 09:57:54 +0000 (09:57 +0000)
R=verwaest@chromium.org, vervaest@chromium.org

BUG=

Review URL: https://codereview.chromium.org/140613004

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@18847 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

13 files changed:
src/arm/code-stubs-arm.cc
src/arm/macro-assembler-arm.cc
src/arm/macro-assembler-arm.h
src/arm/stub-cache-arm.cc
src/code-stubs.h
src/ia32/code-stubs-ia32.cc
src/ia32/macro-assembler-ia32.cc
src/ia32/macro-assembler-ia32.h
src/ia32/stub-cache-ia32.cc
src/x64/code-stubs-x64.cc
src/x64/macro-assembler-x64.cc
src/x64/macro-assembler-x64.h
src/x64/stub-cache-x64.cc

index 8e9a394..74d13e0 100644 (file)
@@ -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
index b8b39c9..cc7283b 100644 (file)
@@ -2298,8 +2298,7 @@ static int AddressOffset(ExternalReference ref0, ExternalReference ref1) {
 
 
 void MacroAssembler::CallApiFunctionAndReturn(
-    ExternalReference function,
-    Address function_address,
+    Register function_address,
     ExternalReference thunk_ref,
     Register thunk_last_arg,
     int stack_space,
@@ -2315,7 +2314,26 @@ void MacroAssembler::CallApiFunctionAndReturn(
       ExternalReference::handle_scope_level_address(isolate()),
       next_address);
 
-  ASSERT(!thunk_last_arg.is(r3));
+  ASSERT(function_address.is(r3));
+  ASSERT(thunk_last_arg.is(r1) || thunk_last_arg.is(r2));
+
+  Label profiler_disabled;
+  Label end_profiler_check;
+  bool* is_profiling_flag =
+      isolate()->cpu_profiler()->is_profiling_address();
+  STATIC_ASSERT(sizeof(*is_profiling_flag) == 1);
+  mov(r9, Operand(reinterpret_cast<int32_t>(is_profiling_flag)));
+  ldrb(r9, MemOperand(r9, 0));
+  cmp(r9, Operand(0));
+  b(eq, &profiler_disabled);
+
+  // Additional parameter is the address of the actual callback.
+  mov(r3, Operand(thunk_ref));
+  jmp(&end_profiler_check);
+
+  bind(&profiler_disabled);
+  Move(r3, function_address);
+  bind(&end_profiler_check);
 
   // Allocate HandleScope in callee-save registers.
   mov(r9, Operand(next_address));
@@ -2334,25 +2352,6 @@ void MacroAssembler::CallApiFunctionAndReturn(
     PopSafepointRegisters();
   }
 
-  Label profiler_disabled;
-  Label end_profiler_check;
-  bool* is_profiling_flag =
-      isolate()->cpu_profiler()->is_profiling_address();
-  STATIC_ASSERT(sizeof(*is_profiling_flag) == 1);
-  mov(r3, Operand(reinterpret_cast<int32_t>(is_profiling_flag)));
-  ldrb(r3, MemOperand(r3, 0));
-  cmp(r3, Operand(0));
-  b(eq, &profiler_disabled);
-
-  // Additional parameter is the address of the actual callback.
-  mov(thunk_last_arg, Operand(reinterpret_cast<int32_t>(function_address)));
-  mov(r3, Operand(thunk_ref));
-  jmp(&end_profiler_check);
-
-  bind(&profiler_disabled);
-  mov(r3, Operand(function));
-  bind(&end_profiler_check);
-
   // Native call returns to the DirectCEntry stub which redirects to the
   // return address pushed on stack (could have moved after GC).
   // DirectCEntry stub itself is generated early and never moves.
index 9d4c128..1e774e8 100644 (file)
@@ -1134,8 +1134,7 @@ class MacroAssembler: public Assembler {
   // from handle and propagates exceptions.  Restores context.  stack_space
   // - space to be unwound on exit (includes the call JS arguments space and
   // the additional space allocated for the fast call).
-  void CallApiFunctionAndReturn(ExternalReference function,
-                                Address function_address,
+  void CallApiFunctionAndReturn(Register function_address,
                                 ExternalReference thunk_ref,
                                 Register thunk_last_arg,
                                 int stack_space,
index 987437b..9ad7d2a 100644 (file)
@@ -777,127 +777,56 @@ static void CompileCallLoadPropertyWithInterceptor(
 }
 
 
-static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength;
-
-
 static void GenerateFastApiCallBody(MacroAssembler* masm,
                                     const CallOptimization& optimization,
                                     int argc,
-                                    Register holder,
-                                    Register scratch1,
-                                    Register scratch2,
-                                    Register scratch3,
+                                    Register holder_in,
                                     bool restore_context) {
-  // ----------- S t a t e -------------
-  //  -- sp[0]              : last JS argument
-  //  -- ...
-  //  -- sp[(argc - 1) * 4] : first JS argument
-  //  -- sp[argc * 4]       : receiver
-  // -----------------------------------
   ASSERT(optimization.is_simple_api_call());
 
-  typedef FunctionCallbackArguments FCA;
-
-  STATIC_ASSERT(FCA::kHolderIndex == 0);
-  STATIC_ASSERT(FCA::kIsolateIndex == 1);
-  STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
-  STATIC_ASSERT(FCA::kReturnValueOffset == 3);
-  STATIC_ASSERT(FCA::kDataIndex == 4);
-  STATIC_ASSERT(FCA::kCalleeIndex == 5);
-  STATIC_ASSERT(FCA::kContextSaveIndex == 6);
-  STATIC_ASSERT(FCA::kArgsLength == 7);
+  // Abi for CallApiFunctionStub.
+  Register callee = r0;
+  Register call_data = r4;
+  Register holder = r2;
+  Register api_function_address = r3;
+  Register thunk_arg = r1;
 
-  ASSERT(!holder.is(cp));
+  // Put holder in place.
+  __ Move(holder, holder_in);
 
-  // Save calling context.
-  __ push(cp);
-  // Get the function and setup the context.
+  Isolate* isolate = masm->isolate();
   Handle<JSFunction> function = optimization.constant_function();
-  __ Move(scratch1, function);
-  __ ldr(cp, FieldMemOperand(scratch1, JSFunction::kContextOffset));
-  __ push(scratch1);
-
-  // Construct the FunctionCallbackInfo.
   Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
-  Handle<Object> call_data(api_call_info->data(), masm->isolate());
+  Handle<Object> call_data_obj(api_call_info->data(), isolate);
+
+  // Put callee in place.
+  __ Move(callee, function);
+
   bool call_data_undefined = false;
-  if (masm->isolate()->heap()->InNewSpace(*call_data)) {
-    __ Move(scratch1, api_call_info);
-    __ ldr(scratch1, FieldMemOperand(scratch1, CallHandlerInfo::kDataOffset));
-  }  else if (call_data->IsUndefined()) {
+  // Put call_data in place.
+  if (isolate->heap()->InNewSpace(*call_data_obj)) {
+    __ Move(call_data, api_call_info);
+    __ ldr(call_data, FieldMemOperand(call_data, CallHandlerInfo::kDataOffset));
+  } else if (call_data_obj->IsUndefined()) {
     call_data_undefined = true;
-    __ LoadRoot(scratch3, Heap::kUndefinedValueRootIndex);
+    __ LoadRoot(call_data, Heap::kUndefinedValueRootIndex);
   } else {
-    __ Move(scratch1, call_data);
+    __ Move(call_data, call_data_obj);
   }
-  // Store call data.
-  __ push(scratch1);
-  if (!call_data_undefined) {
-    __ LoadRoot(scratch1, Heap::kUndefinedValueRootIndex);
-  }
-  // Store ReturnValue default and ReturnValue.
-  __ LoadRoot(scratch1, Heap::kUndefinedValueRootIndex);
-  __ push(scratch1);
-  __ push(scratch1);
-  // Store isolate.
-  __ mov(scratch1,
-         Operand(ExternalReference::isolate_address(masm->isolate())));
-  __ push(scratch1);
-  // holder
-  __ push(holder);
 
-  // Prepare arguments.
-  __ mov(r2, 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);
-
-  // r0 = FunctionCallbackInfo&
-  // Arguments is after the return address.
-  __ add(r0, sp, Operand(1 * kPointerSize));
-  // FunctionCallbackInfo::implicit_args_
-  __ str(r2, MemOperand(r0, 0 * kPointerSize));
-  // FunctionCallbackInfo::values_
-  __ add(ip, r2, Operand((kFastApiCallArguments - 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 + kFastApiCallArguments + 1;
+  // Put api_function_address in place.
   Address function_address = v8::ToCData<Address>(api_call_info->callback());
   ApiFunction fun(function_address);
   ExternalReference::Type type = ExternalReference::DIRECT_API_CALL;
   ExternalReference ref = ExternalReference(&fun,
                                             type,
                                             masm->isolate());
-  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());
+  __ mov(api_function_address, Operand(ref));
+  __ mov(thunk_arg, Operand(reinterpret_cast<int32_t>(function_address)));
 
-  AllowExternalCallThatCantCauseGC scope(masm);
-  MemOperand context_restore_operand(
-      fp, (2 + FCA::kContextSaveIndex) * kPointerSize);
-  MemOperand return_value_operand(fp,
-                                  (2 + FCA::kReturnValueOffset) * kPointerSize);
-
-  __ CallApiFunctionAndReturn(ref,
-                              function_address,
-                              thunk_ref,
-                              r1,
-                              kStackUnwindSpace,
-                              return_value_operand,
-                              restore_context ?
-                                  &context_restore_operand : NULL);
+  // Jump to stub.
+  CallApiFunctionStub stub(restore_context, call_data_undefined, argc);
+  __ TailCallStub(&stub);
 }
 
 
@@ -911,7 +840,7 @@ static void GenerateFastApiCall(MacroAssembler* masm,
   __ IncrementCounter(counters->call_const_fast_api(), 1, r0, r1);
 
   // Move holder to a register
-  Register holder_reg = r0;
+  Register holder_reg = r2;
   switch (holder_lookup) {
     case CallOptimization::kHolderIsReceiver:
       {
@@ -938,9 +867,6 @@ static void GenerateFastApiCall(MacroAssembler* masm,
                           optimization,
                           argc,
                           holder_reg,
-                          r1,
-                          r2,
-                          r3,
                           false);
 }
 
@@ -961,21 +887,11 @@ static void GenerateFastApiCall(MacroAssembler* masm,
     ASSERT(!scratch.is(arg));
     __ push(arg);
   }
-  Register scratch1 = r0;
-  Register scratch2 = r1;
-  Register scratch3 = r2;
-  if (!r3.is(receiver)) {
-    __ mov(r3, receiver);
-    receiver = r3;
-  }
   // Stack now matches JSFunction abi.
   GenerateFastApiCallBody(masm,
                           optimization,
                           argc,
                           receiver,
-                          scratch1,
-                          scratch2,
-                          scratch3,
                           true);
 }
 
@@ -1423,6 +1339,10 @@ void LoadStubCompiler::GenerateLoadCallback(
   ApiFunction fun(getter_address);
   ExternalReference::Type type = ExternalReference::DIRECT_GETTER_CALL;
   ExternalReference ref = ExternalReference(&fun, type, isolate());
+  Register getter_address_reg = r3;
+  Register thunk_last_arg = r2;
+  __ mov(getter_address_reg, Operand(ref));
+  __ mov(thunk_last_arg, Operand(reinterpret_cast<int32_t>(getter_address)));
 
   Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback);
   ExternalReference::Type thunk_type =
@@ -1430,10 +1350,9 @@ void LoadStubCompiler::GenerateLoadCallback(
   ApiFunction thunk_fun(thunk_address);
   ExternalReference thunk_ref = ExternalReference(&thunk_fun, thunk_type,
       isolate());
-  __ CallApiFunctionAndReturn(ref,
-                              getter_address,
+  __ CallApiFunctionAndReturn(getter_address_reg,
                               thunk_ref,
-                              r2,
+                              thunk_last_arg,
                               kStackUnwindSpace,
                               MemOperand(fp, 6 * kPointerSize),
                               NULL);
index 8fb74b5..63e9f07 100644 (file)
@@ -96,6 +96,7 @@ namespace internal {
   V(InternalArrayConstructor)            \
   V(ProfileEntryHook)                    \
   V(StoreGlobal)                         \
+  V(CallApiFunction)                     \
   /* IC Handler stubs */                 \
   V(LoadField)                           \
   V(KeyedLoadField)                      \
@@ -1035,6 +1036,32 @@ class StoreGlobalStub : public HandlerStub {
 };
 
 
+class CallApiFunctionStub : public PlatformCodeStub {
+ public:
+  CallApiFunctionStub(bool restore_context,
+                      bool call_data_undefined,
+                      int argc) {
+    bit_field_ =
+        RestoreContextBits::encode(restore_context) |
+        CallDataUndefinedBits::encode(call_data_undefined) |
+        ArgumentBits::encode(argc);
+  }
+
+ private:
+  virtual void Generate(MacroAssembler* masm) V8_OVERRIDE;
+  virtual Major MajorKey() V8_OVERRIDE { return CallApiFunction; }
+  virtual int MinorKey() V8_OVERRIDE { return bit_field_; }
+
+  class RestoreContextBits: public BitField<bool, 0, 1> {};
+  class CallDataUndefinedBits: public BitField<bool, 1, 1> {};
+  class ArgumentBits: public BitField<int, 2, Code::kArgumentsBits> {};
+
+  int bit_field_;
+
+  DISALLOW_COPY_AND_ASSIGN(CallApiFunctionStub);
+};
+
+
 class KeyedLoadFieldStub: public LoadFieldStub {
  public:
   KeyedLoadFieldStub(bool inobject, int index, Representation representation)
index 48b5999..a935e12 100644 (file)
@@ -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
index 78ba28b..25598ce 100644 (file)
@@ -2297,7 +2297,7 @@ void MacroAssembler::PrepareCallApiFunction(int argc) {
 
 
 void MacroAssembler::CallApiFunctionAndReturn(
-    Address function_address,
+    Register function_address,
     Address thunk_address,
     Operand thunk_last_arg,
     int stack_space,
@@ -2310,6 +2310,7 @@ void MacroAssembler::CallApiFunctionAndReturn(
   ExternalReference level_address =
       ExternalReference::handle_scope_level_address(isolate());
 
+  ASSERT(edx.is(function_address));
   // Allocate HandleScope in callee-save registers.
   mov(ebx, Operand::StaticVariable(next_address));
   mov(edi, Operand::StaticVariable(limit_address));
@@ -2336,14 +2337,14 @@ void MacroAssembler::CallApiFunctionAndReturn(
   j(zero, &profiler_disabled);
 
   // Additional parameter is the address of the actual getter function.
-  mov(thunk_last_arg, Immediate(function_address));
+  mov(thunk_last_arg, function_address);
   // Call the api function.
   call(thunk_address, RelocInfo::RUNTIME_ENTRY);
   jmp(&end_profiler_check);
 
   bind(&profiler_disabled);
   // Call the api function.
-  call(function_address, RelocInfo::RUNTIME_ENTRY);
+  call(function_address);
   bind(&end_profiler_check);
 
   if (FLAG_log_timer_events) {
index e109b20..2628382 100644 (file)
@@ -815,7 +815,7 @@ class MacroAssembler: public Assembler {
   // from handle and propagates exceptions.  Clobbers ebx, edi and
   // caller-save registers.  Restores context.  On return removes
   // stack_space * kPointerSize (GCed).
-  void CallApiFunctionAndReturn(Address function_address,
+  void CallApiFunctionAndReturn(Register function_address,
                                 Address thunk_address,
                                 Operand thunk_last_arg,
                                 int stack_space,
index e76bfb5..d7f6845 100644 (file)
@@ -414,18 +414,53 @@ static void CompileCallLoadPropertyWithInterceptor(
 }
 
 
-// Number of pointers to be reserved on stack for fast API call.
-static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength;
-
-
 static void GenerateFastApiCallBody(MacroAssembler* masm,
                                     const CallOptimization& optimization,
                                     int argc,
-                                    Register holder,
-                                    Register scratch1,
-                                    Register scratch2,
-                                    Register scratch3,
-                                    bool restore_context);
+                                    Register holder_in,
+                                    bool restore_context) {
+  ASSERT(optimization.is_simple_api_call());
+
+  // Abi for CallApiFunctionStub.
+  Register callee = eax;
+  Register call_data = ebx;
+  Register holder = ecx;
+  Register api_function_address = edx;
+
+  // Put holder in place.
+  __ Move(holder, holder_in);
+
+  Register scratch = edi;
+
+  Isolate* isolate = masm->isolate();
+  Handle<JSFunction> function = optimization.constant_function();
+  Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
+  Handle<Object> call_data_obj(api_call_info->data(), isolate);
+
+  // Put callee in place.
+  __ LoadHeapObject(callee, function);
+
+  bool call_data_undefined = false;
+  // Put call_data in place.
+  if (isolate->heap()->InNewSpace(*call_data_obj)) {
+    __ mov(scratch, api_call_info);
+    __ mov(call_data, FieldOperand(scratch, CallHandlerInfo::kDataOffset));
+  } else if (call_data_obj->IsUndefined()) {
+    call_data_undefined = true;
+    __ mov(call_data, Immediate(isolate->factory()->undefined_value()));
+  } else {
+    __ mov(call_data, call_data_obj);
+  }
+
+  // Put api_function_address in place.
+  Address function_address = v8::ToCData<Address>(api_call_info->callback());
+  __ mov(api_function_address, Immediate(function_address));
+
+  // Jump to stub.
+  CallApiFunctionStub stub(restore_context, call_data_undefined, argc);
+  __ TailCallStub(&stub);
+}
+
 
 // Generates call to API function.
 static void GenerateFastApiCall(MacroAssembler* masm,
@@ -437,7 +472,7 @@ static void GenerateFastApiCall(MacroAssembler* masm,
   __ IncrementCounter(counters->call_const_fast_api(), 1);
 
   // Move holder to a register
-  Register holder_reg = eax;
+  Register holder_reg = ecx;
   switch (holder_lookup) {
     case CallOptimization::kHolderIsReceiver:
       {
@@ -463,9 +498,6 @@ static void GenerateFastApiCall(MacroAssembler* masm,
                           optimization,
                           argc,
                           holder_reg,
-                          ebx,
-                          ecx,
-                          edx,
                           false);
 }
 
@@ -478,8 +510,6 @@ static void GenerateFastApiCall(MacroAssembler* masm,
                                 const CallOptimization& optimization,
                                 Register receiver,
                                 Register scratch1,
-                                Register scratch2,
-                                Register scratch3,
                                 int argc,
                                 Register* values) {
   // Copy return value.
@@ -491,8 +521,6 @@ static void GenerateFastApiCall(MacroAssembler* masm,
     Register arg = values[argc-1-i];
     ASSERT(!receiver.is(arg));
     ASSERT(!scratch1.is(arg));
-    ASSERT(!scratch2.is(arg));
-    ASSERT(!scratch3.is(arg));
     __ push(arg);
   }
   __ push(scratch1);
@@ -501,124 +529,10 @@ static void GenerateFastApiCall(MacroAssembler* masm,
                           optimization,
                           argc,
                           receiver,
-                          scratch1,
-                          scratch2,
-                          scratch3,
                           true);
 }
 
 
-static void GenerateFastApiCallBody(MacroAssembler* masm,
-                                    const CallOptimization& optimization,
-                                    int argc,
-                                    Register holder,
-                                    Register scratch1,
-                                    Register scratch2,
-                                    Register scratch3,
-                                    bool restore_context) {
-  // ----------- S t a t e -------------
-  //  -- esp[0]              : return address
-  //  -- esp[4]              : last argument
-  //  -- ...
-  //  -- esp[argc * 4]       : first argument
-  //  -- esp[(argc + 1) * 4] : receiver
-  ASSERT(optimization.is_simple_api_call());
-
-  typedef FunctionCallbackArguments FCA;
-
-  STATIC_ASSERT(FCA::kHolderIndex == 0);
-  STATIC_ASSERT(FCA::kIsolateIndex == 1);
-  STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
-  STATIC_ASSERT(FCA::kReturnValueOffset == 3);
-  STATIC_ASSERT(FCA::kDataIndex == 4);
-  STATIC_ASSERT(FCA::kCalleeIndex == 5);
-  STATIC_ASSERT(FCA::kContextSaveIndex == 6);
-  STATIC_ASSERT(FCA::kArgsLength == 7);
-
-  __ pop(scratch1);
-
-  ASSERT(!holder.is(esi));
-  // context save
-  __ push(esi);
-
-  // Get the function and setup the context.
-  Handle<JSFunction> function = optimization.constant_function();
-  __ LoadHeapObject(scratch2, function);
-  __ mov(esi, FieldOperand(scratch2, JSFunction::kContextOffset));
-  // callee
-  __ push(scratch2);
-
-  Isolate* isolate = masm->isolate();
-  Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
-  Handle<Object> call_data(api_call_info->data(), isolate);
-  // Push data from ExecutableAccessorInfo.
-  if (isolate->heap()->InNewSpace(*call_data)) {
-    __ mov(scratch2, api_call_info);
-    __ mov(scratch3, FieldOperand(scratch2, CallHandlerInfo::kDataOffset));
-    __ push(scratch3);
-  } else {
-    __ push(Immediate(call_data));
-  }
-  // return value
-  __ push(Immediate(isolate->factory()->undefined_value()));
-  // return value default
-  __ push(Immediate(isolate->factory()->undefined_value()));
-  // isolate
-  __ push(Immediate(reinterpret_cast<int>(isolate)));
-  // holder
-  __ push(holder);
-
-  // store receiver address for GenerateFastApiCallBody
-  ASSERT(!scratch1.is(eax));
-  __ mov(eax, esp);
-
-  // return address
-  __ push(scratch1);
-
-  // 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;
-
-  // Function address is a foreign pointer outside V8's heap.
-  Address function_address = v8::ToCData<Address>(api_call_info->callback());
-  __ PrepareCallApiFunction(kApiArgc + kApiStackSpace);
-
-  // FunctionCallbackInfo::implicit_args_.
-  __ mov(ApiParameterOperand(2), eax);
-  __ add(eax, Immediate((argc + kFastApiCallArguments - 1) * kPointerSize));
-  // FunctionCallbackInfo::values_.
-  __ mov(ApiParameterOperand(3), eax);
-  // FunctionCallbackInfo::length_.
-  __ Set(ApiParameterOperand(4), Immediate(argc));
-  // FunctionCallbackInfo::is_construct_call_.
-  __ Set(ApiParameterOperand(5), Immediate(0));
-
-  // v8::InvocationCallback's argument.
-  __ lea(eax, ApiParameterOperand(2));
-  __ mov(ApiParameterOperand(0), eax);
-
-  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(function_address,
-                              thunk_address,
-                              ApiParameterOperand(1),
-                              argc + kFastApiCallArguments + 1,
-                              return_value_operand,
-                              restore_context ?
-                                  &context_restore_operand : NULL);
-}
-
-
 class CallInterceptorCompiler BASE_EMBEDDED {
  public:
   CallInterceptorCompiler(CallStubCompiler* stub_compiler,
@@ -1361,8 +1275,8 @@ void LoadStubCompiler::GenerateLoadField(Register reg,
 void LoadStubCompiler::GenerateLoadCallback(
     const CallOptimization& call_optimization) {
   GenerateFastApiCall(
-      masm(), call_optimization, receiver(), scratch1(),
-      scratch2(), name(), 0, NULL);
+      masm(), call_optimization, receiver(),
+      scratch1(), 0, NULL);
 }
 
 
@@ -1410,7 +1324,6 @@ void LoadStubCompiler::GenerateLoadCallback(
   // CPU profiler is active.
   const int kApiArgc = 2 + 1;
 
-  Address getter_address = v8::ToCData<Address>(callback->getter());
   __ PrepareCallApiFunction(kApiArgc);
   __ mov(ApiParameterOperand(0), ebx);  // name.
   __ add(ebx, Immediate(kPointerSize));
@@ -1421,6 +1334,10 @@ void LoadStubCompiler::GenerateLoadCallback(
   // garbage collection but instead return the allocation failure
   // object.
 
+  Register getter_address = edx;
+  Address function_address = v8::ToCData<Address>(callback->getter());
+  __ mov(getter_address, Immediate(function_address));
+
   Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback);
 
   __ CallApiFunctionAndReturn(getter_address,
@@ -1876,8 +1793,8 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
 
   Register values[] = { value() };
   GenerateFastApiCall(
-      masm(), call_optimization, receiver(), scratch1(),
-      scratch2(), this->name(), 1, values);
+      masm(), call_optimization, receiver(),
+      scratch1(), 1, values);
 
   // Return the generated code.
   return GetCode(kind(), Code::FAST, name);
index b8ef7de..74a265d 100644 (file)
@@ -5222,6 +5222,121 @@ void InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
 }
 
 
+void CallApiFunctionStub::Generate(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- rax                 : callee
+  //  -- rbx                 : call_data
+  //  -- rcx                 : holder
+  //  -- rdx                 : api_function_address
+  //  -- rsi                 : context
+  //  --
+  //  -- rsp[0]              : return address
+  //  -- rsp[8]              : last argument
+  //  -- ...
+  //  -- rsp[argc * 8]       : first argument
+  //  -- rsp[(argc + 1) * 8] : receiver
+  // -----------------------------------
+
+  Register callee = rax;
+  Register call_data = rbx;
+  Register holder = rcx;
+  Register api_function_address = rdx;
+  Register return_address = rdi;
+  Register context = rsi;
+
+  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);
+
+  __ PopReturnAddressTo(return_address);
+
+  // context save
+  __ push(context);
+  // load context from callee
+  __ movp(context, FieldOperand(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
+  __ Move(scratch,
+          ExternalReference::isolate_address(masm->isolate()));
+  __ push(scratch);
+  // holder
+  __ push(holder);
+
+  __ movp(scratch, rsp);
+  // Push return address back on stack.
+  __ PushReturnAddressFrom(return_address);
+
+  // Allocate the v8::Arguments structure in the arguments' space since
+  // it's not controlled by GC.
+  const int kApiStackSpace = 4;
+
+  __ PrepareCallApiFunction(kApiStackSpace);
+
+  // FunctionCallbackInfo::implicit_args_.
+  __ movp(StackSpaceOperand(0), scratch);
+  __ addq(scratch, Immediate((argc + FCA::kArgsLength - 1) * kPointerSize));
+  __ movp(StackSpaceOperand(1), scratch);  // FunctionCallbackInfo::values_.
+  __ Set(StackSpaceOperand(2), argc);  // FunctionCallbackInfo::length_.
+  // FunctionCallbackInfo::is_construct_call_.
+  __ Set(StackSpaceOperand(3), 0);
+
+#if defined(__MINGW64__) || defined(_WIN64)
+  Register arguments_arg = rcx;
+  Register callback_arg = rdx;
+#else
+  Register arguments_arg = rdi;
+  Register callback_arg = rsi;
+#endif
+
+  // It's okay if callback_arg == api_function_address
+  // but not arguments_arg
+  ASSERT(!api_function_address.is(arguments_arg));
+
+  // v8::InvocationCallback's argument.
+  __ lea(arguments_arg, StackSpaceOperand(0));
+
+  Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback);
+
+  StackArgumentsAccessor args_from_rbp(rbp, FCA::kArgsLength,
+                                       ARGUMENTS_DONT_CONTAIN_RECEIVER);
+  Operand context_restore_operand = args_from_rbp.GetArgumentOperand(
+      FCA::kArgsLength - 1 - FCA::kContextSaveIndex);
+  Operand return_value_operand = args_from_rbp.GetArgumentOperand(
+      FCA::kArgsLength - 1 - FCA::kReturnValueOffset);
+  __ CallApiFunctionAndReturn(
+      api_function_address,
+      thunk_address,
+      callback_arg,
+      argc + FCA::kArgsLength + 1,
+      return_value_operand,
+      restore_context ? &context_restore_operand : NULL);
+}
+
+
 #undef __
 
 } }  // namespace v8::internal
index 1fa2c8d..94b3f40 100644 (file)
@@ -671,7 +671,7 @@ void MacroAssembler::PrepareCallApiFunction(int arg_stack_space) {
 
 
 void MacroAssembler::CallApiFunctionAndReturn(
-    Address function_address,
+    Register function_address,
     Address thunk_address,
     Register thunk_last_arg,
     int stack_space,
@@ -697,6 +697,7 @@ void MacroAssembler::CallApiFunctionAndReturn(
   ExternalReference scheduled_exception_address =
       ExternalReference::scheduled_exception_address(isolate());
 
+  ASSERT(rdx.is(function_address));
   // Allocate HandleScope in callee-save registers.
   Register prev_next_address_reg = r14;
   Register prev_limit_reg = rbx;
@@ -726,14 +727,13 @@ void MacroAssembler::CallApiFunctionAndReturn(
   j(zero, &profiler_disabled);
 
   // Third parameter is the address of the actual getter function.
-  Move(thunk_last_arg, function_address, RelocInfo::EXTERNAL_REFERENCE);
+  Move(thunk_last_arg, function_address);
   Move(rax, thunk_address, RelocInfo::EXTERNAL_REFERENCE);
   jmp(&end_profiler_check);
 
   bind(&profiler_disabled);
   // Call the api function!
-  Move(rax, reinterpret_cast<Address>(function_address),
-       RelocInfo::EXTERNAL_REFERENCE);
+  Move(rax, function_address);
 
   bind(&end_profiler_check);
 
index 048eff1..c3fd782 100644 (file)
@@ -1309,7 +1309,7 @@ class MacroAssembler: public Assembler {
   // from handle and propagates exceptions.  Clobbers r14, r15, rbx and
   // caller-save registers.  Restores context.  On return removes
   // stack_space * kPointerSize (GCed).
-  void CallApiFunctionAndReturn(Address function_address,
+  void CallApiFunctionAndReturn(Register function_address,
                                 Address thunk_address,
                                 Register thunk_last_arg,
                                 int stack_space,
index b579e94..fce9b92 100644 (file)
@@ -388,18 +388,53 @@ static void CompileCallLoadPropertyWithInterceptor(
 }
 
 
-// Number of pointers to be reserved on stack for fast API call.
-static const int kFastApiCallArguments = FunctionCallbackArguments::kArgsLength;
-
-
 static void GenerateFastApiCallBody(MacroAssembler* masm,
                                     const CallOptimization& optimization,
                                     int argc,
-                                    Register holder,
-                                    Register scratch1,
-                                    Register scratch2,
-                                    Register scratch3,
-                                    bool restore_context);
+                                    Register holder_in,
+                                    bool restore_context) {
+  ASSERT(optimization.is_simple_api_call());
+
+  // Abi for CallApiFunctionStub.
+  Register callee = rax;
+  Register call_data = rbx;
+  Register holder = rcx;
+  Register api_function_address = rdx;
+
+  // Put holder in place.
+  __ Move(holder, holder_in);
+
+  Register scratch = rdi;
+
+  Isolate* isolate = masm->isolate();
+  Handle<JSFunction> function = optimization.constant_function();
+  Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
+  Handle<Object> call_data_obj(api_call_info->data(), isolate);
+
+  // Put callee in place.
+  __ Move(callee, function);
+
+  bool call_data_undefined = false;
+  // Put call_data in place.
+  if (isolate->heap()->InNewSpace(*call_data_obj)) {
+    __ Move(scratch, api_call_info);
+    __ movp(call_data, FieldOperand(scratch, CallHandlerInfo::kDataOffset));
+  } else if (call_data_obj->IsUndefined()) {
+    call_data_undefined = true;
+    __ LoadRoot(call_data, Heap::kUndefinedValueRootIndex);
+  } else {
+    __ Move(call_data, call_data_obj);
+  }
+
+  // Put api_function_address in place.
+  Address function_address = v8::ToCData<Address>(api_call_info->callback());
+  __ Move(
+      api_function_address, function_address, RelocInfo::EXTERNAL_REFERENCE);
+
+  // Jump to stub.
+  CallApiFunctionStub stub(restore_context, call_data_undefined, argc);
+  __ TailCallStub(&stub);
+}
 
 
 // Generates call to API function.
@@ -439,23 +474,15 @@ static void GenerateFastApiCall(MacroAssembler* masm,
                           optimization,
                           argc,
                           holder_reg,
-                          rbx,
-                          rcx,
-                          rdx,
                           false);
 }
 
 
 // Generate call to api function.
-// This function uses push() to generate smaller, faster code than
-// the version above. It is an optimization that should will be removed
-// when api call ICs are generated in hydrogen.
 static void GenerateFastApiCall(MacroAssembler* masm,
                                 const CallOptimization& optimization,
                                 Register receiver,
                                 Register scratch1,
-                                Register scratch2,
-                                Register scratch3,
                                 int argc,
                                 Register* values) {
   __ PopReturnAddressTo(scratch1);
@@ -466,8 +493,6 @@ static void GenerateFastApiCall(MacroAssembler* masm,
     Register arg = values[argc-1-i];
     ASSERT(!receiver.is(arg));
     ASSERT(!scratch1.is(arg));
-    ASSERT(!scratch2.is(arg));
-    ASSERT(!scratch3.is(arg));
     __ push(arg);
   }
   __ PushReturnAddressFrom(scratch1);
@@ -476,133 +501,10 @@ static void GenerateFastApiCall(MacroAssembler* masm,
                           optimization,
                           argc,
                           receiver,
-                          scratch1,
-                          scratch2,
-                          scratch3,
                           true);
 }
 
 
-static void GenerateFastApiCallBody(MacroAssembler* masm,
-                                    const CallOptimization& optimization,
-                                    int argc,
-                                    Register holder,
-                                    Register scratch1,
-                                    Register scratch2,
-                                    Register scratch3,
-                                    bool restore_context) {
-  // ----------- S t a t e -------------
-  //  -- rsp[0]              : return address
-  //  -- rsp[8]              : last argument
-  //  -- ...
-  //  -- rsp[argc * 8]       : first argument
-  //  -- rsp[(argc + 1) * 8] : receiver
-  // -----------------------------------
-  ASSERT(optimization.is_simple_api_call());
-
-  typedef FunctionCallbackArguments FCA;
-
-  STATIC_ASSERT(FCA::kHolderIndex == 0);
-  STATIC_ASSERT(FCA::kIsolateIndex == 1);
-  STATIC_ASSERT(FCA::kReturnValueDefaultValueIndex == 2);
-  STATIC_ASSERT(FCA::kReturnValueOffset == 3);
-  STATIC_ASSERT(FCA::kDataIndex == 4);
-  STATIC_ASSERT(FCA::kCalleeIndex == 5);
-  STATIC_ASSERT(FCA::kContextSaveIndex == 6);
-  STATIC_ASSERT(FCA::kArgsLength == 7);
-
-  __ PopReturnAddressTo(scratch1);
-
-  ASSERT(!holder.is(rsi));
-  // context save
-  __ push(rsi);
-
-  // Get the function and setup the context.
-  Handle<JSFunction> function = optimization.constant_function();
-  __ Move(scratch2, function);
-  __ push(scratch2);
-  __ movp(rsi, FieldOperand(scratch2, JSFunction::kContextOffset));
-
-  Isolate* isolate = masm->isolate();
-  Handle<CallHandlerInfo> api_call_info = optimization.api_call_info();
-  Handle<Object> call_data(api_call_info->data(), isolate);
-  // Push data from ExecutableAccessorInfo.
-  bool call_data_undefined = false;
-  if (isolate->heap()->InNewSpace(*call_data)) {
-    __ Move(scratch2, api_call_info);
-    __ movp(scratch3, FieldOperand(scratch2, CallHandlerInfo::kDataOffset));
-  } else if (call_data->IsUndefined()) {
-    call_data_undefined = true;
-    __ LoadRoot(scratch3, Heap::kUndefinedValueRootIndex);
-  } else {
-    __ Move(scratch3, call_data);
-  }
-  // call data
-  __ push(scratch3);
-  if (!call_data_undefined) {
-    __ LoadRoot(scratch3, Heap::kUndefinedValueRootIndex);
-  }
-  // return value
-  __ push(scratch3);
-  // return value default
-  __ push(scratch3);
-  // isolate
-  __ Move(scratch3,
-          ExternalReference::isolate_address(masm->isolate()));
-  __ push(scratch3);
-  // holder
-  __ push(holder);
-
-  ASSERT(!scratch1.is(rax));
-  __ movp(rax, rsp);
-  // Push return address back on stack.
-  __ PushReturnAddressFrom(scratch1);
-
-  // Function address is a foreign pointer outside V8's heap.
-  Address function_address = v8::ToCData<Address>(api_call_info->callback());
-
-  // Allocate the v8::Arguments structure in the arguments' space since
-  // it's not controlled by GC.
-  const int kApiStackSpace = 4;
-
-  __ PrepareCallApiFunction(kApiStackSpace);
-
-  __ movp(StackSpaceOperand(0), rax);  // FunctionCallbackInfo::implicit_args_.
-  __ addq(rax, Immediate((argc + kFastApiCallArguments - 1) * kPointerSize));
-  __ movp(StackSpaceOperand(1), rax);  // FunctionCallbackInfo::values_.
-  __ Set(StackSpaceOperand(2), argc);  // FunctionCallbackInfo::length_.
-  // FunctionCallbackInfo::is_construct_call_.
-  __ Set(StackSpaceOperand(3), 0);
-
-#if defined(__MINGW64__) || defined(_WIN64)
-  Register arguments_arg = rcx;
-  Register callback_arg = rdx;
-#else
-  Register arguments_arg = rdi;
-  Register callback_arg = rsi;
-#endif
-
-  // v8::InvocationCallback's argument.
-  __ lea(arguments_arg, StackSpaceOperand(0));
-
-  Address thunk_address = FUNCTION_ADDR(&InvokeFunctionCallback);
-
-  StackArgumentsAccessor args_from_rbp(rbp, kFastApiCallArguments,
-                                       ARGUMENTS_DONT_CONTAIN_RECEIVER);
-  Operand context_restore_operand = args_from_rbp.GetArgumentOperand(
-      kFastApiCallArguments - 1 - FCA::kContextSaveIndex);
-  Operand return_value_operand = args_from_rbp.GetArgumentOperand(
-      kFastApiCallArguments - 1 - FCA::kReturnValueOffset);
-  __ CallApiFunctionAndReturn(
-      function_address,
-      thunk_address,
-      callback_arg,
-      argc + kFastApiCallArguments + 1,
-      return_value_operand,
-      restore_context ? &context_restore_operand : NULL);
-}
-
-
 class CallInterceptorCompiler BASE_EMBEDDED {
  public:
   CallInterceptorCompiler(CallStubCompiler* stub_compiler,
@@ -1279,7 +1181,7 @@ void LoadStubCompiler::GenerateLoadCallback(
     const CallOptimization& call_optimization) {
   GenerateFastApiCall(
       masm(), call_optimization, receiver(),
-      scratch1(), scratch2(), name(), 0, NULL);
+      scratch1(), 0, NULL);
 }
 
 
@@ -1350,12 +1252,15 @@ void LoadStubCompiler::GenerateLoadCallback(
 
   Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback);
 
+  Register api_function_address = rdx;
+  __ Move(api_function_address, getter_address, RelocInfo::EXTERNAL_REFERENCE);
+
   // The name handler is counted as an argument.
   StackArgumentsAccessor args(rbp, PropertyCallbackArguments::kArgsLength);
   Operand return_value_operand = args.GetArgumentOperand(
       PropertyCallbackArguments::kArgsLength - 1 -
       PropertyCallbackArguments::kReturnValueOffset);
-  __ CallApiFunctionAndReturn(getter_address,
+  __ CallApiFunctionAndReturn(api_function_address,
                               thunk_address,
                               getter_arg,
                               kStackSpace,
@@ -1792,8 +1697,8 @@ Handle<Code> StoreStubCompiler::CompileStoreCallback(
 
   Register values[] = { value() };
   GenerateFastApiCall(
-      masm(), call_optimization, receiver(), scratch1(),
-      scratch2(), this->name(), 1, values);
+      masm(), call_optimization, receiver(),
+      scratch1(), 1, values);
 
   // Return the generated code.
   return GetCode(kind(), Code::FAST, name);