MIPS: stub fast api calls
authorpalfia@homejinni.com <palfia@homejinni.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 28 Jan 2014 01:35:20 +0000 (01:35 +0000)
committerpalfia@homejinni.com <palfia@homejinni.com@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 28 Jan 2014 01:35:20 +0000 (01:35 +0000)
Port r18847 (c920fc50)

BUG=
R=plind44@gmail.com

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

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

src/mips/code-stubs-mips.cc
src/mips/macro-assembler-mips.cc
src/mips/macro-assembler-mips.h
src/mips/stub-cache-mips.cc

index 8651b691ae3cc442f1397afbbec3274097f3c76e..ab1b90adae8d14ec2abb90a96aafef30af865fe1 100644 (file)
@@ -5692,6 +5692,109 @@ void InternalArrayConstructorStub::Generate(MacroAssembler* masm) {
 }
 
 
+void CallApiFunctionStub::Generate(MacroAssembler* masm) {
+  // ----------- S t a t e -------------
+  //  -- a0                  : callee
+  //  -- t0                  : call_data
+  //  -- a2                  : holder
+  //  -- a3                  : api_function_address
+  //  -- a1                  : thunk_arg
+  //  -- cp                  : context
+  //  --
+  //  -- sp[0]               : last argument
+  //  -- ...
+  //  -- sp[(argc - 1)* 4]   : first argument
+  //  -- sp[argc * 4]        : receiver
+  // -----------------------------------
+
+  Register callee = a0;
+  Register call_data = t0;
+  Register holder = a2;
+  Register api_function_address = a3;
+  Register thunk_arg = a1;
+  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();
+
+  // Save context, callee and call data.
+  __ Push(context, callee, call_data);
+  // Load context from callee.
+  __ lw(context, FieldMemOperand(callee, JSFunction::kContextOffset));
+
+  Register scratch = call_data;
+  if (!call_data_undefined) {
+    __ LoadRoot(scratch, Heap::kUndefinedValueRootIndex);
+  }
+  // Push return value and default return value.
+  __ Push(scratch, scratch);
+  __ li(scratch,
+        Operand(ExternalReference::isolate_address(isolate)));
+  // Push isolate and holder.
+  __ Push(scratch, 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(a0) && !api_function_address.is(a0) && !scratch.is(a0));
+  // a0 = FunctionCallbackInfo&
+  // Arguments is after the return address.
+  __ Addu(a0, sp, Operand(1 * kPointerSize));
+  // FunctionCallbackInfo::implicit_args_
+  __ sw(scratch, MemOperand(a0, 0 * kPointerSize));
+  // FunctionCallbackInfo::values_
+  __ Addu(at, scratch, Operand((FCA::kArgsLength - 1 + argc) * kPointerSize));
+  __ sw(at, MemOperand(a0, 1 * kPointerSize));
+  // FunctionCallbackInfo::length_ = argc
+  __ li(at, Operand(argc));
+  __ sw(at, MemOperand(a0, 2 * kPointerSize));
+  // FunctionCallbackInfo::is_construct_call = 0
+  __ sw(zero_reg, MemOperand(a0, 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 f8c037dedda9b51ad7007393403527e46ff90c43..517344857fbbab147bfa9665f1ddc4b3d3c7b7da 100644 (file)
@@ -3872,8 +3872,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,
@@ -3889,6 +3888,26 @@ void MacroAssembler::CallApiFunctionAndReturn(
       ExternalReference::handle_scope_level_address(isolate()),
       next_address);
 
+  ASSERT(function_address.is(a3));
+  ASSERT(thunk_last_arg.is(a1) || thunk_last_arg.is(a2));
+
+  Label profiler_disabled;
+  Label end_profiler_check;
+  bool* is_profiling_flag =
+      isolate()->cpu_profiler()->is_profiling_address();
+  STATIC_ASSERT(sizeof(*is_profiling_flag) == 1);
+  li(t9, reinterpret_cast<int32_t>(is_profiling_flag));
+  lb(t9, MemOperand(t9, 0));
+  Branch(&profiler_disabled, eq, t9, Operand(zero_reg));
+
+  // Additional parameter is the address of the actual callback.
+  li(t9, Operand(thunk_ref));
+  jmp(&end_profiler_check);
+
+  bind(&profiler_disabled);
+  mov(t9, function_address);
+  bind(&end_profiler_check);
+
   // Allocate HandleScope in callee-save registers.
   li(s3, Operand(next_address));
   lw(s0, MemOperand(s3, kNextOffset));
@@ -3906,25 +3925,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);
-  li(t9, reinterpret_cast<int32_t>(is_profiling_flag));
-  lb(t9, MemOperand(t9, 0));
-  beq(t9, zero_reg, &profiler_disabled);
-
-  // Third parameter is the address of the actual getter function.
-  li(thunk_last_arg, reinterpret_cast<int32_t>(function_address));
-  li(t9, Operand(thunk_ref));
-  jmp(&end_profiler_check);
-
-  bind(&profiler_disabled);
-  li(t9, 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 2e380622a47e8d8d69c9688d683f6fec88551f17..e4e027790462d578fb44addd8d6031a989e2bb15 100644 (file)
@@ -1276,8 +1276,7 @@ const Operand& rt = Operand(zero_reg), BranchDelaySlot bd = PROTECT
   // 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 ef98db59bb8288a52e746dbb9d0a79c9456a5acf..f90db7cdcd3ebda3154a30f218adbc3eaab01767 100644 (file)
@@ -765,98 +765,43 @@ 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 = a0;
+  Register call_data = t0;
+  Register holder = a2;
+  Register api_function_address = a3;
+  Register thunk_arg = a1;
 
-  ASSERT(!holder.is(cp));
+  // Put holder in place.
+  __ mov(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();
-  __ li(scratch1, function);
-  __ lw(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.
+  __ li(callee, function);
+
   bool call_data_undefined = false;
-  if (masm->isolate()->heap()->InNewSpace(*call_data)) {
-    __ li(scratch1, api_call_info);
-    __ lw(scratch1, FieldMemOperand(scratch1, CallHandlerInfo::kDataOffset));
-  }  else if (call_data->IsUndefined()) {
+  // Put call_data in place.
+  if (isolate->heap()->InNewSpace(*call_data_obj)) {
+    __ li(call_data, api_call_info);
+    __ lw(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 {
-    __ li(scratch1, call_data);
-  }
-  // Store call data.
-  __ push(scratch1);
-  if (!call_data_undefined) {
-    __ LoadRoot(scratch1, Heap::kUndefinedValueRootIndex);
+    __ li(call_data, call_data_obj);
   }
-  // Store ReturnValue default and ReturnValue.
-  __ LoadRoot(scratch1, Heap::kUndefinedValueRootIndex);
-  __ Push(scratch1, scratch1);
-  // Store isolate.
-  __ li(scratch1, Operand(ExternalReference::isolate_address(masm->isolate())));
-  __ push(scratch1);
-  // Store holder.
-  __ push(holder);
-
-  // Prepare arguments.
-  __ Move(a2, 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);
-
-  // a0 = FunctionCallbackInfo&
-  // Arguments is built at sp + 1 (sp is a reserved spot for ra).
-  __ Addu(a0, sp, kPointerSize);
-  // FunctionCallbackInfo::implicit_args_
-  __ sw(a2, MemOperand(a0, 0 * kPointerSize));
-  // FunctionCallbackInfo::values_
-  __ Addu(t0, a2, Operand((kFastApiCallArguments - 1 + argc) * kPointerSize));
-  __ sw(t0, MemOperand(a0, 1 * kPointerSize));
-  // FunctionCallbackInfo::length_ = argc
-  __ li(t0, Operand(argc));
-  __ sw(t0, MemOperand(a0, 2 * kPointerSize));
-  // FunctionCallbackInfo::is_construct_call = 0
-  __ sw(zero_reg, MemOperand(a0, 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;
@@ -864,26 +809,12 @@ static void GenerateFastApiCallBody(MacroAssembler* masm,
       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());
-
-  AllowExternalCallThatCantCauseGC scope(masm);
-  MemOperand context_restore_operand(
-      fp, (2 + FCA::kContextSaveIndex) * kPointerSize);
-  MemOperand return_value_operand(
-      fp, (2 + FCA::kReturnValueOffset) * kPointerSize);
+  __ li(api_function_address, Operand(ref));
+  __ li(thunk_arg, Operand(reinterpret_cast<int32_t>(function_address)));
 
-  __ CallApiFunctionAndReturn(ref,
-                              function_address,
-                              thunk_ref,
-                              a1,
-                              kStackUnwindSpace,
-                              return_value_operand,
-                              restore_context ?
-                                  &context_restore_operand : NULL);
+  // Jump to stub.
+  CallApiFunctionStub stub(restore_context, call_data_undefined, argc);
+  __ TailCallStub(&stub);
 }
 
 
@@ -897,7 +828,7 @@ static void GenerateFastApiCall(MacroAssembler* masm,
   __ IncrementCounter(counters->call_const_fast_api(), 1, a0, a1);
 
   // Move holder to a register.
-  Register holder_reg = a0;
+  Register holder_reg = a2;
   switch (holder_lookup) {
     case CallOptimization::kHolderIsReceiver:
       {
@@ -924,9 +855,6 @@ static void GenerateFastApiCall(MacroAssembler* masm,
                           optimization,
                           argc,
                           holder_reg,
-                          a1,
-                          a2,
-                          a3,
                           false);
 }
 
@@ -948,21 +876,11 @@ static void GenerateFastApiCall(MacroAssembler* masm,
     __ push(arg);
   }
 
-  Register scratch1 = a0;
-  Register scratch2 = a1;
-  Register scratch3 = a2;
-  if (!a3.is(receiver)) {
-    __ mov(a3, receiver);
-    receiver = a3;
-  }
   // Stack now matches JSFunction abi.
   GenerateFastApiCallBody(masm,
                           optimization,
                           argc,
                           receiver,
-                          scratch1,
-                          scratch2,
-                          scratch3,
                           true);
 }
 
@@ -1412,6 +1330,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 = a3;
+  Register thunk_last_arg = a2;
+  __ li(getter_address_reg, Operand(ref));
+  __ li(thunk_last_arg, Operand(reinterpret_cast<int32_t>(getter_address)));
 
   Address thunk_address = FUNCTION_ADDR(&InvokeAccessorGetterCallback);
   ExternalReference::Type thunk_type =
@@ -1419,10 +1341,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,
-                              a2,
+                              thunk_last_arg,
                               kStackUnwindSpace,
                               MemOperand(fp, 6 * kPointerSize),
                               NULL);