Removing redundant stubs for API functions.
authorserya@chromium.org <serya@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 15 Nov 2010 17:12:34 +0000 (17:12 +0000)
committerserya@chromium.org <serya@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 15 Nov 2010 17:12:34 +0000 (17:12 +0000)
Review URL: http://codereview.chromium.org/4695003

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

14 files changed:
src/code-stubs.cc
src/code-stubs.h
src/codegen.cc
src/ia32/code-stubs-ia32.cc
src/ia32/macro-assembler-ia32.cc
src/ia32/macro-assembler-ia32.h
src/ia32/stub-cache-ia32.cc
src/objects-debug.cc
src/objects-inl.h
src/objects.h
src/x64/code-stubs-x64.cc
src/x64/macro-assembler-x64.cc
src/x64/macro-assembler-x64.h
src/x64/stub-cache-x64.cc

index 787ec2a..8b9198f 100644 (file)
@@ -37,7 +37,6 @@ namespace v8 {
 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> CodeStub::GetCode() {
     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 @@ MaybeObject* CodeStub::TryGetCode() {
     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));
     }
   }
 
index ec64353..b156647 100644 (file)
@@ -124,12 +124,6 @@ class CodeStub BASE_EMBEDDED {
 
   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;
   static const int kMinorBits = kBitsPerInt - kSmiTagSize - kMajorBits;
@@ -524,58 +518,6 @@ class CEntryStub : public CodeStub {
 };
 
 
-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() { }
index 6db3d1c..fb8c5cd 100644 (file)
@@ -449,35 +449,4 @@ int CEntryStub::MinorKey() {
 }
 
 
-// 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
index a7d658b..6ac89bf 100644 (file)
@@ -3058,35 +3058,6 @@ void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
 }
 
 
-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,
                               Label* throw_normal_exception,
                               Label* throw_termination_exception,
index b72f4df..c53e273 100644 (file)
@@ -1110,6 +1110,17 @@ void MacroAssembler::TailCallExternalReference(const ExternalReference& 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,
                                      int num_arguments,
                                      int result_size) {
@@ -1117,6 +1128,14 @@ void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
 }
 
 
+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
 // using the location_ field directly.  If false, it is passed and
 // returned as a pointer to a handle.
@@ -1144,7 +1163,8 @@ void MacroAssembler::PrepareCallApiFunction(int stack_space, int argc) {
 }
 
 
-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 @@ void MacroAssembler::CallApiFunctionAndReturn(ApiFunction* function, int argc) {
   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 @@ void MacroAssembler::CallApiFunctionAndReturn(ApiFunction* function, int argc) {
   call(Operand(eax));
   mov(eax, edi);
   jmp(&leave_exit_frame);
+
+  return result;
 }
 
 
@@ -1238,6 +1264,15 @@ void MacroAssembler::JumpToExternalReference(const ExternalReference& ext) {
 }
 
 
+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,
                                     const ParameterCount& actual,
                                     Handle<Code> code_constant,
index fc6161a..b205f84 100644 (file)
@@ -460,11 +460,23 @@ class MacroAssembler: public Assembler {
                                  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 @@ class MacroAssembler: public Assembler {
   // 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
index f59928f..48e04c8 100644 (file)
@@ -486,31 +486,43 @@ static bool GenerateFastApiCall(MacroAssembler* masm,
            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);
+  const int kApiArgc = 1;  // API function gets reference to the v8::Arguments.
 
-  __ EnterInternalFrame();
+  // 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 @@ bool StubCompiler::GenerateLoadCallback(JSObject* object,
 
   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;
-    }
+  MaybeObject* result = masm()->TryCallApiFunctionAndReturn(&fun, kApiArgc);
+  if (result->IsFailure()) {
+    *failure = Failure::cast(result);
+    return false;
   }
-  __ LeaveInternalFrame();
 
-  __ ret(0);
   return true;
 }
 
index 2b79016..69219ee 100644 (file)
@@ -982,7 +982,6 @@ void AccessorInfo::AccessorInfoVerify() {
   VerifyPointer(name());
   VerifyPointer(data());
   VerifyPointer(flag());
-  VerifyPointer(load_stub_cache());
 }
 
 void AccessorInfo::AccessorInfoPrint() {
@@ -997,8 +996,6 @@ void AccessorInfo::AccessorInfoPrint() {
   data()->ShortPrint();
   PrintF("\n - flag: ");
   flag()->ShortPrint();
-  PrintF("\n - load_stub_cache: ");
-  load_stub_cache()->ShortPrint();
 }
 
 void AccessCheckInfo::AccessCheckInfoVerify() {
@@ -1048,7 +1045,6 @@ void CallHandlerInfo::CallHandlerInfoVerify() {
   CHECK(IsCallHandlerInfo());
   VerifyPointer(callback());
   VerifyPointer(data());
-  VerifyPointer(call_stub_cache());
 }
 
 void CallHandlerInfo::CallHandlerInfoPrint() {
@@ -1058,7 +1054,6 @@ void CallHandlerInfo::CallHandlerInfoPrint() {
   PrintF("\n - data: ");
   data()->ShortPrint();
   PrintF("\n - call_stub_cache: ");
-  call_stub_cache()->ShortPrint();
 }
 
 void TemplateInfo::TemplateInfoVerify() {
index 79d70e1..499cb91 100644 (file)
@@ -2542,7 +2542,6 @@ ACCESSORS(AccessorInfo, setter, Object, kSetterOffset)
 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(InterceptorInfo, data, Object, kDataOffset)
 
 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)
index 9d975ec..b52bac2 100644 (file)
@@ -5327,7 +5327,6 @@ class AccessorInfo: public Struct {
   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 @@ class AccessorInfo: public Struct {
   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 @@ class CallHandlerInfo: public Struct {
  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 @@ class CallHandlerInfo: public Struct {
 
   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);
index c179769..291375c 100644 (file)
@@ -2483,20 +2483,6 @@ void CEntryStub::GenerateThrowTOS(MacroAssembler* masm) {
 }
 
 
-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,
                               Label* throw_normal_exception,
                               Label* throw_termination_exception,
index 293d8a5..a7dc1e9 100644 (file)
@@ -327,7 +327,7 @@ MaybeObject* MacroAssembler::TryCallStub(CodeStub* stub) {
 
 
 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);
 }
 
@@ -456,6 +456,24 @@ void MacroAssembler::TailCallExternalReference(const ExternalReference& ext,
 }
 
 
+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,
                                      int num_arguments,
                                      int result_size) {
@@ -463,6 +481,15 @@ void MacroAssembler::TailCallRuntime(Runtime::FunctionId fid,
 }
 
 
+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) {
   int64_t offset = (ref0.address() - ref1.address());
   // Check that fits into int.
@@ -471,12 +498,24 @@ static int Offset(ExternalReference ref0, ExternalReference ref1) {
 }
 
 
-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 @@ void MacroAssembler::CallApiFunctionAndReturn(ApiFunction* function) {
   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 @@ void MacroAssembler::CallApiFunctionAndReturn(ApiFunction* function) {
   call(rax);
   movq(rax, prev_limit_reg);
   jmp(&leave_exit_frame);
+
+  return result;
 }
 
 
@@ -566,6 +611,15 @@ void MacroAssembler::JumpToExternalReference(const ExternalReference& ext,
 }
 
 
+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) {
   // Calls are not allowed in some stubs.
   ASSERT(flag == JUMP_FUNCTION || allow_stub_calls());
@@ -1742,6 +1796,10 @@ void MacroAssembler::EnterApiExitFrame(int stack_space,
   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);
 }
 
index 7007374..2554868 100644 (file)
@@ -813,22 +813,38 @@ class MacroAssembler: public Assembler {
                                  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);
 
-  // Prepares stack to put arguments (aligns and so on).
-  // Uses calle-saved esi to restore stack state after call.
-  void PrepareCallApiFunction(int stack_space);
+  // Jump to a runtime routine.
+  MaybeObject* TryJumpToExternalReference(const ExternalReference& ext,
+                                          int result_size);
 
-  // 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);
+  // Prepares stack to put arguments (aligns and so on).
+  // 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],
index 24609bf..13a543f 100644 (file)
@@ -1844,7 +1844,7 @@ MaybeObject* LoadStubCompiler::CompileLoadCallback(String* name,
   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 @@ bool StubCompiler::GenerateLoadCallback(JSObject* object,
 
   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 @@ bool StubCompiler::GenerateLoadCallback(JSObject* object,
   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;
 }