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)
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;