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 188516 f74c9326b89c94440109bbcfc99330695b6576d5
parent 188515 53c7d68128b9829e69e4a5d8ead7a732ad1a5bc3
child 188517 8d8165293e9b34761a1517f7904488742d47dcd8
push id474
push userasasaki@mozilla.com
push dateMon, 02 Jun 2014 21:01:02 +0000
treeherdermozilla-release@967f4cf1b31c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs976247
milestone30.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 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),