Bug 1399921 - Register zone allocator independently, and delay jemalloc initialization on mac. r?njn draft
authorMike Hommey <mh+mozilla@glandium.org>
Fri, 15 Sep 2017 07:34:48 +0900
changeset 665133 912ecebecee6be1424459d686cbba4e4207d0d2c
parent 664555 7fbd7a84416c8e129665ecce4f111c0346d33f10
child 665197 d88986fdf81fe4b85e229b46dac0e6482148778a
push id79942
push userbmo:mh+mozilla@glandium.org
push dateThu, 14 Sep 2017 23:58:22 +0000
reviewersnjn
bugs1399921, 1361258
milestone57.0a1
Bug 1399921 - Register zone allocator independently, and delay jemalloc initialization on mac. r?njn In bug 1361258, we unified the initialization sequence on mac, and chose to make the zone registration happen after jemalloc initialization. The order between jemalloc init and zone registration shouldn't actually matter, because jemalloc initializes the first time the allocator is actually used. On the other hand, in some build setups (e.g. with light optimization), the initialization of the thread_arena thread local variable can happen after the forced jemalloc initialization because of the order the corresponding static initializers run. In some levels of optimization, the thread_arena initializer resets the value the jemalloc initialization has set, which subsequently makes choose_arena() return a bogus value (or hit an assertion in ThreadLocal.h on debug builds). So instead of initializing jemalloc from a static initializer, which then registers the zone, we instead register the zone and let jemalloc initialize itself when used, which increases the chances of the thread_arena initializer running first.
memory/build/mozjemalloc.cpp
memory/build/zone.c
--- a/memory/build/mozjemalloc.cpp
+++ b/memory/build/mozjemalloc.cpp
@@ -4365,34 +4365,30 @@ huge_dalloc(void *ptr)
 	base_node_dealloc(node);
 }
 
 /*
  * FreeBSD's pthreads implementation calls malloc(3), so the malloc
  * implementation has to take pains to avoid infinite recursion during
  * initialization.
  */
-#if (defined(XP_WIN) || defined(XP_DARWIN))
+#if defined(XP_WIN)
 #define	malloc_init() false
 #else
 static inline bool
 malloc_init(void)
 {
 
 	if (malloc_initialized == false)
 		return (malloc_init_hard());
 
 	return (false);
 }
 #endif
 
-#if defined(XP_DARWIN)
-extern "C" void register_zone(void);
-#endif
-
 static size_t
 GetKernelPageSize()
 {
   static size_t kernel_page_size = ([]() {
 #ifdef XP_WIN
     SYSTEM_INFO info;
     GetSystemInfo(&info);
     return info.dwPageSize;
@@ -4647,20 +4643,16 @@ MALLOC_OUT:
 
   malloc_initialized = true;
 
 #if !defined(XP_WIN) && !defined(XP_DARWIN)
   /* Prevent potential deadlock on malloc locks after fork. */
   pthread_atfork(_malloc_prefork, _malloc_postfork_parent, _malloc_postfork_child);
 #endif
 
-#if defined(XP_DARWIN)
-  register_zone();
-#endif
-
 #ifndef XP_WIN
   malloc_mutex_unlock(&init_lock);
 #endif
   return false;
 }
 
 /*
  * End general internal functions.
@@ -5440,28 +5432,16 @@ replace_malloc_init_funcs()
 #define MALLOC_FUNCS MALLOC_FUNCS_JEMALLOC
 #include "malloc_decls.h"
 /******************************************************************************/
 
 #ifdef HAVE_DLOPEN
 #  include <dlfcn.h>
 #endif
 
-#if defined(XP_DARWIN)
-
-__attribute__((constructor))
-void
-jemalloc_darwin_init(void)
-{
-	if (malloc_init_hard())
-		MOZ_CRASH();
-}
-
-#endif
-
 #if defined(__GLIBC__) && !defined(__UCLIBC__)
 /*
  * glibc provides the RTLD_DEEPBIND flag for dlopen which can make it possible
  * to inconsistently reference libc's malloc(3)-compatible functions
  * (bug 493541).
  *
  * These definitions interpose hooks in glibc.  The functions are actually
  * passed an extra argument for the caller return address, which will be
--- a/memory/build/zone.c
+++ b/memory/build/zone.c
@@ -340,17 +340,18 @@ static malloc_zone_t *get_default_zone()
   }
   if (num_zones) {
     return zones[0];
   }
   return malloc_default_zone();
 }
 
 
-void
+ __attribute__((constructor))
+static void
 register_zone(void)
 {
   malloc_zone_t *default_zone = get_default_zone();
 
   zone.size = zone_size;
   zone.malloc = zone_malloc;
   zone.calloc = zone_calloc;
   zone.valloc = zone_valloc;