Revision: 5827
Author: [email protected]
Date: Mon Nov 15 09:12:34 2010
Log: Removing redundant stubs for API functions.

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

Modified:
 /branches/bleeding_edge/src/code-stubs.cc
 /branches/bleeding_edge/src/code-stubs.h
 /branches/bleeding_edge/src/codegen.cc
 /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/objects-debug.cc
 /branches/bleeding_edge/src/objects-inl.h
 /branches/bleeding_edge/src/objects.h
 /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/code-stubs.cc   Mon Oct 25 08:22:03 2010
+++ /branches/bleeding_edge/src/code-stubs.cc   Mon Nov 15 09:12:34 2010
@@ -37,7 +37,6 @@
 namespace internal {

 bool CodeStub::FindCodeInCache(Code** code_out) {
-  if (has_custom_cache()) return GetCustomCache(code_out);
   int index = Heap::code_stubs()->FindEntry(GetKey());
   if (index != NumberDictionary::kNotFound) {
     *code_out = Code::cast(Heap::code_stubs()->ValueAt(index));
@@ -105,17 +104,14 @@
Handle<Code> new_object = Factory::NewCode(desc, flags, masm.CodeObject());
     RecordCodeGeneration(*new_object, &masm);

-    if (has_custom_cache()) {
-      SetCustomCache(*new_object);
-    } else {
-      // Update the dictionary and the root in Heap.
-      Handle<NumberDictionary> dict =
-          Factory::DictionaryAtNumberPut(
-              Handle<NumberDictionary>(Heap::code_stubs()),
-              GetKey(),
-              new_object);
-      Heap::public_set_code_stubs(*dict);
-    }
+    // Update the dictionary and the root in Heap.
+    Handle<NumberDictionary> dict =
+        Factory::DictionaryAtNumberPut(
+            Handle<NumberDictionary>(Heap::code_stubs()),
+            GetKey(),
+            new_object);
+    Heap::public_set_code_stubs(*dict);
+
     code = *new_object;
   }

@@ -147,15 +143,11 @@
     code = Code::cast(new_object);
     RecordCodeGeneration(code, &masm);

-    if (has_custom_cache()) {
-      SetCustomCache(code);
-    } else {
-      // Try to update the code cache but do not fail if unable.
-      MaybeObject* maybe_new_object =
-          Heap::code_stubs()->AtNumberPut(GetKey(), code);
-      if (maybe_new_object->ToObject(&new_object)) {
-        Heap::public_set_code_stubs(NumberDictionary::cast(new_object));
-      }
+    // Try to update the code cache but do not fail if unable.
+    MaybeObject* maybe_new_object =
+        Heap::code_stubs()->AtNumberPut(GetKey(), code);
+    if (maybe_new_object->ToObject(&new_object)) {
+      Heap::public_set_code_stubs(NumberDictionary::cast(new_object));
     }
   }

=======================================
--- /branches/bleeding_edge/src/code-stubs.h    Tue Nov  9 06:01:23 2010
+++ /branches/bleeding_edge/src/code-stubs.h    Mon Nov 15 09:12:34 2010
@@ -123,12 +123,6 @@
   static const char* MajorName(Major major_key, bool allow_unknown_keys);

   virtual ~CodeStub() {}
-
-  // Override these methods to provide a custom caching mechanism for
-  // an individual type of code stub.
-  virtual bool GetCustomCache(Code** code_out) { return false; }
-  virtual void SetCustomCache(Code* value) { }
-  virtual bool has_custom_cache() { return false; }

  protected:
   static const int kMajorBits = 5;
@@ -524,58 +518,6 @@
 };


-class ApiGetterEntryStub : public CodeStub {
- public:
-  ApiGetterEntryStub(Handle<AccessorInfo> 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 = 5;
-  static const int kArgc = 2;
- private:
-  Handle<AccessorInfo> info() { return info_; }
-  ApiFunction* fun() { return fun_; }
-  Major MajorKey() { return NoCache; }
-  int MinorKey() { return 0; }
-  const char* GetName() { return "ApiGetterEntryStub"; }
-  // The accessor info associated with the function.
-  Handle<AccessorInfo> info_;
-  // The function to be called.
-  ApiFunction* fun_;
-};
-
-
-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 11 02:33:51 2010
+++ /branches/bleeding_edge/src/codegen.cc      Mon Nov 15 09:12:34 2010
@@ -447,37 +447,6 @@
   return 0;
 #endif
 }
-
-
-// Implementation of CodeStub::GetCustomCache.
-static bool GetCustomCacheHelper(Object* cache, Code** code_out) {
-  if (cache->IsUndefined()) {
-    return false;
-  } else {
-    *code_out = Code::cast(cache);
-    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/code-stubs-ia32.cc Tue Nov 9 06:01:23 2010 +++ /branches/bleeding_edge/src/ia32/code-stubs-ia32.cc Mon Nov 15 09:12:34 2010
@@ -3056,35 +3056,6 @@
   STATIC_ASSERT(StackHandlerConstants::kPCOffset == 3 * kPointerSize);
   __ ret(0);
 }
-
-
-void ApiGetterEntryStub::Generate(MacroAssembler* masm) {
-  __ PrepareCallApiFunction(kStackSpace, kArgc);
-  STATIC_ASSERT(kArgc == 2);
-  __ mov(ApiParameterOperand(0), ebx);  // name.
-  __ 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.cc Mon Oct 25 08:22:03 2010 +++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.cc Mon Nov 15 09:12:34 2010
@@ -1108,6 +1108,17 @@
   Set(eax, Immediate(num_arguments));
   JumpToExternalReference(ext);
 }
+
+
+MaybeObject* MacroAssembler::TryTailCallExternalReference(
+    const ExternalReference& ext, int num_arguments, int result_size) {
+  // TODO(1236192): Most runtime routines don't need the number of
+  // arguments passed in because it is constant. At some point we
+  // should remove this need and make the runtime routine entry code
+  // smarter.
+  Set(eax, Immediate(num_arguments));
+  return TryJumpToExternalReference(ext);
+}


 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
@@ -1115,6 +1126,14 @@
                                      int result_size) {
TailCallExternalReference(ExternalReference(fid), num_arguments, result_size);
 }
+
+
+MaybeObject* MacroAssembler::TryTailCallRuntime(Runtime::FunctionId fid,
+                                                int num_arguments,
+                                                int result_size) {
+  return TryTailCallExternalReference(
+      ExternalReference(fid), num_arguments, result_size);
+}


 // If true, a Handle<T> passed by value is passed and returned by
@@ -1144,7 +1163,8 @@
 }


-void MacroAssembler::CallApiFunctionAndReturn(ApiFunction* function, int argc) { +MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(ApiFunction* function,
+                                                         int argc) {
   if (!kPassHandlesDirectly) {
     // The argument slots are filled as follows:
     //
@@ -1213,7 +1233,11 @@
   LeaveExitFrame();
   ret(0);
   bind(&promote_scheduled_exception);
-  TailCallRuntime(Runtime::kPromoteScheduledException, 0, 1);
+  MaybeObject* result =
+      TryTailCallRuntime(Runtime::kPromoteScheduledException, 0, 1);
+  if (result->IsFailure()) {
+    return result;
+  }
   bind(&empty_handle);
   // It was zero; the result is undefined.
   mov(eax, Factory::undefined_value());
@@ -1227,6 +1251,8 @@
   call(Operand(eax));
   mov(eax, edi);
   jmp(&leave_exit_frame);
+
+  return result;
 }


@@ -1236,6 +1262,15 @@
   CEntryStub ces(1);
   jmp(ces.GetCode(), RelocInfo::CODE_TARGET);
 }
+
+
+MaybeObject* MacroAssembler::TryJumpToExternalReference(
+    const ExternalReference& ext) {
+  // Set the entry point and jump to the C entry runtime stub.
+  mov(ebx, Immediate(ext));
+  CEntryStub ces(1);
+  return TryTailCallStub(&ces);
+}


 void MacroAssembler::InvokePrologue(const ParameterCount& expected,
=======================================
--- /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h Wed Nov 10 09:00:20 2010 +++ /branches/bleeding_edge/src/ia32/macro-assembler-ia32.h Mon Nov 15 09:12:34 2010
@@ -460,11 +460,23 @@
                                  int num_arguments,
                                  int result_size);

+  // Tail call of a runtime routine (jump). Try to generate the code if
+ // necessary. Do not perform a GC but instead return a retry after GC failure.
+  MUST_USE_RESULT MaybeObject* TryTailCallExternalReference(
+      const ExternalReference& ext, int num_arguments, int result_size);
+
   // Convenience function: tail call a runtime routine (jump).
   void TailCallRuntime(Runtime::FunctionId fid,
                        int num_arguments,
                        int result_size);

+ // Convenience function: tail call a runtime routine (jump). Try to generate + // the code if necessary. Do not perform a GC but instead return a retry after
+  // GC failure.
+  MUST_USE_RESULT MaybeObject* TryTailCallRuntime(Runtime::FunctionId fid,
+                                                  int num_arguments,
+                                                  int result_size);
+
// Before calling a C-function from generated code, align arguments on stack.
   // After aligning the frame, arguments must be stored in esp[0], esp[4],
// etc., not pushed. The argument count assumes all arguments are word sized.
@@ -485,17 +497,20 @@
   // Prepares stack to put arguments (aligns and so on). Reserves
// space for return value if needed (assumes the return value is a handle). // Uses callee-saved esi to restore stack state after call. Arguments must be
-  // stored in ApiParameterOperand(0), ApiParameterOperand(1) etc.
+  // stored in ApiParameterOperand(0), ApiParameterOperand(1) etc. Saves
+  // context (esi).
   void PrepareCallApiFunction(int stack_space, int argc);

   // 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);
+  // Clobbers ebx, edi and caller-save registers. Restores context.
+ MaybeObject* TryCallApiFunctionAndReturn(ApiFunction* function, int argc);

   // Jump to a runtime routine.
   void JumpToExternalReference(const ExternalReference& ext);

+  MaybeObject* TryJumpToExternalReference(const ExternalReference& ext);
+

// ---------------------------------------------------------------------------
   // Utilities
=======================================
--- /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Tue Nov 9 06:01:23 2010 +++ /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Mon Nov 15 09:12:34 2010
@@ -486,31 +486,43 @@
            Immediate(Handle<Object>(call_data)));
   }

-  // Prepare arguments for ApiCallEntryStub.
+  // Prepare arguments.
   __ 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();
+ const int kApiArgc = 1; // API function gets reference to the v8::Arguments.
+
+  // Allocate the v8::Arguments structure in the arguments' space since
+  // it's not controlled by GC.
+  const int kApiStackSpace = 4;
+
+  __ PrepareCallApiFunction(argc + kFastApiCallArguments + 1,
+                            kApiArgc + kApiStackSpace);
+
+  __ mov(ApiParameterOperand(1), eax);  // v8::Arguments::implicit_args_.
+  __ add(Operand(eax), Immediate(argc * kPointerSize));
+  __ mov(ApiParameterOperand(2), eax);  // v8::Arguments::values_.
+ __ Set(ApiParameterOperand(3), Immediate(argc)); // 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);

   // 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);
+  MaybeObject* result =
+      masm->TryCallApiFunctionAndReturn(&fun, kApiArgc + kApiStackSpace);
   if (result->IsFailure()) {
     *failure = Failure::cast(result);
     return false;
   }
-
-  __ LeaveInternalFrame();
-  __ ret((argc + 4) * kPointerSize);
   return true;
 }

@@ -1063,44 +1075,55 @@

   Handle<AccessorInfo> callback_handle(callback);

-  __ EnterInternalFrame();
-  // Push the stack address where the list of arguments ends.
-  __ lea(scratch2, Operand(esp, -2 * kPointerSize));
-  __ push(scratch2);
+ // Insert additional parameters into the stack frame above return address.
+  ASSERT(!scratch3.is(reg));
+  __ pop(scratch3);  // Get return address to place it below.
+
   __ push(receiver);  // receiver
+  __ mov(scratch2, Operand(esp));
+  ASSERT(!scratch2.is(reg));
   __ push(reg);  // holder
   // Push data from AccessorInfo.
   if (Heap::InNewSpace(callback_handle->data())) {
-    __ mov(scratch2, Immediate(callback_handle));
-    __ push(FieldOperand(scratch2, AccessorInfo::kDataOffset));
+    __ mov(scratch1, Immediate(callback_handle));
+    __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset));
   } else {
     __ push(Immediate(Handle<Object>(callback_handle->data())));
   }
-  __ 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.
-  STATIC_ASSERT(ApiGetterEntryStub::kStackSpace == 5);
-  __ lea(eax, Operand(esp, 4 * kPointerSize));
-  __ mov(ebx, esp);
+  __ push(scratch2);
+
+  __ push(name_reg);  // name
+  __ mov(ebx, esp);  // esp points to reference to name (handler).
+
+  __ push(scratch3);  // Restore return address.

   // Do call through the api.
   Address getter_address = v8::ToCData<Address>(callback->getter());
   ApiFunction fun(getter_address);
-  ApiGetterEntryStub stub(callback_handle, &fun);
+
+ // 3 elements array for v8::Agruments::values_, handler for name and pointer
+  // to the values (it considered as smi in GC).
+  const int kStackSpace = 5;
+  const int kApiArgc = 2;
+
+  __ PrepareCallApiFunction(kStackSpace, kApiArgc);
+  __ mov(ApiParameterOperand(0), ebx);  // name.
+  __ add(Operand(ebx), Immediate(kPointerSize));
+  __ mov(ApiParameterOperand(1), ebx);  // arguments pointer.
+
   // 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.
-  Object* result = NULL;  // Initialization to please compiler.
-  { MaybeObject* try_call_result = masm()->TryCallStub(&stub);
-    if (!try_call_result->ToObject(&result)) {
-      *failure = Failure::cast(try_call_result);
-      return false;
-    }
-  }
-  __ LeaveInternalFrame();
-
-  __ ret(0);
+ MaybeObject* result = masm()->TryCallApiFunctionAndReturn(&fun, kApiArgc);
+  if (result->IsFailure()) {
+    *failure = Failure::cast(result);
+    return false;
+  }
+
   return true;
 }

=======================================
--- /branches/bleeding_edge/src/objects-debug.cc        Tue Nov  9 06:01:23 2010
+++ /branches/bleeding_edge/src/objects-debug.cc        Mon Nov 15 09:12:34 2010
@@ -982,7 +982,6 @@
   VerifyPointer(name());
   VerifyPointer(data());
   VerifyPointer(flag());
-  VerifyPointer(load_stub_cache());
 }

 void AccessorInfo::AccessorInfoPrint() {
@@ -997,8 +996,6 @@
   data()->ShortPrint();
   PrintF("\n - flag: ");
   flag()->ShortPrint();
-  PrintF("\n - load_stub_cache: ");
-  load_stub_cache()->ShortPrint();
 }

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

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

 void TemplateInfo::TemplateInfoVerify() {
=======================================
--- /branches/bleeding_edge/src/objects-inl.h   Tue Nov  9 06:01:23 2010
+++ /branches/bleeding_edge/src/objects-inl.h   Mon Nov 15 09:12:34 2010
@@ -2542,7 +2542,6 @@
 ACCESSORS(AccessorInfo, data, Object, kDataOffset)
 ACCESSORS(AccessorInfo, name, Object, kNameOffset)
 ACCESSORS(AccessorInfo, flag, Smi, kFlagOffset)
-ACCESSORS(AccessorInfo, load_stub_cache, Object, kLoadStubCacheOffset)

 ACCESSORS(AccessCheckInfo, named_callback, Object, kNamedCallbackOffset)
ACCESSORS(AccessCheckInfo, indexed_callback, Object, kIndexedCallbackOffset)
@@ -2557,7 +2556,6 @@

 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       Tue Nov  9 06:01:23 2010
+++ /branches/bleeding_edge/src/objects.h       Mon Nov 15 09:12:34 2010
@@ -5327,7 +5327,6 @@
   DECL_ACCESSORS(data, Object)
   DECL_ACCESSORS(name, Object)
   DECL_ACCESSORS(flag, Smi)
-  DECL_ACCESSORS(load_stub_cache, Object)

   inline bool all_can_read();
   inline void set_all_can_read(bool value);
@@ -5353,8 +5352,7 @@
   static const int kDataOffset = kSetterOffset + kPointerSize;
   static const int kNameOffset = kDataOffset + kPointerSize;
   static const int kFlagOffset = kNameOffset + kPointerSize;
-  static const int kLoadStubCacheOffset = kFlagOffset + kPointerSize;
-  static const int kSize = kLoadStubCacheOffset + kPointerSize;
+  static const int kSize = kFlagOffset + kPointerSize;

  private:
   // Bit positions in flag.
@@ -5423,7 +5421,6 @@
  public:
   DECL_ACCESSORS(callback, Object)
   DECL_ACCESSORS(data, Object)
-  DECL_ACCESSORS(call_stub_cache, Object)

   static inline CallHandlerInfo* cast(Object* obj);

@@ -5434,8 +5431,7 @@

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

  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(CallHandlerInfo);
=======================================
--- /branches/bleeding_edge/src/x64/code-stubs-x64.cc Thu Oct 21 07:21:00 2010 +++ /branches/bleeding_edge/src/x64/code-stubs-x64.cc Mon Nov 15 09:12:34 2010
@@ -2481,20 +2481,6 @@
   __ bind(&skip);
   __ ret(0);
 }
-
-
-void ApiGetterEntryStub::Generate(MacroAssembler* masm) {
-  __ PrepareCallApiFunction(kStackSpace);
-#ifdef _WIN64
-  // All the parameters should be set up by a caller.
-#else
-  // Set 1st parameter register with property name.
-  __ movq(rsi, rdx);
- // Second parameter register rdi should be set with pointer to AccessorInfo
-  // by a caller.
-#endif
-  __ CallApiFunctionAndReturn(fun());
-}


 void CEntryStub::GenerateCore(MacroAssembler* masm,
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Mon Oct 25 08:22:03 2010 +++ /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Mon Nov 15 09:12:34 2010
@@ -327,7 +327,7 @@


 void MacroAssembler::TailCallStub(CodeStub* stub) {
-  ASSERT(allow_stub_calls());  // calls are not allowed in some stubs
+  ASSERT(allow_stub_calls());  // Calls are not allowed in some stubs.
   Jump(stub->GetCode(), RelocInfo::CODE_TARGET);
 }

@@ -454,6 +454,24 @@
   Set(rax, num_arguments);
   JumpToExternalReference(ext, result_size);
 }
+
+
+MaybeObject* MacroAssembler::TryTailCallExternalReference(
+    const ExternalReference& ext, int num_arguments, int result_size) {
+  // ----------- S t a t e -------------
+  //  -- rsp[0] : return address
+  //  -- rsp[8] : argument num_arguments - 1
+  //  ...
+  //  -- rsp[8 * num_arguments] : argument 0 (receiver)
+  // -----------------------------------
+
+  // TODO(1236192): Most runtime routines don't need the number of
+  // arguments passed in because it is constant. At some point we
+  // should remove this need and make the runtime routine entry code
+  // smarter.
+  Set(rax, num_arguments);
+  return TryJumpToExternalReference(ext, result_size);
+}


 void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
@@ -461,6 +479,15 @@
                                      int result_size) {
TailCallExternalReference(ExternalReference(fid), num_arguments, result_size);
 }
+
+
+MaybeObject* MacroAssembler::TryTailCallRuntime(Runtime::FunctionId fid,
+                                                int num_arguments,
+                                                int result_size) {
+  return TryTailCallExternalReference(ExternalReference(fid),
+                                      num_arguments,
+                                      result_size);
+}


 static int Offset(ExternalReference ref0, ExternalReference ref1) {
@@ -471,12 +498,24 @@
 }


-void MacroAssembler::PrepareCallApiFunction(int stack_space) {
-  EnterApiExitFrame(stack_space, 0);
+void MacroAssembler::PrepareCallApiFunction(int stack_space, int argc) {
+#ifdef _WIN64
+  // We need to prepare a slot for result handle on stack and put
+  // a pointer to it into 1st arg register.
+  int register_based_args = argc > 3 ? 3 : argc;
+  EnterApiExitFrame(stack_space, argc - register_based_args + 1);
+
+  int return_value_slot = (argc > 3 ? argc - 3 + 1 : 4);
+  // rcx must be used to pass the pointer to the return value slot.
+  lea(rcx, Operand(rsp, return_value_slot * kPointerSize));
+#else
+  EnterApiExitFrame(stack_space, argc);
+#endif
 }


-void MacroAssembler::CallApiFunctionAndReturn(ApiFunction* function) {
+MaybeObject* MacroAssembler::TryCallApiFunctionAndReturn(
+    ApiFunction* function) {
   Label empty_result;
   Label prologue;
   Label promote_scheduled_exception;
@@ -539,7 +578,11 @@
   ret(0);

   bind(&promote_scheduled_exception);
-  TailCallRuntime(Runtime::kPromoteScheduledException, 0, 1);
+ MaybeObject* result = TryTailCallRuntime(Runtime::kPromoteScheduledException,
+                                           0, 1);
+  if (result->IsFailure()) {
+    return result;
+  }

   bind(&empty_result);
   // It was zero; the result is undefined.
@@ -554,6 +597,8 @@
   call(rax);
   movq(rax, prev_limit_reg);
   jmp(&leave_exit_frame);
+
+  return result;
 }


@@ -564,6 +609,15 @@
   CEntryStub ces(result_size);
   jmp(ces.GetCode(), RelocInfo::CODE_TARGET);
 }
+
+
+MaybeObject* MacroAssembler::TryJumpToExternalReference(
+    const ExternalReference& ext, int result_size) {
+  // Set the entry point and jump to the C entry runtime stub.
+  movq(rbx, ext);
+  CEntryStub ces(result_size);
+  return TryTailCallStub(&ces);
+}


void MacroAssembler::InvokeBuiltin(Builtins::JavaScript id, InvokeFlag flag) {
@@ -1742,6 +1796,10 @@
   int offset = StandardFrameConstants::kCallerSPOffset - kPointerSize;
   lea(r12, Operand(rbp, (stack_space * kPointerSize) + offset));

+#ifndef _WIN64
+ ASSERT(argc <= 6); // EnterApiExitFrame supports only register based args.
+#endif
+
   EnterExitFrameEpilogue(result_size, argc);
 }

=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.h Wed Nov 10 09:00:20 2010 +++ /branches/bleeding_edge/src/x64/macro-assembler-x64.h Mon Nov 15 09:12:34 2010
@@ -813,22 +813,38 @@
                                  int num_arguments,
                                  int result_size);

+  MUST_USE_RESULT MaybeObject* TryTailCallExternalReference(
+      const ExternalReference& ext, int num_arguments, int result_size);
+
   // Convenience function: tail call a runtime routine (jump).
   void TailCallRuntime(Runtime::FunctionId fid,
                        int num_arguments,
                        int result_size);

+  MUST_USE_RESULT  MaybeObject* TryTailCallRuntime(Runtime::FunctionId fid,
+                                                   int num_arguments,
+                                                   int result_size);
+
   // Jump to a runtime routine.
void JumpToExternalReference(const ExternalReference& ext, int result_size);

+  // Jump to a runtime routine.
+  MaybeObject* TryJumpToExternalReference(const ExternalReference& ext,
+                                          int result_size);
+
   // Prepares stack to put arguments (aligns and so on).
-  // Uses calle-saved esi to restore stack state after call.
-  void PrepareCallApiFunction(int stack_space);
-
-  // Tail call an API function (jump). Allocates HandleScope, extracts
-  // returned value from handle and propogates exceptions.
-  // Clobbers ebx, edi and caller-save registers.
-  void CallApiFunctionAndReturn(ApiFunction* function);
+  // Uses callee-saved rsi to restore stack state after call. WIN64 calling
+ // convention requires to put the pointer to the return value slot into rcx + // (rcx must be preserverd until TryCallApiFunctionAndReturn). argc is number + // of arguments to be passed in C-function. stack_space * kPointerSize bytes
+  // will be removed from stack after the call. Saves context (rsi).
+  void PrepareCallApiFunction(int stack_space, int argc);
+
+  // Calls an API function. Allocates HandleScope, extracts
+  // returned value from handle and propagates exceptions.
+  // Clobbers r12, r14, rbx and caller-save registers. Restores context.
+  MUST_USE_RESULT MaybeObject* TryCallApiFunctionAndReturn(
+      ApiFunction* function);

// Before calling a C-function from generated code, align arguments on stack.
   // After aligning the frame, arguments must be stored in esp[0], esp[4],
=======================================
--- /branches/bleeding_edge/src/x64/stub-cache-x64.cc Mon Nov 1 02:16:39 2010 +++ /branches/bleeding_edge/src/x64/stub-cache-x64.cc Mon Nov 15 09:12:34 2010
@@ -1844,7 +1844,7 @@
   Label miss;

   Failure* failure = Failure::InternalError();
- bool success = GenerateLoadCallback(object, holder, rax, rcx, rbx, rdx, rdi, + bool success = GenerateLoadCallback(object, holder, rax, rcx, rdx, rbx, rdi,
                                       callback, name, &miss, &failure);
   if (!success) {
     miss.Unuse();
@@ -2585,19 +2585,21 @@

   Handle<AccessorInfo> callback_handle(callback);

-  __ EnterInternalFrame();
-  // Push the stack address where the list of arguments ends.
-  __ movq(scratch2, rsp);
-  __ subq(scratch2, Immediate(2 * kPointerSize));
-  __ push(scratch2);
+ // Insert additional parameters into the stack frame above return address.
+  ASSERT(!scratch2.is(reg));
+  __ pop(scratch2);  // Get return address to place it below.
+
   __ push(receiver);  // receiver
+  ASSERT(!scratch3.is(reg));
+  __ movq(scratch3, rsp);
   __ push(reg);  // holder
   if (Heap::InNewSpace(callback_handle->data())) {
-    __ Move(scratch2, callback_handle);
-    __ push(FieldOperand(scratch2, AccessorInfo::kDataOffset));  // data
+    __ Move(scratch1, callback_handle);
+    __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset));  // data
   } else {
     __ Push(Handle<Object>(callback_handle->data()));
   }
+  __ push(scratch3);
   __ 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.
@@ -2607,42 +2609,38 @@
   Register accessor_info_arg = r8;
   Register name_arg = rdx;
 #else
- Register accessor_info_arg = rdx; // temporary, copied to rsi by the stub.
+  Register accessor_info_arg = rsi;
   Register name_arg = rdi;
 #endif

-  __ movq(accessor_info_arg, rsp);
-  __ addq(accessor_info_arg, Immediate(4 * kPointerSize));
+  ASSERT(!name_arg.is(scratch2));
   __ movq(name_arg, rsp);
+  __ push(scratch2);  // Restore return address.

   // 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);
-#ifdef _WIN64
-  // We need to prepare a slot for result handle on stack and put
-  // a pointer to it into 1st arg register.
-  __ push(Immediate(0));
-  __ movq(rcx, rsp);
-#endif
+
+ // 3 elements array for v8::Agruments::values_, handler for name and pointer
+  // to the values (it considered as smi in GC).
+  const int kStackSpace = 5;
+  const int kApiArgc = 2;
+
+  __ PrepareCallApiFunction(kStackSpace, kApiArgc);
+
+ // The context register (rsi) has been saved in PrepareCallApiFunction and
+  // could be used to pass arguments.
+  __ lea(accessor_info_arg, Operand(name_arg, 1 * kPointerSize));
+
   // 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);
+  MaybeObject* result = masm()->TryCallApiFunctionAndReturn(&fun);
   if (result->IsFailure()) {
     *failure = Failure::cast(result);
     return false;
   }
-#ifdef _WIN64
-  // Discard allocated slot.
-  __ addq(rsp, Immediate(kPointerSize));
-#endif
-  __ LeaveInternalFrame();
-
-  __ ret(0);
-
   return true;
 }

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

Reply via email to