Bug 1399921 - Register zone allocator independently, and delay jemalloc initialization on mac. r=njn
authorMike Hommey <mh+mozilla@glandium.org>
Fri, 15 Sep 2017 07:34:48 +0900
changeset 665565 50770364778192f030136c3ac91528fbe994df28
parent 665564 013516394a9cd0ccfed501b78f796cfdf877654d
child 665566 a7f12e31f7e02368b00d72ac73bf3c661d55d0ad
push id80115
push userbmo:eoger@fastmail.com
push dateFri, 15 Sep 2017 18:29:01 +0000
bugs1399921, 1361258
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.
--- a/memory/build/mozjemalloc.cpp
+++ b/memory/build/mozjemalloc.cpp
@@ -4370,34 +4370,30 @@ huge_dalloc(void *ptr)
  * 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
 static inline bool
 	if (malloc_initialized == false)
 		return (malloc_init_hard());
 	return (false);
-#if defined(XP_DARWIN)
-extern "C" void register_zone(void);
 static size_t
   static size_t kernel_page_size = ([]() {
 #ifdef XP_WIN
     SYSTEM_INFO info;
     return info.dwPageSize;
@@ -4652,20 +4648,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);
-#if defined(XP_DARWIN)
-  register_zone();
 #ifndef XP_WIN
   return false;
  * End general internal functions.
@@ -5445,28 +5437,16 @@ replace_malloc_init_funcs()
 #include "malloc_decls.h"
 #  include <dlfcn.h>
-#if defined(XP_DARWIN)
-	if (malloc_init_hard())
 #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();
+ __attribute__((constructor))
+static 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;