Bug 1395776 - Fold replace-malloc into mozjemalloc. r=njn
authorMike Hommey <mh+mozilla@glandium.org>
Thu, 31 Aug 2017 12:02:01 +0900
changeset 427858 cce866682b2c6858dfd06924c3c843c7f5612826
parent 427857 91571e2385a4dea755d8c019d1dcb6a14c78ce3b
child 427859 59ebc7093c39c6e7af63f12abcb8f064a997a719
push id7761
push userjlund@mozilla.com
push dateFri, 15 Sep 2017 00:19:52 +0000
treeherdermozilla-beta@c38455951db4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnjn
bugs1395776, 1395449
milestone57.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 1395776 - Fold replace-malloc into mozjemalloc. r=njn Add the MPL 2.0 license header per bug 1395449.
memory/build/moz.build
memory/build/mozmemory_wrap.h
memory/build/replace_malloc.c
memory/mozjemalloc/mozjemalloc.cpp
memory/mozjemalloc/mozjemalloc.h
mozglue/build/mozglue.def.in
toolkit/content/license.html
--- a/memory/build/moz.build
+++ b/memory/build/moz.build
@@ -18,21 +18,16 @@ if CONFIG['MOZ_REPLACE_MALLOC']:
         'replace_malloc.h',
         'replace_malloc_bridge.h',
     ]
 
 SOURCES += [
     'mozmemory_wrap.c',
 ]
 
-if CONFIG['MOZ_REPLACE_MALLOC']:
-    SOURCES += [
-        'replace_malloc.c',
-    ]
-
 if CONFIG['OS_TARGET'] == 'Darwin' and (CONFIG['MOZ_REPLACE_MALLOC'] or
         CONFIG['MOZ_MEMORY']):
     SOURCES += [
         'zone.c',
     ]
 
 Library('memory')
 
--- a/memory/build/mozmemory_wrap.h
+++ b/memory/build/mozmemory_wrap.h
@@ -81,32 +81,16 @@
  * appears after mozglue ; which we double check when building anyways)
  *
  *
  * Within libmozglue (when MOZ_MEMORY_IMPL is defined), all the functions
  * should be suffixed with "_impl" both for declarations and use.
  * That is, the implementation declaration for e.g. strdup would look like:
  *   char* strdup_impl(const char *)
  * That implementation would call malloc by using "malloc_impl".
- *
- *
- * When building with replace-malloc support, the above still holds, but
- * the malloc implementation and jemalloc specific functions are the
- * replace-malloc functions from replace_malloc.c.
- *
- * The actual mozjemalloc implementation is prefixed with "je_".
- *
- * Thus, when MOZ_REPLACE_MALLOC is defined, the "_impl" suffixed macros
- * expand to "je_" prefixed function when building mozjemalloc, where
- * MOZ_JEMALLOC_IMPL is defined.
- *
- * In other cases, the "_impl" suffixed macros follow the original scheme,
- * except on Windows and MacOSX, where they would expand to "je_" prefixed
- * functions. Instead, they are left unmodified (malloc_impl expands to
- * malloc_impl).
  */
 
 #ifndef MOZ_MEMORY
 #  error Should only include mozmemory_wrap.h when MOZ_MEMORY is set.
 #endif
 
 #if defined(MOZ_JEMALLOC_IMPL) && !defined(MOZ_MEMORY_IMPL)
 #  define MOZ_MEMORY_IMPL
@@ -124,37 +108,28 @@
 #ifdef __cplusplus
 #define MOZ_EXTERN_C extern "C"
 #else
 #define MOZ_EXTERN_C
 #endif
 #endif
 
 #ifdef MOZ_MEMORY_IMPL
-#  if defined(MOZ_JEMALLOC_IMPL) && defined(MOZ_REPLACE_MALLOC)
-#    define mozmem_malloc_impl(a)     je_ ## a
-#    define mozmem_jemalloc_impl(a)   je_ ## a
+#  define MOZ_JEMALLOC_API MOZ_EXTERN_C MFBT_API
+#  if defined(XP_WIN)
+#    define mozmem_malloc_impl(a)   je_ ## a
 #  else
-#    define MOZ_JEMALLOC_API MOZ_EXTERN_C MFBT_API
-#    if defined(XP_WIN)
-#      if defined(MOZ_REPLACE_MALLOC)
-#        define mozmem_malloc_impl(a)   a ## _impl
-#      else
-#        define mozmem_malloc_impl(a)   je_ ## a
-#      endif
-#    else
-#      define MOZ_MEMORY_API MOZ_EXTERN_C MFBT_API
-#      if defined(MOZ_WIDGET_ANDROID)
-#        define MOZ_WRAP_NEW_DELETE
-#      endif
+#    define MOZ_MEMORY_API MOZ_EXTERN_C MFBT_API
+#    if defined(MOZ_WIDGET_ANDROID)
+#      define MOZ_WRAP_NEW_DELETE
 #    endif
 #  endif
-#  ifdef XP_WIN
-#    define mozmem_dup_impl(a)      wrap_ ## a
-#  endif
+#endif
+#ifdef XP_WIN
+#  define mozmem_dup_impl(a)      wrap_ ## a
 #endif
 
 #if !defined(MOZ_MEMORY_IMPL)
 #  define MOZ_MEMORY_API MOZ_EXTERN_C MFBT_API
 #  define MOZ_JEMALLOC_API MOZ_EXTERN_C MFBT_API
 #endif
 
 #ifndef MOZ_MEMORY_API
deleted file mode 100644
--- a/memory/build/replace_malloc.c
+++ /dev/null
@@ -1,294 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef MOZ_MEMORY
-#  error Should not compile this file when MOZ_MEMORY is not set
-#endif
-
-#ifndef MOZ_REPLACE_MALLOC
-#  error Should not compile this file when replace-malloc is disabled
-#endif
-
-#include "mozmemory_wrap.h"
-
-/* Declare all je_* functions */
-#define MALLOC_DECL(name, return_type, ...) \
-  return_type je_ ## name(__VA_ARGS__);
-#include "malloc_decls.h"
-
-#include "mozilla/Likely.h"
-#include "mozilla/MacroArgs.h"
-#include <errno.h>
-#ifndef XP_WIN
-#include <unistd.h>
-#endif
-
-/*
- * Windows doesn't come with weak imports as they are possible with
- * LD_PRELOAD or DYLD_INSERT_LIBRARIES on Linux/OSX. On this platform,
- * the replacement functions are defined as variable pointers to the
- * function resolved with GetProcAddress() instead of weak definitions
- * of functions. On Android, the same needs to happen as well, because
- * the Android linker doesn't handle weak linking with non LD_PRELOADed
- * libraries, but LD_PRELOADing is not very convenient on Android, with
- * the zygote.
- */
-#ifdef XP_DARWIN
-#  define MOZ_REPLACE_WEAK __attribute__((weak_import))
-#elif defined(XP_WIN) || defined(MOZ_WIDGET_ANDROID)
-#  define MOZ_NO_REPLACE_FUNC_DECL
-#elif defined(__GNUC__)
-#  define MOZ_REPLACE_WEAK __attribute__((weak))
-#endif
-
-#include "replace_malloc.h"
-
-#define MALLOC_DECL(name, return_type, ...) \
-    je_ ## name,
-
-static const malloc_table_t malloc_table = {
-#include "malloc_decls.h"
-};
-
-static malloc_table_t replace_malloc_table;
-
-#ifdef MOZ_NO_REPLACE_FUNC_DECL
-#  define MALLOC_DECL(name, return_type, ...) \
-    typedef return_type (name ## _impl_t)(__VA_ARGS__); \
-    name ## _impl_t* replace_ ## name = NULL;
-#  define MALLOC_FUNCS (MALLOC_FUNCS_INIT | MALLOC_FUNCS_BRIDGE)
-#  include "malloc_decls.h"
-#endif
-
-#ifdef XP_WIN
-#  include <windows.h>
-
-typedef HMODULE replace_malloc_handle_t;
-
-static replace_malloc_handle_t
-replace_malloc_handle()
-{
-  char replace_malloc_lib[1024];
-  if (GetEnvironmentVariableA("MOZ_REPLACE_MALLOC_LIB", (LPSTR)&replace_malloc_lib,
-                              sizeof(replace_malloc_lib)) > 0) {
-    return LoadLibraryA(replace_malloc_lib);
-  }
-  return NULL;
-}
-
-#    define REPLACE_MALLOC_GET_FUNC(handle, name) \
-      (name ## _impl_t*) GetProcAddress(handle, "replace_" # name)
-
-#elif defined(MOZ_WIDGET_ANDROID)
-#  include <dlfcn.h>
-#  include <stdlib.h>
-
-typedef void* replace_malloc_handle_t;
-
-static replace_malloc_handle_t
-replace_malloc_handle()
-{
-  const char *replace_malloc_lib = getenv("MOZ_REPLACE_MALLOC_LIB");
-  if (replace_malloc_lib && *replace_malloc_lib) {
-    return dlopen(replace_malloc_lib, RTLD_LAZY);
-  }
-  return NULL;
-}
-
-#  define REPLACE_MALLOC_GET_FUNC(handle, name) \
-    (name ## _impl_t*) dlsym(handle, "replace_" # name)
-
-#else
-
-#  include <stdbool.h>
-
-typedef bool replace_malloc_handle_t;
-
-static replace_malloc_handle_t
-replace_malloc_handle()
-{
-  return true;
-}
-
-#  define REPLACE_MALLOC_GET_FUNC(handle, name) \
-    replace_ ## name
-
-#endif
-
-static void replace_malloc_init_funcs();
-
-/*
- * Below is the malloc implementation overriding jemalloc and calling the
- * replacement functions if they exist.
- */
-
-static int replace_malloc_initialized = 0;
-static void
-init()
-{
-  replace_malloc_init_funcs();
-  // Set this *before* calling replace_init, otherwise if replace_init calls
-  // malloc() we'll get an infinite loop.
-  replace_malloc_initialized = 1;
-  if (replace_init)
-    replace_init(&malloc_table);
-}
-
-/*
- * Malloc implementation functions are MOZ_MEMORY_API, and jemalloc
- * specific functions MOZ_JEMALLOC_API; see mozmemory_wrap.h
- */
-#define MACRO_CALL(a, b) a b
-/* Can't use macros recursively, so we need another one doing the same as above. */
-#define MACRO_CALL2(a, b) a b
-
-#define ARGS_HELPER(name, ...) MACRO_CALL2( \
-  MOZ_PASTE_PREFIX_AND_ARG_COUNT(name, ##__VA_ARGS__), \
-  (__VA_ARGS__))
-#define TYPED_ARGS0()
-#define TYPED_ARGS1(t1) t1 arg1
-#define TYPED_ARGS2(t1, t2) TYPED_ARGS1(t1), t2 arg2
-#define TYPED_ARGS3(t1, t2, t3) TYPED_ARGS2(t1, t2), t3 arg3
-
-#define ARGS0()
-#define ARGS1(t1) arg1
-#define ARGS2(t1, t2) ARGS1(t1), arg2
-#define ARGS3(t1, t2, t3) ARGS2(t1, t2), arg3
-
-#define GENERIC_MALLOC_DECL_HELPER(name, return, return_type, ...) \
-  return_type name ## _impl(ARGS_HELPER(TYPED_ARGS, ##__VA_ARGS__)) \
-  { \
-    if (MOZ_UNLIKELY(!replace_malloc_initialized)) \
-      init(); \
-    return replace_malloc_table.name(ARGS_HELPER(ARGS, ##__VA_ARGS__)); \
-  }
-
-#define GENERIC_MALLOC_DECL(name, return_type, ...) \
-  GENERIC_MALLOC_DECL_HELPER(name, return, return_type, ##__VA_ARGS__)
-#define GENERIC_MALLOC_DECL_VOID(name, ...) \
-  GENERIC_MALLOC_DECL_HELPER(name, , void, ##__VA_ARGS__)
-
-#define MALLOC_DECL(...) MOZ_MEMORY_API MACRO_CALL(GENERIC_MALLOC_DECL, (__VA_ARGS__))
-#define MALLOC_DECL_VOID(...) MOZ_MEMORY_API MACRO_CALL(GENERIC_MALLOC_DECL_VOID, (__VA_ARGS__))
-#define MALLOC_FUNCS MALLOC_FUNCS_MALLOC
-#include "malloc_decls.h"
-
-#define MALLOC_DECL(...) MOZ_JEMALLOC_API MACRO_CALL(GENERIC_MALLOC_DECL, (__VA_ARGS__))
-#define MALLOC_DECL_VOID(...) MOZ_JEMALLOC_API MACRO_CALL(GENERIC_MALLOC_DECL_VOID, (__VA_ARGS__))
-#define MALLOC_FUNCS MALLOC_FUNCS_JEMALLOC
-#include "malloc_decls.h"
-
-MFBT_API struct ReplaceMallocBridge*
-get_bridge(void)
-{
-  if (MOZ_UNLIKELY(!replace_malloc_initialized))
-    init();
-  if (MOZ_LIKELY(!replace_get_bridge))
-    return NULL;
-  return replace_get_bridge();
-}
-
-/* The following comment and definitions are from jemalloc.c: */
-#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
- * (https://bugzilla.mozilla.org/show_bug.cgi?id=493541).
- *
- * These definitions interpose hooks in glibc.  The functions are actually
- * passed an extra argument for the caller return address, which will be
- * ignored.
- */
-
-typedef void (* __free_hook_type)(void *ptr);
-typedef void *(* __malloc_hook_type)(size_t size);
-typedef void *(* __realloc_hook_type)(void *ptr, size_t size);
-typedef void *(* __memalign_hook_type)(size_t alignment, size_t size);
-
-MOZ_MEMORY_API __free_hook_type __free_hook = free_impl;
-MOZ_MEMORY_API __malloc_hook_type __malloc_hook = malloc_impl;
-MOZ_MEMORY_API __realloc_hook_type __realloc_hook = realloc_impl;
-MOZ_MEMORY_API __memalign_hook_type __memalign_hook = memalign_impl;
-
-#endif
-
-/*
- * posix_memalign, aligned_alloc, memalign and valloc all implement some kind
- * of aligned memory allocation. For convenience, a replace-malloc library can
- * skip defining replace_posix_memalign, replace_aligned_alloc and
- * replace_valloc, and default implementations will be automatically derived
- * from replace_memalign.
- */
-static int
-default_posix_memalign(void** ptr, size_t alignment, size_t size)
-{
-  void *result;
-  /* alignment must be a power of two and a multiple of sizeof(void *) */
-  if (((alignment - 1) & alignment) != 0 || (alignment < sizeof(void *)))
-    return EINVAL;
-  result = replace_malloc_table.memalign(alignment, size);
-  if (!result) {
-    return ENOMEM;
-  }
-  *ptr = result;
-  return 0;
-}
-
-static void*
-default_aligned_alloc(size_t alignment, size_t size)
-{
-  /* size should be a multiple of alignment */
-  if (size % alignment)
-    return NULL;
-  return replace_malloc_table.memalign(alignment, size);
-}
-
-// Nb: sysconf() is expensive, but valloc is obsolete and rarely used.
-static void*
-default_valloc(size_t size)
-{
-#ifdef XP_WIN
-  SYSTEM_INFO si;
-  GetSystemInfo(&si);
-  size_t page_size = si.dwPageSize;
-#else
-  size_t page_size = sysconf(_SC_PAGE_SIZE);
-#endif
-  return replace_malloc_table.memalign(page_size, size);
-}
-
-static void
-replace_malloc_init_funcs()
-{
-  replace_malloc_handle_t handle = replace_malloc_handle();
-  if (handle) {
-#ifdef MOZ_NO_REPLACE_FUNC_DECL
-#  define MALLOC_DECL(name, ...) \
-    replace_ ## name = REPLACE_MALLOC_GET_FUNC(handle, name);
-
-#  define MALLOC_FUNCS (MALLOC_FUNCS_INIT | MALLOC_FUNCS_BRIDGE)
-#  include "malloc_decls.h"
-#endif
-
-#define MALLOC_DECL(name, ...) \
-  replace_malloc_table.name = REPLACE_MALLOC_GET_FUNC(handle, name);
-#include "malloc_decls.h"
-  }
-
-  if (!replace_malloc_table.posix_memalign && replace_malloc_table.memalign)
-    replace_malloc_table.posix_memalign = default_posix_memalign;
-
-  if (!replace_malloc_table.aligned_alloc && replace_malloc_table.memalign)
-    replace_malloc_table.aligned_alloc = default_aligned_alloc;
-
-  if (!replace_malloc_table.valloc && replace_malloc_table.memalign)
-    replace_malloc_table.valloc = default_valloc;
-
-#define MALLOC_DECL(name, ...) \
-  if (!replace_malloc_table.name) { \
-    replace_malloc_table.name = je_ ## name; \
-  }
-#include "malloc_decls.h"
-}
--- a/memory/mozjemalloc/mozjemalloc.cpp
+++ b/memory/mozjemalloc/mozjemalloc.cpp
@@ -1,13 +1,20 @@
 /* -*- Mode: C; tab-width: 8; c-basic-offset: 8; indent-tabs-mode: t -*- */
 /* vim:set softtabstop=8 shiftwidth=8 noet: */
-/*-
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * Portions of this file were originally under the following license:
+ *
  * Copyright (C) 2006-2008 Jason Evans <jasone@FreeBSD.org>.
  * All rights reserved.
+ * Copyright (C) 2007-2017 Mozilla Foundation.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice(s), this list of conditions and the following disclaimer as
  *    the first lines of this file unmodified other than the possible
  *    addition of one or more copyright notices.
@@ -98,16 +105,18 @@
  *          Metadata are stored in a separate red-black tree.
  *
  *******************************************************************************
  */
 
 #include "mozmemory_wrap.h"
 #include "mozjemalloc.h"
 #include "mozilla/Sprintf.h"
+#include "mozilla/Likely.h"
+#include "mozilla/MacroArgs.h"
 
 #ifdef ANDROID
 #define NO_TLS
 #endif
 
 /*
  * On Linux, we use madvise(MADV_DONTNEED) to release memory back to the
  * operating system.  If we release 1MB of live pages with MADV_DONTNEED, our
@@ -5226,17 +5235,17 @@ void
 	}
 	malloc_spin_init(&arenas_lock);
 }
 
 /*
  * End library-private functions.
  */
 /******************************************************************************/
-/* Definition of all the _impl functions */
+/* Macro helpers */
 
 #define MACRO_CALL(a, b) a b
 /* Can't use macros recursively, so we need another one doing the same as above. */
 #define MACRO_CALL2(a, b) a b
 
 #define ARGS_HELPER(name, ...) MACRO_CALL2( \
   MOZ_PASTE_PREFIX_AND_ARG_COUNT(name, ##__VA_ARGS__), \
   (__VA_ARGS__))
@@ -5245,27 +5254,242 @@ void
 #define TYPED_ARGS2(t1, t2) TYPED_ARGS1(t1), t2 arg2
 #define TYPED_ARGS3(t1, t2, t3) TYPED_ARGS2(t1, t2), t3 arg3
 
 #define ARGS0()
 #define ARGS1(t1) arg1
 #define ARGS2(t1, t2) ARGS1(t1), arg2
 #define ARGS3(t1, t2, t3) ARGS2(t1, t2), arg3
 
-#define GENERIC_MALLOC_DECL_HELPER(name, return, return_type, ...) \
-  return_type name##_impl(ARGS_HELPER(TYPED_ARGS, ##__VA_ARGS__)) \
-  { \
-    return MozJemalloc::name(ARGS_HELPER(ARGS, ##__VA_ARGS__)); \
-  }
-
 #define GENERIC_MALLOC_DECL(name, return_type, ...) \
   GENERIC_MALLOC_DECL_HELPER(name, return, return_type, ##__VA_ARGS__)
 #define GENERIC_MALLOC_DECL_VOID(name, ...) \
   GENERIC_MALLOC_DECL_HELPER(name, , void, ##__VA_ARGS__)
 
+/******************************************************************************/
+#ifdef MOZ_REPLACE_MALLOC
+
+/*
+ * Windows doesn't come with weak imports as they are possible with
+ * LD_PRELOAD or DYLD_INSERT_LIBRARIES on Linux/OSX. On this platform,
+ * the replacement functions are defined as variable pointers to the
+ * function resolved with GetProcAddress() instead of weak definitions
+ * of functions. On Android, the same needs to happen as well, because
+ * the Android linker doesn't handle weak linking with non LD_PRELOADed
+ * libraries, but LD_PRELOADing is not very convenient on Android, with
+ * the zygote.
+ */
+#ifdef XP_DARWIN
+#  define MOZ_REPLACE_WEAK __attribute__((weak_import))
+#elif defined(XP_WIN) || defined(MOZ_WIDGET_ANDROID)
+#  define MOZ_NO_REPLACE_FUNC_DECL
+#elif defined(__GNUC__)
+#  define MOZ_REPLACE_WEAK __attribute__((weak))
+#endif
+
+#include "replace_malloc.h"
+
+#define MALLOC_DECL(name, return_type, ...) \
+    MozJemalloc::name,
+
+static const malloc_table_t malloc_table = {
+#include "malloc_decls.h"
+};
+
+static malloc_table_t replace_malloc_table;
+
+#ifdef MOZ_NO_REPLACE_FUNC_DECL
+#  define MALLOC_DECL(name, return_type, ...) \
+    typedef return_type (name##_impl_t)(__VA_ARGS__); \
+    name##_impl_t* replace_##name = nullptr;
+#  define MALLOC_FUNCS (MALLOC_FUNCS_INIT | MALLOC_FUNCS_BRIDGE)
+#  include "malloc_decls.h"
+#endif
+
+#ifdef XP_WIN
+typedef HMODULE replace_malloc_handle_t;
+
+static replace_malloc_handle_t
+replace_malloc_handle()
+{
+  char replace_malloc_lib[1024];
+  if (GetEnvironmentVariableA("MOZ_REPLACE_MALLOC_LIB", (LPSTR)&replace_malloc_lib,
+                              sizeof(replace_malloc_lib)) > 0) {
+    return LoadLibraryA(replace_malloc_lib);
+  }
+  return nullptr;
+}
+
+#    define REPLACE_MALLOC_GET_FUNC(handle, name) \
+      (name##_impl_t*) GetProcAddress(handle, "replace_" # name)
+
+#elif defined(ANDROID)
+#  include <dlfcn.h>
+
+typedef void* replace_malloc_handle_t;
+
+static replace_malloc_handle_t
+replace_malloc_handle()
+{
+  const char *replace_malloc_lib = getenv("MOZ_REPLACE_MALLOC_LIB");
+  if (replace_malloc_lib && *replace_malloc_lib) {
+    return dlopen(replace_malloc_lib, RTLD_LAZY);
+  }
+  return nullptr;
+}
+
+#  define REPLACE_MALLOC_GET_FUNC(handle, name) \
+    (name##_impl_t*) dlsym(handle, "replace_" # name)
+
+#else
+
+typedef bool replace_malloc_handle_t;
+
+static replace_malloc_handle_t
+replace_malloc_handle()
+{
+  return true;
+}
+
+#  define REPLACE_MALLOC_GET_FUNC(handle, name) \
+    replace_##name
+
+#endif
+
+static void replace_malloc_init_funcs();
+
+/*
+ * Below is the malloc implementation overriding jemalloc and calling the
+ * replacement functions if they exist.
+ */
+
+static int replace_malloc_initialized = 0;
+static void
+init()
+{
+  replace_malloc_init_funcs();
+  // Set this *before* calling replace_init, otherwise if replace_init calls
+  // malloc() we'll get an infinite loop.
+  replace_malloc_initialized = 1;
+  if (replace_init) {
+    replace_init(&malloc_table);
+  }
+}
+
+#define GENERIC_MALLOC_DECL_HELPER(name, return, return_type, ...) \
+  template<> inline return_type \
+  ReplaceMalloc::name(ARGS_HELPER(TYPED_ARGS, ##__VA_ARGS__)) \
+  { \
+    if (MOZ_UNLIKELY(!replace_malloc_initialized)) { \
+      init(); \
+    } \
+    return replace_malloc_table.name(ARGS_HELPER(ARGS, ##__VA_ARGS__)); \
+  }
+
+#define MALLOC_DECL(...) MACRO_CALL(GENERIC_MALLOC_DECL, (__VA_ARGS__))
+#define MALLOC_DECL_VOID(...) MACRO_CALL(GENERIC_MALLOC_DECL_VOID, (__VA_ARGS__))
+#define MALLOC_FUNCS (MALLOC_FUNCS_MALLOC | MALLOC_FUNCS_JEMALLOC)
+#include "malloc_decls.h"
+
+#undef GENERIC_MALLOC_DECL_HELPER
+
+MOZ_JEMALLOC_API struct ReplaceMallocBridge*
+get_bridge(void)
+{
+  if (MOZ_UNLIKELY(!replace_malloc_initialized))
+    init();
+  if (MOZ_LIKELY(!replace_get_bridge))
+    return nullptr;
+  return replace_get_bridge();
+}
+
+/*
+ * posix_memalign, aligned_alloc, memalign and valloc all implement some kind
+ * of aligned memory allocation. For convenience, a replace-malloc library can
+ * skip defining replace_posix_memalign, replace_aligned_alloc and
+ * replace_valloc, and default implementations will be automatically derived
+ * from replace_memalign.
+ */
+static int
+default_posix_memalign(void** aPtr, size_t aAlignment, size_t aSize)
+{
+  void* result;
+  /* alignment must be a power of two and a multiple of sizeof(void *) */
+  if (((aAlignment - 1) & aAlignment) != 0 || (aAlignment < sizeof(void *)))
+    return EINVAL;
+  result = replace_malloc_table.memalign(aAlignment, aSize);
+  if (!result) {
+    return ENOMEM;
+  }
+  *aPtr = result;
+  return 0;
+}
+
+static void*
+default_aligned_alloc(size_t aAlignment, size_t aSize)
+{
+  /* size should be a multiple of alignment */
+  if (aSize % aAlignment)
+    return nullptr;
+  return replace_malloc_table.memalign(aAlignment, aSize);
+}
+
+// Nb: sysconf() is expensive, but valloc is obsolete and rarely used.
+static void*
+default_valloc(size_t aSize)
+{
+  return replace_malloc_table.memalign(GetKernelPageSize(), aSize);
+}
+
+static void
+replace_malloc_init_funcs()
+{
+  replace_malloc_handle_t handle = replace_malloc_handle();
+  if (handle) {
+#ifdef MOZ_NO_REPLACE_FUNC_DECL
+#  define MALLOC_DECL(name, ...) \
+    replace_##name = REPLACE_MALLOC_GET_FUNC(handle, name);
+
+#  define MALLOC_FUNCS (MALLOC_FUNCS_INIT | MALLOC_FUNCS_BRIDGE)
+#  include "malloc_decls.h"
+#endif
+
+#define MALLOC_DECL(name, ...) \
+  replace_malloc_table.name = REPLACE_MALLOC_GET_FUNC(handle, name);
+#include "malloc_decls.h"
+  }
+
+  if (!replace_malloc_table.posix_memalign && replace_malloc_table.memalign) {
+    replace_malloc_table.posix_memalign = default_posix_memalign;
+  }
+
+  if (!replace_malloc_table.aligned_alloc && replace_malloc_table.memalign) {
+    replace_malloc_table.aligned_alloc = default_aligned_alloc;
+  }
+
+  if (!replace_malloc_table.valloc && replace_malloc_table.memalign) {
+    replace_malloc_table.valloc = default_valloc;
+  }
+#define MALLOC_DECL(name, ...) \
+  if (!replace_malloc_table.name) { \
+    replace_malloc_table.name = MozJemalloc::name; \
+  }
+#include "malloc_decls.h"
+}
+
+#endif /* MOZ_REPLACE_MALLOC */
+/******************************************************************************/
+/* Definition of all the _impl functions */
+
+#define GENERIC_MALLOC_DECL_HELPER(name, return, return_type, ...) \
+  return_type name##_impl(ARGS_HELPER(TYPED_ARGS, ##__VA_ARGS__)) \
+  { \
+    return DefaultMalloc::name(ARGS_HELPER(ARGS, ##__VA_ARGS__)); \
+  }
+
 #define MALLOC_DECL(...) MOZ_MEMORY_API MACRO_CALL(GENERIC_MALLOC_DECL, (__VA_ARGS__))
 #define MALLOC_DECL_VOID(...) MOZ_MEMORY_API MACRO_CALL(GENERIC_MALLOC_DECL_VOID, (__VA_ARGS__))
 #define MALLOC_FUNCS MALLOC_FUNCS_MALLOC
 #include "malloc_decls.h"
 
 #define MALLOC_DECL(...) MOZ_JEMALLOC_API MACRO_CALL(GENERIC_MALLOC_DECL, (__VA_ARGS__))
 #define MALLOC_DECL_VOID(...) MOZ_JEMALLOC_API MACRO_CALL(GENERIC_MALLOC_DECL_VOID, (__VA_ARGS__))
 #define MALLOC_FUNCS MALLOC_FUNCS_JEMALLOC
@@ -5283,50 +5507,40 @@ void
 jemalloc_darwin_init(void)
 {
 	if (malloc_init_hard())
 		MOZ_CRASH();
 }
 
 #endif
 
-/*
- * is_malloc(malloc_impl) is some macro magic to detect if malloc_impl is
- * defined as "malloc" in mozmemory_wrap.h
- */
-#define malloc_is_malloc 1
-#define is_malloc_(a) malloc_is_ ## a
-#define is_malloc(a) is_malloc_(a)
-
-#if !defined(XP_DARWIN) && (is_malloc(malloc_impl) == 1)
-#  if defined(__GLIBC__) && !defined(__UCLIBC__)
+#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
  * ignored.
  */
 extern "C" {
 MOZ_EXPORT void (*__free_hook)(void*) = free_impl;
 MOZ_EXPORT void* (*__malloc_hook)(size_t) = malloc_impl;
 MOZ_EXPORT void* (*__realloc_hook)(void*, size_t) = realloc_impl;
 MOZ_EXPORT void* (*__memalign_hook)(size_t, size_t) = memalign_impl;
 }
 
-#  elif defined(RTLD_DEEPBIND)
+#elif defined(RTLD_DEEPBIND)
 /*
  * XXX On systems that support RTLD_GROUP or DF_1_GROUP, do their
  * implementations permit similar inconsistencies?  Should STV_SINGLETON
  * visibility be used for interposition where available?
  */
 #    error "Interposing malloc is unsafe on this system without libc malloc hooks."
-#  endif
 #endif
 
 #ifdef XP_WIN
 /*
  * In the new style jemalloc integration jemalloc is built as a separate
  * shared library.  Since we're no longer hooking into the CRT binary,
  * we need to initialize the heap at the first opportunity we get.
  * DLL_PROCESS_ATTACH in DllMain is that opportunity.
--- a/memory/mozjemalloc/mozjemalloc.h
+++ b/memory/mozjemalloc/mozjemalloc.h
@@ -16,8 +16,18 @@ struct Allocator: public T {
 #define MALLOC_DECL(name, return_type, ...) \
   static return_type name(__VA_ARGS__);
 #include "malloc_decls.h"
 };
 
 /* The MozJemalloc allocator */
 struct MozJemallocBase {};
 typedef Allocator<MozJemallocBase> MozJemalloc;
+
+#ifdef MOZ_REPLACE_MALLOC
+/* The replace-malloc allocator */
+struct ReplaceMallocBase {};
+typedef Allocator<ReplaceMallocBase> ReplaceMalloc;
+
+typedef ReplaceMalloc DefaultMalloc;
+#else
+typedef MozJemalloc DefaultMalloc;
+#endif
--- a/mozglue/build/mozglue.def.in
+++ b/mozglue/build/mozglue.def.in
@@ -2,35 +2,24 @@
 ; License, v. 2.0. If a copy of the MPL was not distributed with this
 ; file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 LIBRARY mozglue.dll
 
 EXPORTS
 #ifdef MOZ_MEMORY
   ; symbols that are actually useful
-#ifdef MOZ_REPLACE_MALLOC
-  malloc=malloc_impl
-  calloc=calloc_impl
-  realloc=realloc_impl
-  free=free_impl
-  posix_memalign=posix_memalign_impl
-  malloc_usable_size=malloc_usable_size_impl
-  malloc_good_size=malloc_good_size_impl
-  _aligned_free=free_impl
-#else
   malloc=je_malloc
   calloc=je_calloc
   realloc=je_realloc
   free=je_free
   posix_memalign=je_posix_memalign
   malloc_usable_size=je_malloc_usable_size
   malloc_good_size=je_malloc_good_size
   _aligned_free=je_free
-#endif
   _aligned_malloc
   strndup=wrap_strndup
   strdup=wrap_strdup
   _strdup=wrap_strdup
   wcsdup=wrap_wcsdup
   _wcsdup=wrap_wcsdup
   jemalloc_stats
   jemalloc_purge_freed_pages
--- a/toolkit/content/license.html
+++ b/toolkit/content/license.html
@@ -3888,18 +3888,18 @@ LIABILITY, WHETHER IN AN ACTION OF CONTR
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
 </pre>
 
     <hr>
 
     <h1><a id="jemalloc"></a>jemalloc License</h1>
 
-    <p>This license applies to files in the directories
-    <code>memory/mozjemalloc/</code> and
+    <p>This license applies to portions of the files in the directory
+    <code>memory/mozjemalloc/</code>.
     </p>
 
 <pre>
 Copyright (C) 2006-2008 Jason Evans &lt;jasone@canonware.com&gt;.
 All rights reserved.
 Copyright (C) 2007-2017 Mozilla Foundation.
 
 Redistribution and use in source and binary forms, with or without