Bug 1533240 - Replace DMD's custom TLS code with use of mozilla/ThreadLocal.h. r=erahm
☠☠ backed out by bc61185b6f57 ☠ ☠
authorNicholas Nethercote <nnethercote@mozilla.com>
Thu, 14 Mar 2019 01:05:15 +0000
changeset 521823 46f6705f9c0c2c8bbd45b60615a1081f40a8402b
parent 521822 779dcbea91ce69857c4aa3a9d1823905cb45ee03
child 521824 64f68305520218d7655672aceebbae9122d38729
push id10867
push userdvarga@mozilla.com
push dateThu, 14 Mar 2019 15:20:45 +0000
treeherdermozilla-beta@abad13547875 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerserahm
bugs1533240
milestone67.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 1533240 - Replace DMD's custom TLS code with use of mozilla/ThreadLocal.h. r=erahm Differential Revision: https://phabricator.services.mozilla.com/D22448
memory/replace/dmd/DMD.cpp
--- a/memory/replace/dmd/DMD.cpp
+++ b/memory/replace/dmd/DMD.cpp
@@ -36,16 +36,17 @@
 #include "mozilla/HashFunctions.h"
 #include "mozilla/HashTable.h"
 #include "mozilla/IntegerPrintfMacros.h"
 #include "mozilla/JSONWriter.h"
 #include "mozilla/Likely.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/PodOperations.h"
 #include "mozilla/StackWalk.h"
+#include "mozilla/ThreadLocal.h"
 
 // CodeAddressService is defined entirely in the header, so this does not make
 // DMD depend on XPCOM's object file.
 #include "CodeAddressService.h"
 
 // replace_malloc.h needs to be included before replace_malloc_bridge.h,
 // which DMD.h includes, so DMD.h needs to be included after replace_malloc.h.
 #include "replace_malloc.h"
@@ -430,85 +431,68 @@ class AutoUnlockState {
   DISALLOW_COPY_AND_ASSIGN(AutoUnlockState);
 
  public:
   AutoUnlockState() { gStateLock->Unlock(); }
   ~AutoUnlockState() { gStateLock->Lock(); }
 };
 
 //---------------------------------------------------------------------------
-// Thread-local storage and blocking of intercepts
+// Per-thread blocking of intercepts
 //---------------------------------------------------------------------------
 
-#ifdef XP_WIN
-
-#  define DMD_TLS_INDEX_TYPE DWORD
-#  define DMD_CREATE_TLS_INDEX(i_) \
-    do {                           \
-      (i_) = TlsAlloc();           \
-    } while (0)
-#  define DMD_DESTROY_TLS_INDEX(i_) TlsFree((i_))
-#  define DMD_GET_TLS_DATA(i_) TlsGetValue((i_))
-#  define DMD_SET_TLS_DATA(i_, v_) TlsSetValue((i_), (v_))
-
-#else
-
-#  define DMD_TLS_INDEX_TYPE pthread_key_t
-#  define DMD_CREATE_TLS_INDEX(i_) pthread_key_create(&(i_), nullptr)
-#  define DMD_DESTROY_TLS_INDEX(i_) pthread_key_delete((i_))
-#  define DMD_GET_TLS_DATA(i_) pthread_getspecific((i_))
-#  define DMD_SET_TLS_DATA(i_, v_) pthread_setspecific((i_), (v_))
-
-#endif
-
-static DMD_TLS_INDEX_TYPE gTlsIndex;
-
 class Thread {
   // Required for allocation via InfallibleAllocPolicy::new_.
   friend class InfallibleAllocPolicy;
 
   // When true, this blocks intercepts, which allows malloc interception
   // functions to themselves call malloc.  (Nb: for direct calls to malloc we
   // can just use InfallibleAllocPolicy::{malloc_,new_}, but we sometimes
   // indirectly call vanilla malloc via functions like MozStackWalk.)
   bool mBlockIntercepts;
 
   Thread() : mBlockIntercepts(false) {}
 
   DISALLOW_COPY_AND_ASSIGN(Thread);
 
+  static MOZ_THREAD_LOCAL(Thread*) tlsThread;
+
  public:
-  static Thread* Fetch();
+  static void Init() {
+    if (!tlsThread.init()) {
+      MOZ_CRASH();
+    }
+  }
+
+  static Thread* Fetch() {
+    Thread* t = tlsThread.get();
+    if (MOZ_UNLIKELY(!t)) {
+      // This memory is never freed, even if the thread dies. It's a leak, but
+      // only a tiny one.
+      t = InfallibleAllocPolicy::new_<Thread>();
+      tlsThread.set(t);
+    }
+
+    return t;
+  }
 
   bool BlockIntercepts() {
     MOZ_ASSERT(!mBlockIntercepts);
     return mBlockIntercepts = true;
   }
 
   bool UnblockIntercepts() {
     MOZ_ASSERT(mBlockIntercepts);
     return mBlockIntercepts = false;
   }
 
   bool InterceptsAreBlocked() const { return mBlockIntercepts; }
 };
 
-/* static */
-Thread* Thread::Fetch() {
-  Thread* t = static_cast<Thread*>(DMD_GET_TLS_DATA(gTlsIndex));
-
-  if (MOZ_UNLIKELY(!t)) {
-    // This memory is never freed, even if the thread dies.  It's a leak, but
-    // only a tiny one.
-    t = InfallibleAllocPolicy::new_<Thread>();
-    DMD_SET_TLS_DATA(gTlsIndex, t);
-  }
-
-  return t;
-}
+MOZ_THREAD_LOCAL(Thread*) Thread::tlsThread;
 
 // An object of this class must be created (on the stack) before running any
 // code that might allocate.
 class AutoBlockIntercepts {
   Thread* const mT;
 
   DISALLOW_COPY_AND_ASSIGN(AutoBlockIntercepts);
 
@@ -1405,17 +1389,17 @@ static bool Init(malloc_table_t* aMalloc
   gOptions = InfallibleAllocPolicy::new_<Options>(e);
 
   gStateLock = InfallibleAllocPolicy::new_<Mutex>();
 
   gBernoulli = (FastBernoulliTrial*)InfallibleAllocPolicy::malloc_(
       sizeof(FastBernoulliTrial));
   ResetBernoulli();
 
-  DMD_CREATE_TLS_INDEX(gTlsIndex);
+  Thread::Init();
 
   {
     AutoLockState lock;
 
     gStackTraceTable = InfallibleAllocPolicy::new_<StackTraceTable>(8192);
     gLiveBlockTable = InfallibleAllocPolicy::new_<LiveBlockTable>(8192);
 
     // Create this even if the mode isn't Cumulative (albeit with a small