Revision: 18847
Author:   [email protected]
Date:     Mon Jan 27 09:57:54 2014 UTC
Log:      stub fast api calls

[email protected], [email protected]

BUG=

Review URL: https://codereview.chromium.org/140613004
http://code.google.com/p/v8/source/detail?r=18847

Modified:
 /branches/bleeding_edge/src/arm/code-stubs-arm.cc
 /branches/bleeding_edge/src/arm/macro-assembler-arm.cc
 /branches/bleeding_edge/src/arm/macro-assembler-arm.h
 /branches/bleeding_edge/src/arm/stub-cache-arm.cc
 /branches/bleeding_edge/src/code-stubs.h
 /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc
 /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc
 /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h
 /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc
 /branches/bleeding_edge/src/x64/code-stubs-x64.cc
 /branches/bleeding_edge/src/x64/macro-assembler-x64.cc
 /branches/bleeding_edge/src/x64/macro-assembler-x64.h
 /branches/bleeding_edge/src/x64/stub-cache-x64.cc

=======================================
--- /branches/bleeding_edge/src/arm/code-stubs-arm.cc Fri Jan 24 11:47:53 2014 UTC +++ /branches/bleeding_edge/src/arm/code-stubs-arm.cc Mon Jan 27 09:57:54 2014 UTC
@@ -5513,6 +5513,120 @@
   __ bind(&fast_elements_case);
   GenerateCase(masm, FAST_ELEMENTS);
 }
+
+
+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 __
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Thu Jan 23 13:02:27 2014 UTC +++ /branches/bleeding_edge/src/arm/macro-assembler-arm.cc Mon Jan 27 09:57:54 2014 UTC
@@ -2298,8 +2298,7 @@


 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 @@
       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));
@@ -2333,25 +2351,6 @@
CallCFunction(ExternalReference::log_enter_external_function(isolate()), 1);
     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).
=======================================
--- /branches/bleeding_edge/src/arm/macro-assembler-arm.h Wed Jan 15 17:00:35 2014 UTC +++ /branches/bleeding_edge/src/arm/macro-assembler-arm.h Mon Jan 27 09:57:54 2014 UTC
@@ -1134,8 +1134,7 @@
   // 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,
=======================================
--- /branches/bleeding_edge/src/arm/stub-cache-arm.cc Fri Jan 24 11:47:53 2014 UTC +++ /branches/bleeding_edge/src/arm/stub-cache-arm.cc Mon Jan 27 09:57:54 2014 UTC
@@ -775,129 +775,58 @@
       ExternalReference(IC_Utility(id), masm->isolate()),
       StubCache::kInterceptorArgsLength);
 }
-
-
-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;
+  // Abi for CallApiFunctionStub.
+  Register callee = r0;
+  Register call_data = r4;
+  Register holder = r2;
+  Register api_function_address = r3;
+  Register thunk_arg = r1;

-  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);
+  // Put holder in place.
+  __ Move(holder, holder_in);

-  ASSERT(!holder.is(cp));
-
-  // 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 @@
   __ 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 @@
                           optimization,
                           argc,
                           holder_reg,
-                          r1,
-                          r2,
-                          r3,
                           false);
 }

@@ -961,21 +887,11 @@
     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 @@
   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 @@
   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);
=======================================
--- /branches/bleeding_edge/src/code-stubs.h    Thu Jan 23 08:36:22 2014 UTC
+++ /branches/bleeding_edge/src/code-stubs.h    Mon Jan 27 09:57:54 2014 UTC
@@ -96,6 +96,7 @@
   V(InternalArrayConstructor)            \
   V(ProfileEntryHook)                    \
   V(StoreGlobal)                         \
+  V(CallApiFunction)                     \
   /* IC Handler stubs */                 \
   V(LoadField)                           \
   V(KeyedLoadField)                      \
@@ -1035,6 +1036,32 @@
 };


+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)
=======================================
--- /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Fri Jan 24 11:47:53 2014 UTC +++ /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Mon Jan 27 09:57:54 2014 UTC
@@ -5380,6 +5380,122 @@
   __ bind(&fast_elements_case);
   GenerateCase(masm, FAST_ELEMENTS);
 }
+
+
+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 __
=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Thu Jan 23 13:02:27 2014 UTC +++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Mon Jan 27 09:57:54 2014 UTC
@@ -2297,7 +2297,7 @@


 void MacroAssembler::CallApiFunctionAndReturn(
-    Address function_address,
+    Register function_address,
     Address thunk_address,
     Operand thunk_last_arg,
     int stack_space,
@@ -2310,6 +2310,7 @@
   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 @@
   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) {
=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h Wed Jan 15 17:00:35 2014 UTC +++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h Mon Jan 27 09:57:54 2014 UTC
@@ -815,7 +815,7 @@
   // 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,
=======================================
--- /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Fri Jan 24 11:47:53 2014 UTC +++ /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Mon Jan 27 09:57:54 2014 UTC
@@ -412,20 +412,55 @@
       ExternalReference(IC_Utility(id), masm->isolate()),
       StubCache::kInterceptorArgsLength);
 }
-
-
-// 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 @@
   __ 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 @@
                           optimization,
                           argc,
                           holder_reg,
-                          ebx,
-                          ecx,
-                          edx,
                           false);
 }

@@ -478,8 +510,6 @@
                                 const CallOptimization& optimization,
                                 Register receiver,
                                 Register scratch1,
-                                Register scratch2,
-                                Register scratch3,
                                 int argc,
                                 Register* values) {
   // Copy return value.
@@ -491,8 +521,6 @@
     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,123 +529,9 @@
                           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:
@@ -1361,8 +1275,8 @@
 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 @@
   // 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 @@
   // 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 @@

   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);
=======================================
--- /branches/bleeding_edge/src/x64/code-stubs-x64.cc Fri Jan 24 11:47:53 2014 UTC +++ /branches/bleeding_edge/src/x64/code-stubs-x64.cc Mon Jan 27 09:57:54 2014 UTC
@@ -5220,6 +5220,121 @@
   __ bind(&fast_elements_case);
   GenerateCase(masm, FAST_ELEMENTS);
 }
+
+
+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 __
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Fri Jan 24 01:45:53 2014 UTC +++ /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Mon Jan 27 09:57:54 2014 UTC
@@ -671,7 +671,7 @@


 void MacroAssembler::CallApiFunctionAndReturn(
-    Address function_address,
+    Register function_address,
     Address thunk_address,
     Register thunk_last_arg,
     int stack_space,
@@ -697,6 +697,7 @@
   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 @@
   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);

=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.h Fri Jan 24 01:45:53 2014 UTC +++ /branches/bleeding_edge/src/x64/macro-assembler-x64.h Mon Jan 27 09:57:54 2014 UTC
@@ -1309,7 +1309,7 @@
   // 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,
=======================================
--- /branches/bleeding_edge/src/x64/stub-cache-x64.cc Mon Jan 27 08:12:59 2014 UTC +++ /branches/bleeding_edge/src/x64/stub-cache-x64.cc Mon Jan 27 09:57:54 2014 UTC
@@ -386,20 +386,55 @@
       ExternalReference(IC_Utility(id), masm->isolate()),
       StubCache::kInterceptorArgsLength);
 }
-
-
-// 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 @@
                           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 @@
     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,132 +501,9 @@
                           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:
@@ -1279,7 +1181,7 @@
     const CallOptimization& call_optimization) {
   GenerateFastApiCall(
       masm(), call_optimization, receiver(),
-      scratch1(), scratch2(), name(), 0, NULL);
+      scratch1(), 0, NULL);
 }


@@ -1350,12 +1252,15 @@

   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 @@

   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);

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to