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
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
@@ -4365,34 +4365,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;
@@ -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);
-#if defined(XP_DARWIN)
-  register_zone();
 #ifndef XP_WIN
   return false;
  * End general internal functions.
@@ -5440,28 +5432,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;