Bug 995893 part.1 Use nsAutoRefCnt in IUnknown inherited classes and log the refcounting r=jimm
authorMasayuki Nakano <masayuki@d-toybox.com>
Sat, 12 Jul 2014 02:09:59 +0900
changeset 193622 05ae727d8db22d25ef19d4cd6f17681e5418cbed
parent 193621 9ded0b5313b40c3e95e38a9c5067f69431218a06
child 193623 5d68184741eac8d184ff718320482d050abfcfe0
push id27123
push userryanvm@gmail.com
push dateFri, 11 Jul 2014 20:35:05 +0000
treeherdermozilla-central@84bd8d9f4256 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimm
bugs995893
milestone33.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 995893 part.1 Use nsAutoRefCnt in IUnknown inherited classes and log the refcounting r=jimm
widget/windows/WinUtils.h
widget/windows/nsTextStore.cpp
widget/windows/nsTextStore.h
--- a/widget/windows/WinUtils.h
+++ b/widget/windows/WinUtils.h
@@ -21,16 +21,53 @@
 #include "nsIFaviconService.h"
 #endif
 #include "nsIDownloader.h"
 #include "nsIURI.h"
 #include "nsIWidget.h"
 
 #include "mozilla/Attributes.h"
 
+/**
+ * NS_INLINE_DECL_IUNKNOWN_REFCOUNTING should be used for defining and
+ * implementing AddRef() and Release() of IUnknown interface.
+ * This depends on xpcom/glue/nsISupportsImpl.h.
+ */
+
+#define NS_INLINE_DECL_IUNKNOWN_REFCOUNTING(_class)                           \
+public:                                                                       \
+  STDMETHODIMP_(ULONG) AddRef()                                               \
+  {                                                                           \
+    MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class)                                \
+    MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt");                      \
+    NS_ASSERT_OWNINGTHREAD(_class);                                           \
+    ++mRefCnt;                                                                \
+    NS_LOG_ADDREF(this, mRefCnt, #_class, sizeof(*this));                     \
+    return static_cast<ULONG>(mRefCnt.get());                                 \
+  }                                                                           \
+  STDMETHODIMP_(ULONG) Release()                                              \
+  {                                                                           \
+    MOZ_ASSERT(int32_t(mRefCnt) > 0,                                          \
+      "Release called on object that has already been released!");            \
+    NS_ASSERT_OWNINGTHREAD(_class);                                           \
+    --mRefCnt;                                                                \
+    NS_LOG_RELEASE(this, mRefCnt, #_class);                                   \
+    if (mRefCnt == 0) {                                                       \
+      NS_ASSERT_OWNINGTHREAD(_class);                                         \
+      mRefCnt = 1; /* stabilize */                                            \
+      delete this;                                                            \
+      return 0;                                                               \
+    }                                                                         \
+    return static_cast<ULONG>(mRefCnt.get());                                 \
+  }                                                                           \
+protected:                                                                    \
+  nsAutoRefCnt mRefCnt;                                                       \
+  NS_DECL_OWNINGTHREAD                                                        \
+public:
+
 class nsWindow;
 class nsWindowBase;
 struct KeyPair;
 struct nsIntRect;
 class nsIThread;
 
 namespace mozilla {
 namespace widget {
--- a/widget/windows/nsTextStore.cpp
+++ b/widget/windows/nsTextStore.cpp
@@ -56,37 +56,24 @@ PRLogModuleInfo* sTextStoreLog = nullptr
 
 /******************************************************************/
 /* InputScopeImpl                                                 */
 /******************************************************************/
 
 class InputScopeImpl MOZ_FINAL : public ITfInputScope
 {
 public:
-  InputScopeImpl(const nsTArray<InputScope>& aList) :
-    mRefCnt(1),
-    mInputScopes(aList)
+  InputScopeImpl(const nsTArray<InputScope>& aList)
+    : mInputScopes(aList)
   {
     PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
       ("TSF: 0x%p InputScopeImpl()", this));
   }
 
-  STDMETHODIMP_(ULONG) AddRef(void) { return ++mRefCnt; }
-
-  STDMETHODIMP_(ULONG) Release(void)
-  {
-    --mRefCnt;
-    if (mRefCnt) {
-      return mRefCnt;
-    }
-    PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
-      ("TSF: 0x%p InputScopeImpl::Release() final", this));
-    delete this;
-    return 0;
-  }
+  NS_INLINE_DECL_IUNKNOWN_REFCOUNTING(InputScopeImpl)
 
   STDMETHODIMP QueryInterface(REFIID riid, void** ppv)
   {
     *ppv=nullptr;
     if ( (IID_IUnknown == riid) || (IID_ITfInputScope == riid) ) {
       *ppv = static_cast<ITfInputScope*>(this);
     }
     if (*ppv) {
@@ -122,17 +109,16 @@ public:
   }
 
   STDMETHODIMP GetPhrase(BSTR **ppbstrPhrases, UINT *pcCount) { return E_NOTIMPL; }
   STDMETHODIMP GetRegularExpression(BSTR *pbstrRegExp) { return E_NOTIMPL; }
   STDMETHODIMP GetSRGS(BSTR *pbstrSRGS) { return E_NOTIMPL; }
   STDMETHODIMP GetXML(BSTR *pbstrXML) { return E_NOTIMPL; }
 
 private:
-  DWORD mRefCnt;
   nsTArray<InputScope> mInputScopes;
 };
 
 /******************************************************************/
 /* nsTextStore                                                    */
 /******************************************************************/
 
 ITfThreadMgr*           nsTextStore::sTsfThreadMgr   = nullptr;
@@ -514,17 +500,16 @@ GetDisplayAttrStr(const TF_DISPLAYATTRIB
   return str;
 }
 
 #endif // #ifdef PR_LOGGING
 
 nsTextStore::nsTextStore()
  : mContent(mComposition, mSelection)
 {
-  mRefCnt = 1;
   mEditCookie = 0;
   mIPProfileCookie = TF_INVALID_COOKIE;
   mLangProfileCookie = TF_INVALID_COOKIE;
   mSinkMask = 0;
   mLock = 0;
   mLockQueued = 0;
   mInputScopeDetected = false;
   mInputScopeRequested = false;
@@ -756,30 +741,16 @@ nsTextStore::QueryInterface(REFIID riid,
   }
 
   PR_LOG(sTextStoreLog, PR_LOG_ERROR,
     ("TSF: 0x%p nsTextStore::QueryInterface() FAILED, riid=%s",
      this, GetRIIDNameStr(riid).get()));
   return E_NOINTERFACE;
 }
 
-STDMETHODIMP_(ULONG) nsTextStore::AddRef()
-{
-  return ++mRefCnt;
-}
-
-STDMETHODIMP_(ULONG) nsTextStore::Release()
-{
-  --mRefCnt;
-  if (0 != mRefCnt)
-    return mRefCnt;
-  delete this;
-  return 0;
-}
-
 STDMETHODIMP
 nsTextStore::AdviseSink(REFIID riid,
                         IUnknown *punk,
                         DWORD dwMask)
 {
   PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
     ("TSF: 0x%p nsTextStore::AdviseSink(riid=%s, punk=0x%p, dwMask=%s), "
      "mSink=0x%p, mSinkMask=%s",
@@ -2247,17 +2218,18 @@ nsTextStore::RetrieveRequestedAttrs(ULON
 
     paAttrVals->idAttr = GUID_PROP_INPUTSCOPE;
     paAttrVals->dwOverlapId = 0;
     paAttrVals->varValue.vt = VT_EMPTY;
     *pcFetched = 1;
 
     if (mInputScopeRequested) {
       paAttrVals->varValue.vt = VT_UNKNOWN;
-      paAttrVals->varValue.punkVal = (IUnknown*) new InputScopeImpl(mInputScopes);
+      nsRefPtr<IUnknown> inputScope = new InputScopeImpl(mInputScopes);
+      paAttrVals->varValue.punkVal = inputScope.forget().take();
     }
 
     mInputScopeDetected = mInputScopeRequested = false;
     return S_OK;
   }
 
   PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
          ("TSF: 0x%p   nsTextStore::RetrieveRequestedAttrs() called "
--- a/widget/windows/nsTextStore.h
+++ b/widget/windows/nsTextStore.h
@@ -6,16 +6,17 @@
 #ifndef NSTEXTSTORE_H_
 #define NSTEXTSTORE_H_
 
 #include "nsAutoPtr.h"
 #include "nsString.h"
 #include "nsCOMPtr.h"
 #include "nsIWidget.h"
 #include "nsWindowBase.h"
+#include "WinUtils.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/TextRange.h"
 #include "mozilla/WindowsVersion.h"
 
 #include <msctf.h>
 #include <textstor.h>
 
 // GUID_PROP_INPUTSCOPE is declared in inputscope.h using INIT_GUID.
@@ -48,19 +49,19 @@ struct MSGResult;
  */
 
 class nsTextStore MOZ_FINAL : public ITextStoreACP,
                               public ITfContextOwnerCompositionSink,
                               public ITfActiveLanguageProfileNotifySink,
                               public ITfInputProcessorProfileActivationSink
 {
 public: /*IUnknown*/
-  STDMETHODIMP_(ULONG)  AddRef(void);
   STDMETHODIMP          QueryInterface(REFIID, void**);
-  STDMETHODIMP_(ULONG)  Release(void);
+
+  NS_INLINE_DECL_IUNKNOWN_REFCOUNTING(nsTextStore)
 
 public: /*ITextStoreACP*/
   STDMETHODIMP AdviseSink(REFIID, IUnknown*, DWORD);
   STDMETHODIMP UnadviseSink(IUnknown*);
   STDMETHODIMP RequestLock(DWORD, HRESULT*);
   STDMETHODIMP GetStatus(TS_STATUS*);
   STDMETHODIMP QueryInsert(LONG, LONG, ULONG, LONG*, LONG*);
   STDMETHODIMP GetSelection(ULONG, ULONG, TS_SELECTION_ACP*, ULONG*);
@@ -691,14 +692,11 @@ protected:
   static ITfInputProcessorProfiles* sInputProcessorProfiles;
 
   // Enables/Disables hack for specific TIP.
   static bool sCreateNativeCaretForATOK;
 
   // Message the Tablet Input Panel uses to flush text during blurring.
   // See comments in Destroy
   static UINT           sFlushTIPInputMessage;
-
-private:
-  ULONG                       mRefCnt;
 };
 
 #endif /*NSTEXTSTORE_H_*/