Revision: 5791
Author: [email protected]
Date: Tue Nov  9 06:01:23 2010
Log: Direct call API functions (ia32 implementation).

Review URL: http://codereview.chromium.org/4456002
http://code.google.com/p/v8/source/detail?r=5791

Modified:
 /branches/bleeding_edge/src/code-stubs.h
 /branches/bleeding_edge/src/codegen.cc
 /branches/bleeding_edge/src/ia32/assembler-ia32.h
 /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc
 /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h
 /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc
 /branches/bleeding_edge/src/objects-debug.cc
 /branches/bleeding_edge/src/objects-inl.h
 /branches/bleeding_edge/src/objects.h

=======================================
--- /branches/bleeding_edge/src/code-stubs.h    Mon Oct 25 08:22:03 2010
+++ /branches/bleeding_edge/src/code-stubs.h    Tue Nov  9 06:01:23 2010
@@ -542,7 +542,7 @@
   ApiFunction* fun() { return fun_; }
   Major MajorKey() { return NoCache; }
   int MinorKey() { return 0; }
-  const char* GetName() { return "ApiEntryStub"; }
+  const char* GetName() { return "ApiGetterEntryStub"; }
   // The accessor info associated with the function.
   Handle<AccessorInfo> info_;
   // The function to be called.
@@ -550,6 +550,32 @@
 };


+class ApiCallEntryStub : public CodeStub {
+ public:
+  ApiCallEntryStub(Handle<CallHandlerInfo> info,
+                   ApiFunction* fun)
+      : info_(info),
+        fun_(fun) { }
+  void Generate(MacroAssembler* masm);
+  virtual bool has_custom_cache() { return true; }
+  virtual bool GetCustomCache(Code** code_out);
+  virtual void SetCustomCache(Code* value);
+
+  static const int kStackSpace = 0;
+  static const int kArgc = 5;
+ private:
+  Handle<CallHandlerInfo> info() { return info_; }
+  ApiFunction* fun() { return fun_; }
+  Major MajorKey() { return NoCache; }
+  int MinorKey() { return 0; }
+  const char* GetName() { return "ApiCallEntryStub"; }
+  // The call handler info associated with the function.
+  Handle<CallHandlerInfo> info_;
+  // The function to be called.
+  ApiFunction* fun_;
+};
+
+
 class JSEntryStub : public CodeStub {
  public:
   JSEntryStub() { }
=======================================
--- /branches/bleeding_edge/src/codegen.cc      Thu Nov  4 08:12:03 2010
+++ /branches/bleeding_edge/src/codegen.cc      Tue Nov  9 06:01:23 2010
@@ -482,8 +482,8 @@
 }


-bool ApiGetterEntryStub::GetCustomCache(Code** code_out) {
-  Object* cache = info()->load_stub_cache();
+// Implementation of CodeStub::GetCustomCache.
+static bool GetCustomCacheHelper(Object* cache, Code** code_out) {
   if (cache->IsUndefined()) {
     return false;
   } else {
@@ -491,11 +491,26 @@
     return true;
   }
 }
+
+
+bool ApiGetterEntryStub::GetCustomCache(Code** code_out) {
+  return GetCustomCacheHelper(info()->load_stub_cache(), code_out);
+}


 void ApiGetterEntryStub::SetCustomCache(Code* value) {
   info()->set_load_stub_cache(value);
 }
+
+
+bool ApiCallEntryStub::GetCustomCache(Code** code_out) {
+  return GetCustomCacheHelper(info()->call_stub_cache(), code_out);
+}
+
+
+void ApiCallEntryStub::SetCustomCache(Code* value) {
+  info()->set_call_stub_cache(value);
+}


 } }  // namespace v8::internal
=======================================
--- /branches/bleeding_edge/src/ia32/assembler-ia32.h Thu Nov 4 08:12:03 2010 +++ /branches/bleeding_edge/src/ia32/assembler-ia32.h Tue Nov 9 06:01:23 2010
@@ -521,7 +521,6 @@
   void push(const Immediate& x);
   void push(Register src);
   void push(const Operand& src);
-  void push(Label* label, RelocInfo::Mode relocation_mode);

   void pop(Register dst);
   void pop(const Operand& dst);
=======================================
--- /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Thu Oct 21 07:21:00 2010 +++ /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Tue Nov 9 06:01:23 2010
@@ -3065,6 +3065,26 @@
   __ mov(ApiParameterOperand(1), eax);  // arguments pointer.
   __ CallApiFunctionAndReturn(fun(), kArgc);
 }
+
+
+void ApiCallEntryStub::Generate(MacroAssembler* masm) {
+  __ PrepareCallApiFunction(kStackSpace, kArgc);
+  STATIC_ASSERT(kArgc == 5);
+
+  // Allocate the v8::Arguments structure in the arguments' space since
+  // it's not controlled by GC.
+  __ mov(ApiParameterOperand(1), eax);  // v8::Arguments::implicit_args_.
+  __ mov(ApiParameterOperand(2), ebx);  // v8::Arguments::values_.
+  __ mov(ApiParameterOperand(3), edx);  // v8::Arguments::length_.
+  // v8::Arguments::is_construct_call_.
+  __ mov(ApiParameterOperand(4), Immediate(0));
+
+  // v8::InvocationCallback's argument.
+  __ lea(eax, ApiParameterOperand(1));
+  __ mov(ApiParameterOperand(0), eax);
+
+  __ CallApiFunctionAndReturn(fun(), kArgc);
+}


 void CEntryStub::GenerateCore(MacroAssembler* masm,
=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h Mon Oct 25 08:22:03 2010 +++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h Tue Nov 9 06:01:23 2010
@@ -488,7 +488,7 @@
   // stored in ApiParameterOperand(0), ApiParameterOperand(1) etc.
   void PrepareCallApiFunction(int stack_space, int argc);

-  // Tail call an API function (jump). Allocates HandleScope, extracts
+  // Calls an API function. Allocates HandleScope, extracts
   // returned value from handle and propagates exceptions.
   // Clobbers ebx, esi, edi and caller-save registers.
   void CallApiFunctionAndReturn(ApiFunction* function, int argc);
=======================================
--- /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Tue Nov 2 04:56:10 2010 +++ /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Tue Nov 9 06:01:23 2010
@@ -411,6 +411,10 @@
ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly)),
         5);
 }
+
+
+// Number of pointers to be reserved on stack for fast API call.
+static const int kFastApiCallArguments = 3;


 // Reserves space for the extra arguments to FastHandleApiCall in the
@@ -423,10 +427,9 @@
   //  -- esp[4] : last argument in the internal frame of the caller
   // -----------------------------------
   __ pop(scratch);
-  __ push(Immediate(Smi::FromInt(0)));
-  __ push(Immediate(Smi::FromInt(0)));
-  __ push(Immediate(Smi::FromInt(0)));
-  __ push(Immediate(Smi::FromInt(0)));
+  for (int i = 0; i < kFastApiCallArguments; i++) {
+    __ push(Immediate(Smi::FromInt(0)));
+  }
   __ push(scratch);
 }

@@ -434,75 +437,81 @@
 // Undoes the effects of ReserveSpaceForFastApiCall.
static void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) {
   // ----------- S t a t e -------------
-  //  -- esp[0]  : return address
-  //  -- esp[4]  : last fast api call extra argument
+  //  -- esp[0]  : return address.
+  //  -- esp[4]  : last fast api call extra argument.
   //  -- ...
-  //  -- esp[16] : first fast api call extra argument
-  //  -- esp[20] : last argument in the internal frame
+ // -- esp[kFastApiCallArguments * 4] : first fast api call extra argument.
+  //  -- esp[kFastApiCallArguments * 4 + 4] : last argument in the internal
+  //                                          frame.
   // -----------------------------------
   __ pop(scratch);
-  __ add(Operand(esp), Immediate(kPointerSize * 4));
+  __ add(Operand(esp), Immediate(kPointerSize * kFastApiCallArguments));
   __ push(scratch);
 }


 // Generates call to FastHandleApiCall builtin.
-static void GenerateFastApiCall(MacroAssembler* masm,
+static bool GenerateFastApiCall(MacroAssembler* masm,
                                 const CallOptimization& optimization,
-                                int argc) {
+                                int argc,
+                                Failure** failure) {
   // ----------- S t a t e -------------
   //  -- esp[0]              : return address
   //  -- esp[4]              : object passing the type check
   //                           (last fast api call extra argument,
   //                            set by CheckPrototypes)
-  //  -- esp[8]              : api call data
-  //  -- esp[12]             : api callback
-  //  -- esp[16]             : api function
+  //  -- esp[8]              : api function
   //                           (first fast api call extra argument)
-  //  -- esp[20]             : last argument
+  //  -- esp[12]             : api call data
+  //  -- esp[16]             : last argument
   //  -- ...
-  //  -- esp[(argc + 5) * 4] : first argument
-  //  -- esp[(argc + 6) * 4] : receiver
+  //  -- esp[(argc + 3) * 4] : first argument
+  //  -- esp[(argc + 4) * 4] : receiver
   // -----------------------------------
-
   // Get the function and setup the context.
   JSFunction* function = optimization.constant_function();
   __ mov(edi, Immediate(Handle<JSFunction>(function)));
   __ mov(esi, FieldOperand(edi, JSFunction::kContextOffset));

   // Pass the additional arguments FastHandleApiCall expects.
-  __ mov(Operand(esp, 4 * kPointerSize), edi);
-  bool info_loaded = false;
-  Object* callback = optimization.api_call_info()->callback();
-  if (Heap::InNewSpace(callback)) {
-    info_loaded = true;
-    __ mov(ecx, Handle<CallHandlerInfo>(optimization.api_call_info()));
-    __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kCallbackOffset));
-    __ mov(Operand(esp, 3 * kPointerSize), ebx);
-  } else {
- __ mov(Operand(esp, 3 * kPointerSize), Immediate(Handle<Object>(callback)));
-  }
+  __ mov(Operand(esp, 2 * kPointerSize), edi);
   Object* call_data = optimization.api_call_info()->data();
+ Handle<CallHandlerInfo> api_call_info_handle(optimization.api_call_info());
   if (Heap::InNewSpace(call_data)) {
-    if (!info_loaded) {
-      __ mov(ecx, Handle<CallHandlerInfo>(optimization.api_call_info()));
-    }
+    __ mov(ecx, api_call_info_handle);
     __ mov(ebx, FieldOperand(ecx, CallHandlerInfo::kDataOffset));
-    __ mov(Operand(esp, 2 * kPointerSize), ebx);
+    __ mov(Operand(esp, 3 * kPointerSize), ebx);
   } else {
-    __ mov(Operand(esp, 2 * kPointerSize),
+    __ mov(Operand(esp, 3 * kPointerSize),
            Immediate(Handle<Object>(call_data)));
   }

-  // Set the number of arguments.
-  __ mov(eax, Immediate(argc + 4));
-
-  // Jump to the fast api call builtin (tail call).
-  Handle<Code> code = Handle<Code>(
-      Builtins::builtin(Builtins::FastHandleApiCall));
-  ParameterCount expected(0);
-  __ InvokeCode(code, expected, expected,
-                RelocInfo::CODE_TARGET, JUMP_FUNCTION);
+  // Prepare arguments for ApiCallEntryStub.
+  __ lea(eax, Operand(esp, 3 * kPointerSize));
+  __ lea(ebx, Operand(esp, (argc + 3) * kPointerSize));
+  __ Set(edx, Immediate(argc));
+
+  Object* callback = optimization.api_call_info()->callback();
+  Address api_function_address = v8::ToCData<Address>(callback);
+  ApiFunction fun(api_function_address);
+
+  ApiCallEntryStub stub(api_call_info_handle, &fun);
+
+  __ EnterInternalFrame();
+
+  // Emitting a stub call may try to allocate (if the code is not
+  // already generated).  Do not allow the assembler to perform a
+  // garbage collection but instead return the allocation failure
+  // object.
+  MaybeObject* result = masm->TryCallStub(&stub);
+  if (result->IsFailure()) {
+    *failure = Failure::cast(result);
+    return false;
+  }
+
+  __ LeaveInternalFrame();
+  __ ret((argc + 4) * kPointerSize);
+  return true;
 }


@@ -515,7 +524,7 @@
         arguments_(arguments),
         name_(name) {}

-  void Compile(MacroAssembler* masm,
+  bool Compile(MacroAssembler* masm,
                JSObject* object,
                JSObject* holder,
                String* name,
@@ -524,7 +533,8 @@
                Register scratch1,
                Register scratch2,
                Register scratch3,
-               Label* miss) {
+               Label* miss,
+               Failure** failure) {
     ASSERT(holder->HasNamedInterceptor());
     ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined());

@@ -535,17 +545,18 @@
     CallOptimization optimization(lookup);

     if (optimization.is_constant_call()) {
-      CompileCacheable(masm,
-                       object,
-                       receiver,
-                       scratch1,
-                       scratch2,
-                       scratch3,
-                       holder,
-                       lookup,
-                       name,
-                       optimization,
-                       miss);
+      return CompileCacheable(masm,
+                              object,
+                              receiver,
+                              scratch1,
+                              scratch2,
+                              scratch3,
+                              holder,
+                              lookup,
+                              name,
+                              optimization,
+                              miss,
+                              failure);
     } else {
       CompileRegular(masm,
                      object,
@@ -556,11 +567,12 @@
                      name,
                      holder,
                      miss);
+      return true;
     }
   }

  private:
-  void CompileCacheable(MacroAssembler* masm,
+  bool CompileCacheable(MacroAssembler* masm,
                         JSObject* object,
                         Register receiver,
                         Register scratch1,
@@ -570,7 +582,8 @@
                         LookupResult* lookup,
                         String* name,
                         const CallOptimization& optimization,
-                        Label* miss_label) {
+                        Label* miss_label,
+                        Failure** failure) {
     ASSERT(optimization.is_constant_call());
     ASSERT(!lookup->holder()->IsGlobalObject());

@@ -632,7 +645,11 @@

     // Invoke function.
     if (can_do_fast_api_call) {
-      GenerateFastApiCall(masm, optimization, arguments_.immediate());
+      bool success = GenerateFastApiCall(masm, optimization,
+                                         arguments_.immediate(), failure);
+      if (!success) {
+        return false;
+      }
     } else {
       __ InvokeFunction(optimization.constant_function(), arguments_,
                         JUMP_FUNCTION);
@@ -650,6 +667,8 @@
     if (can_do_fast_api_call) {
       FreeSpaceForFastApiCall(masm, scratch1);
     }
+
+    return true;
   }

   void CompileRegular(MacroAssembler* masm,
@@ -1046,8 +1065,7 @@

   __ EnterInternalFrame();
   // Push the stack address where the list of arguments ends.
-  __ mov(scratch2, esp);
-  __ sub(Operand(scratch2), Immediate(2 * kPointerSize));
+  __ lea(scratch2, Operand(esp, -2 * kPointerSize));
   __ push(scratch2);
   __ push(receiver);  // receiver
   __ push(reg);  // holder
@@ -1061,12 +1079,11 @@
   __ push(name_reg);  // name
   // Save a pointer to where we pushed the arguments pointer.
   // This will be passed as the const AccessorInfo& to the C++ callback.
-  __ mov(eax, esp);
-  __ add(Operand(eax), Immediate(4 * kPointerSize));
+  STATIC_ASSERT(ApiGetterEntryStub::kStackSpace == 5);
+  __ lea(eax, Operand(esp, 4 * kPointerSize));
   __ mov(ebx, esp);

   // Do call through the api.
-  ASSERT_EQ(5, ApiGetterEntryStub::kStackSpace);
   Address getter_address = v8::ToCData<Address>(callback->getter());
   ApiFunction fun(getter_address);
   ApiGetterEntryStub stub(callback_handle, &fun);
@@ -2208,7 +2225,11 @@
   }

   if (depth != kInvalidProtoDepth) {
-    GenerateFastApiCall(masm(), optimization, argc);
+    Failure* failure;
+ bool success = GenerateFastApiCall(masm(), optimization, argc, &failure);
+    if (!success) {
+      return failure;
+    }
   } else {
     __ InvokeFunction(function, arguments(), JUMP_FUNCTION);
   }
@@ -2253,16 +2274,21 @@
   __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));

   CallInterceptorCompiler compiler(this, arguments(), ecx);
-  compiler.Compile(masm(),
-                   object,
-                   holder,
-                   name,
-                   &lookup,
-                   edx,
-                   ebx,
-                   edi,
-                   eax,
-                   &miss);
+  Failure* failure;
+  bool success = compiler.Compile(masm(),
+                                  object,
+                                  holder,
+                                  name,
+                                  &lookup,
+                                  edx,
+                                  ebx,
+                                  edi,
+                                  eax,
+                                  &miss,
+                                  &failure);
+  if (!success) {
+    return false;
+  }

   // Restore receiver.
   __ mov(edx, Operand(esp, (argc + 1) * kPointerSize));
=======================================
--- /branches/bleeding_edge/src/objects-debug.cc        Mon Oct 25 08:22:03 2010
+++ /branches/bleeding_edge/src/objects-debug.cc        Tue Nov  9 06:01:23 2010
@@ -997,6 +997,8 @@
   data()->ShortPrint();
   PrintF("\n - flag: ");
   flag()->ShortPrint();
+  PrintF("\n - load_stub_cache: ");
+  load_stub_cache()->ShortPrint();
 }

 void AccessCheckInfo::AccessCheckInfoVerify() {
@@ -1046,6 +1048,7 @@
   CHECK(IsCallHandlerInfo());
   VerifyPointer(callback());
   VerifyPointer(data());
+  VerifyPointer(call_stub_cache());
 }

 void CallHandlerInfo::CallHandlerInfoPrint() {
@@ -1054,6 +1057,8 @@
   callback()->ShortPrint();
   PrintF("\n - data: ");
   data()->ShortPrint();
+  PrintF("\n - call_stub_cache: ");
+  call_stub_cache()->ShortPrint();
 }

 void TemplateInfo::TemplateInfoVerify() {
=======================================
--- /branches/bleeding_edge/src/objects-inl.h   Mon Nov  8 02:30:57 2010
+++ /branches/bleeding_edge/src/objects-inl.h   Tue Nov  9 06:01:23 2010
@@ -2557,6 +2557,7 @@

 ACCESSORS(CallHandlerInfo, callback, Object, kCallbackOffset)
 ACCESSORS(CallHandlerInfo, data, Object, kDataOffset)
+ACCESSORS(CallHandlerInfo, call_stub_cache, Object, kCallStubCacheOffset)

 ACCESSORS(TemplateInfo, tag, Object, kTagOffset)
 ACCESSORS(TemplateInfo, property_list, Object, kPropertyListOffset)
=======================================
--- /branches/bleeding_edge/src/objects.h       Wed Oct 27 02:19:43 2010
+++ /branches/bleeding_edge/src/objects.h       Tue Nov  9 06:01:23 2010
@@ -5423,6 +5423,7 @@
  public:
   DECL_ACCESSORS(callback, Object)
   DECL_ACCESSORS(data, Object)
+  DECL_ACCESSORS(call_stub_cache, Object)

   static inline CallHandlerInfo* cast(Object* obj);

@@ -5433,7 +5434,8 @@

   static const int kCallbackOffset = HeapObject::kHeaderSize;
   static const int kDataOffset = kCallbackOffset + kPointerSize;
-  static const int kSize = kDataOffset + kPointerSize;
+  static const int kCallStubCacheOffset = kDataOffset + kPointerSize;
+  static const int kSize = kCallStubCacheOffset + kPointerSize;

  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(CallHandlerInfo);

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to