Bug 976247 - Remove a useless static keyword from mozilla::detail::DEAD; r=froydnj
☠☠ backed out by f0ce508ce329 ☠ ☠
authorEhsan Akhgari <ehsan@mozilla.com>
Mon, 24 Feb 2014 19:37:34 -0500
changeset 170661 f74c9326b89c94440109bbcfc99330695b6576d5
parent 170660 53c7d68128b9829e69e4a5d8ead7a732ad1a5bc3
child 170662 8d8165293e9b34761a1517f7904488742d47dcd8
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewersfroydnj
bugs976247
milestone30.0a1
Bug 976247 - Remove a useless static keyword from mozilla::detail::DEAD; r=froydnj
mfbt/RefPtr.h
mfbt/WeakPtr.h
xpcom/base/nsTraceRefcntImpl.cpp
--- a/mfbt/RefPtr.h
+++ b/mfbt/RefPtr.h
@@ -9,16 +9,19 @@
 #ifndef mozilla_RefPtr_h
 #define mozilla_RefPtr_h
 
 #include "mozilla/Assertions.h"
 #include "mozilla/Atomics.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/RefCountType.h"
 #include "mozilla/TypeTraits.h"
+#if defined(MOZILLA_INTERNAL_API)
+#include "nsTraceRefcnt.h"
+#endif
 
 namespace mozilla {
 
 template<typename T> class RefCounted;
 template<typename T> class RefPtr;
 template<typename T> class TemporaryRef;
 template<typename T> class OutParamRef;
 template<typename T> OutParamRef<T> byRef(RefPtr<T>&);
@@ -48,16 +51,38 @@ template<typename T> OutParamRef<T> byRe
  * should add MOZ_DECLARE_REFCOUNTED_TYPENAME(ClassName) to the public
  * section of your class, where ClassName is the name of your class.
  */
 namespace detail {
 #ifdef DEBUG
 static const MozRefCountType DEAD = 0xffffdead;
 #endif
 
+// When building code that gets compiled into Gecko, try to use the
+// trace-refcount leak logging facilities.
+#if defined(MOZILLA_INTERNAL_API) && (defined(DEBUG) || defined(FORCE_BUILD_REFCNT_LOGGING))
+class RefCountLogger
+{
+  public:
+    static void logAddRef(const void* aPointer, MozRefCountType aRefCount,
+                          const char* aTypeName, uint32_t aInstanceSize)
+    {
+      MOZ_ASSERT(aRefCount != DEAD);
+      NS_LogAddRef(const_cast<void*>(aPointer), aRefCount, aTypeName, aInstanceSize);
+    }
+
+    static void logRelease(const void* aPointer, MozRefCountType aRefCount,
+                           const char* aTypeName)
+    {
+      MOZ_ASSERT(aRefCount != DEAD);
+      NS_LogRelease(const_cast<void*>(aPointer), aRefCount, aTypeName);
+    }
+};
+#endif
+
 // This is used WeakPtr.h as well as this file.
 enum RefCountAtomicity
 {
   AtomicRefCount,
   NonAtomicRefCount
 };
 
 template<typename T, RefCountAtomicity Atomicity>
@@ -71,21 +96,30 @@ class RefCounted
       MOZ_ASSERT(refCnt == detail::DEAD);
     }
 
   public:
     // Compatibility with nsRefPtr.
     void AddRef() const {
       MOZ_ASSERT(int32_t(refCnt) >= 0);
       ++refCnt;
+#if defined(MOZILLA_INTERNAL_API) && (defined(DEBUG) || defined(FORCE_BUILD_REFCNT_LOGGING))
+      detail::RefCountLogger::logAddRef(static_cast<const T*>(this), refCnt,
+                                        static_cast<const T*>(this)->typeName(), sizeof(T));
+#endif
     }
 
     void Release() const {
       MOZ_ASSERT(int32_t(refCnt) > 0);
-      if (0 == --refCnt) {
+      --refCnt;
+#if defined(MOZILLA_INTERNAL_API) && (defined(DEBUG) || defined(FORCE_BUILD_REFCNT_LOGGING))
+      detail::RefCountLogger::logRelease(static_cast<const T*>(this), refCnt,
+                                         static_cast<const T*>(this)->typeName());
+#endif
+      if (0 == refCnt) {
 #ifdef DEBUG
         refCnt = detail::DEAD;
 #endif
         delete static_cast<const T*>(this);
       }
     }
 
     // Compatibility with wtf::RefPtr.
--- a/mfbt/WeakPtr.h
+++ b/mfbt/WeakPtr.h
@@ -59,21 +59,24 @@
  *
  * The API was loosely inspired by Chromium's weak_ptr.h:
  * http://src.chromium.org/svn/trunk/src/base/memory/weak_ptr.h
  */
 
 #ifndef mozilla_WeakPtr_h
 #define mozilla_WeakPtr_h
 
+#include "mozilla/ArrayUtils.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/NullPtr.h"
 #include "mozilla/RefPtr.h"
 #include "mozilla/TypeTraits.h"
 
+#include <string.h>
+
 namespace mozilla {
 
 template <typename T, class WeakReference> class WeakPtrBase;
 template <typename T, class WeakReference> class SupportsWeakPtrBase;
 
 namespace detail {
 
 // This can live beyond the lifetime of the class derived from SupportsWeakPtrBase.
@@ -81,16 +84,30 @@ template<class T>
 class WeakReference : public ::mozilla::RefCounted<WeakReference<T> >
 {
   public:
     explicit WeakReference(T* p) : ptr(p) {}
     T* get() const {
       return ptr;
     }
 
+    const char* typeName() const {
+      static char nameBuffer[1024];
+      const char* innerType = ptr->typeName();
+      // We could do fancier length checks at runtime, but innerType is
+      // controlled by us so we can ensure that this never causes a buffer
+      // overflow by this assertion.
+      MOZ_ASSERT(strlen(innerType) + sizeof("WeakReference<>") < ArrayLength(nameBuffer),
+                 "Exceedingly large type name");
+      sprintf(nameBuffer, "WeakReference<%s>", innerType);
+      // This is usually not OK, but here we are returning a pointer to a static
+      // buffer which will immediately be used by the caller.
+      return nameBuffer;
+    }
+
   private:
     friend class WeakPtrBase<T, WeakReference<T> >;
     friend class SupportsWeakPtrBase<T, WeakReference<T> >;
     void detach() {
       ptr = nullptr;
     }
     T* ptr;
 };
--- a/xpcom/base/nsTraceRefcntImpl.cpp
+++ b/xpcom/base/nsTraceRefcntImpl.cpp
@@ -119,16 +119,23 @@ struct nsTraceRefcntStats {
   uint64_t mAddRefs;
   uint64_t mReleases;
   uint64_t mCreates;
   uint64_t mDestroys;
   double mRefsOutstandingTotal;
   double mRefsOutstandingSquared;
   double mObjsOutstandingTotal;
   double mObjsOutstandingSquared;
+  void dump(FILE* out) {
+    fprintf(out, "mAddRefs: %" PRIu64 ", ", mAddRefs);
+    fprintf(out, "mReleases: %" PRIu64 ", ", mReleases);
+    fprintf(out, "mCreates: %" PRIu64 ", ", mCreates);
+    fprintf(out, "mDestroys: %" PRIu64 ", ", mDestroys);
+    fprintf(out, "\n");
+  }
 };
 
   // I hope to turn this on for everybody once we hit it a little less.
 #ifdef DEBUG
 static const char kStaticCtorDtorWarning[] =
   "XPCOM objects created/destroyed from static ctor/dtor";
 
 static void
@@ -363,16 +370,17 @@ public:
     if ((stats->mAddRefs - stats->mReleases) != 0 ||
         stats->mAddRefs != 0 ||
         meanRefs != 0 ||
         stddevRefs != 0 ||
         (stats->mCreates - stats->mDestroys) != 0 ||
         stats->mCreates != 0 ||
         meanObjs != 0 ||
         stddevObjs != 0) {
+      stats->dump(out);
       fprintf(out, "%4d %-40.40s %8d %8" PRIu64 " %8" PRIu64 " %8" PRIu64 " (%8.2f +/- %8.2f) %8" PRIu64 " %8" PRIu64 " (%8.2f +/- %8.2f)\n",
               i+1, mClassName,
               (int32_t)mClassSize,
               (nsCRT::strcmp(mClassName, "TOTAL"))
                   ?(uint64_t)((stats->mCreates - stats->mDestroys) * mClassSize)
                   :mTotalLeaked,
               stats->mCreates,
               (stats->mCreates - stats->mDestroys),