Bug 804303 part 1 - Cleanup how the mozjemalloc/jemalloc3 glue is set up, attempting to make it clearer. r=jlebar,r=khuey
authorMike Hommey <mh+mozilla@glandium.org>
Fri, 07 Dec 2012 09:32:24 +0100
changeset 125191 af6ca1b6b58a4f61fe0e9436d56a52d007f71013
parent 125190 e6f7e0e1257b998a30fb0f7f4354df82ea75521b
child 125192 201c9e6f8f18ea164f8c48e7985dfb6fa88e9ba7
push id297
push userlsblakk@mozilla.com
push dateTue, 26 Mar 2013 17:28:00 +0000
treeherdermozilla-release@64d7b45c34e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjlebar, khuey
bugs804303
milestone20.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 804303 part 1 - Cleanup how the mozjemalloc/jemalloc3 glue is set up, attempting to make it clearer. r=jlebar,r=khuey
Makefile.in
allmakefiles.sh
config/system-headers
configure.in
js/src/config/system-headers
memory/Makefile.in
memory/build/Makefile.in
memory/build/extraMallocFuncs.c
memory/build/jemalloc_config.c
memory/build/malloc_decls.h
memory/build/mozjemalloc_compat.c
memory/build/mozmemory.h
memory/build/mozmemory_wrap.c
memory/build/mozmemory_wrap.h
memory/mozjemalloc/Makefile.in
memory/mozjemalloc/jemalloc.c
memory/mozjemalloc/jemalloc.h
mozglue/build/mozglue.def.in
storage/src/mozStorageService.cpp
xpcom/base/AvailableMemoryTracker.cpp
xpcom/base/nsMemoryReporterManager.cpp
xpcom/tests/TestJemalloc.cpp
--- a/Makefile.in
+++ b/Makefile.in
@@ -41,23 +41,17 @@ tier_base_dirs += \
 endif
 ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
 tier_base_dirs += \
   other-licenses/android \
   $(NULL)
 endif
 
 ifdef MOZ_MEMORY
-tier_base_dirs += memory/mozjemalloc
-ifdef MOZ_JEMALLOC
-ifndef MOZ_NATIVE_JEMALLOC
-tier_base_dirs += memory/jemalloc
-endif
-endif
-tier_base_dirs += memory/build
+tier_base_dirs += memory
 endif
 ifndef MOZ_NATIVE_ZLIB
 tier_base_dirs += modules/zlib
 endif
 tier_base_dirs += \
   mozglue \
   memory/mozalloc \
   $(NULL)
--- a/allmakefiles.sh
+++ b/allmakefiles.sh
@@ -54,23 +54,24 @@ if [ ! "$LIBXUL_SDK" ]; then
       build/stlport/stl/config/_android.h
     "
   fi
   add_makefiles "
     memory/mozalloc/Makefile
     mozglue/Makefile
     mozglue/build/Makefile
   "
-  if [ "$MOZ_JEMALLOC" -a -z "$MOZ_NATIVE_JEMALLOC" ]; then
+  if [ "$MOZ_JEMALLOC3" -a -z "$MOZ_NATIVE_JEMALLOC" ]; then
     add_makefiles "
       memory/jemalloc/Makefile
     "
   fi
   if [ "$MOZ_MEMORY" ]; then
     add_makefiles "
+      memory/Makefile
       memory/mozjemalloc/Makefile
       memory/build/Makefile
     "
   fi
   if [ "$MOZ_WIDGET_TOOLKIT" = "android" ]; then
     add_makefiles "
       other-licenses/android/Makefile
       other-licenses/skia-npapi/Makefile
--- a/config/system-headers
+++ b/config/system-headers
@@ -468,17 +468,16 @@ IOKit/IOMessage.h
 IOKit/pwr_mgt/IOPMLib.h
 iomanip
 iostream
 iostream.h
 iterator
 JavaControl.h
 JavaEmbedding/JavaControl.h
 JavaVM/jni.h
-jemalloc.h
 JManager.h
 JNIEnvTests.h
 jni.h
 #if MOZ_NATIVE_JPEG==1
 jpeglib.h
 #endif
 JVMManagerTests.h
 Kerberos/Kerberos.h
--- a/configure.in
+++ b/configure.in
@@ -7035,25 +7035,25 @@ else
     MOZ_GLUE_PROGRAM_LDFLAGS="$MOZ_GLUE_PROGRAM_LDFLAGS -rdynamic"
   fi
   if test "$MOZ_LINKER" = 1; then
     MOZ_GLUE_PROGRAM_LDFLAGS="$MOZ_GLUE_PROGRAM_LDFLAGS $ZLIB_LIBS"
   fi
 fi
 
 if test -z "$MOZ_MEMORY"; then
-  if test -n "$MOZ_JEMALLOC"; then
+  if test -n "$MOZ_JEMALLOC3"; then
     MOZ_NATIVE_JEMALLOC=1
     AC_CHECK_FUNCS(mallctl nallocm,,
       [MOZ_NATIVE_JEMALLOC=
        break])
     if test -n "$MOZ_NATIVE_JEMALLOC"; then
       MOZ_MEMORY=1
       AC_DEFINE(MOZ_MEMORY)
-      AC_DEFINE(MOZ_JEMALLOC)
+      AC_DEFINE(MOZ_JEMALLOC3)
       AC_DEFINE(MOZ_NATIVE_JEMALLOC)
     fi
   fi
   case "${target}" in
     *-mingw*)
       if test -z "$WIN32_REDIST_DIR" -a -z "$MOZ_DEBUG"; then
         AC_MSG_WARN([When not building jemalloc, you need to set WIN32_REDIST_DIR to the path to the Visual C++ Redist (usually VCINSTALLDIR\redist\x86\Microsoft.VC80.CRT, for VC++ v8) if you intend to distribute your build.])
       fi
@@ -7078,18 +7078,18 @@ else
       ;;
     *)
       AC_MSG_ERROR([Unexpected pointer size])
       ;;
     esac
   fi
 
   AC_DEFINE(MOZ_MEMORY)
-  if test -n "$MOZ_JEMALLOC"; then
-    AC_DEFINE(MOZ_JEMALLOC)
+  if test -n "$MOZ_JEMALLOC3"; then
+    AC_DEFINE(MOZ_JEMALLOC3)
   fi
   if test "x$MOZ_DEBUG" = "x1"; then
     AC_DEFINE(MOZ_MEMORY_DEBUG)
   fi
   dnl The generic feature tests that determine how to compute ncpus are long and
   dnl complicated.  Therefore, simply define special cpp variables for the
   dnl platforms we have special knowledge of.
   case "${target}" in
@@ -7140,17 +7140,17 @@ else
     export DLLFLAGS
     ;;
   *)
     AC_MSG_ERROR([--enable-jemalloc not supported on ${target}])
     ;;
   esac
 fi # MOZ_MEMORY
 AC_SUBST(MOZ_MEMORY)
-AC_SUBST(MOZ_JEMALLOC)
+AC_SUBST(MOZ_JEMALLOC3)
 AC_SUBST(MOZ_NATIVE_JEMALLOC)
 AC_SUBST(MOZ_GLUE_LDFLAGS)
 AC_SUBST(MOZ_GLUE_PROGRAM_LDFLAGS)
 AC_SUBST(WIN32_CRT_LIBS)
 dnl Need to set this for make because NSS doesn't have configure
 AC_SUBST(DLLFLAGS)
 
 dnl We need to wrap dlopen and related functions on Android because we use
@@ -8989,29 +8989,28 @@ MOZ_PER_WINDOW_PRIVATE_BROWSING=${MOZ_PE
 if cmp -s ./mozinfo.json.tmp ./mozinfo.json; then
   rm ./mozinfo.json.tmp
 else
   mv -f ./mozinfo.json.tmp ./mozinfo.json
 fi
 
 # Run jemalloc configure script
 
-if test -z "$MOZ_NATIVE_JEMALLOC" -a "$MOZ_JEMALLOC" -a "$MOZ_MEMORY" ; then
+if test -z "$MOZ_NATIVE_JEMALLOC" -a "$MOZ_JEMALLOC3" -a "$MOZ_MEMORY" ; then
   ac_configure_args="$_SUBDIR_CONFIG_ARGS --build=$build --host=$target --enable-stats --with-jemalloc-prefix=je_"
+  case "${OS_ARCH}" in
+    WINNT|Darwin)
+      # We want jemalloc functions to be kept hidden on both Mac and Windows
+      # See memory/build/mozmemory_wrap.h for details.
+      ac_configure_args="$ac_configure_args --without-export"
+      ;;
+  esac
   case "$OS_ARCH" in
     Linux|DragonFly|FreeBSD|NetBSD|OpenBSD)
-      MANGLE="malloc calloc valloc free realloc posix_memalign"
-      case "$OS_ARCH" in
-        Linux)
-          MANGLE="$MANGLE memalign malloc_usable_size"
-          ;;
-        FreeBSD)
-          MANGLE="$MANGLE malloc_usable_size"
-          ;;
-      esac
+      MANGLE="malloc posix_memalign aligned_alloc calloc realloc free memalign valloc malloc_usable_size"
       ;;
   esac
   if test -n "$MANGLE"; then
     MANGLED=
     JEMALLOC_WRAPPER=
     if test -n "$_WRAP_MALLOC"; then
       JEMALLOC_WRAPPER=__wrap_
     fi
--- a/js/src/config/system-headers
+++ b/js/src/config/system-headers
@@ -468,17 +468,16 @@ IOKit/IOMessage.h
 IOKit/pwr_mgt/IOPMLib.h
 iomanip
 iostream
 iostream.h
 iterator
 JavaControl.h
 JavaEmbedding/JavaControl.h
 JavaVM/jni.h
-jemalloc.h
 JManager.h
 JNIEnvTests.h
 jni.h
 #if MOZ_NATIVE_JPEG==1
 jpeglib.h
 #endif
 JVMManagerTests.h
 Kerberos/Kerberos.h
new file mode 100644
--- /dev/null
+++ b/memory/Makefile.in
@@ -0,0 +1,22 @@
+# 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/.
+
+DEPTH           = @DEPTH@
+topsrcdir       = @top_srcdir@
+srcdir          = @srcdir@
+VPATH           = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+DIRS += mozjemalloc
+
+ifdef MOZ_JEMALLOC3
+ifndef MOZ_NATIVE_JEMALLOC
+DIRS += jemalloc
+endif
+endif
+
+DIRS += build
+
+include $(topsrcdir)/config/rules.mk
--- a/memory/build/Makefile.in
+++ b/memory/build/Makefile.in
@@ -13,20 +13,35 @@ MODULE = memory
 LIBRARY_NAME = memory
 FORCE_STATIC_LIB = 1
 STLFLAGS =
 ifdef MOZ_GLUE_PROGRAM_LDFLAGS
 SDK_LIBRARY = $(REAL_LIBRARY)
 DIST_INSTALL = 1
 endif
 
-CSRCS = extraMallocFuncs.c
+DEFINES += -DMOZ_MEMORY_IMPL
+
+CSRCS = \
+  mozmemory_wrap.c \
+  jemalloc_config.c \
+  $(NULL)
 
-ifdef MOZ_JEMALLOC
+EXPORTS = \
+  mozmemory.h \
+  mozmemory_wrap.h \
+  $(NULL)
+
+ifdef MOZ_JEMALLOC3
 CSRCS += mozjemalloc_compat.c
+LOCAL_INCLUDES += -I../jemalloc/src/include
+ifdef _MSC_VER
+LOCAL_INCLUDES += -I$(topsrcdir)/memory/jemalloc/src/include/msvc_compat
+endif
+
 ifndef MOZ_NATIVE_JEMALLOC
 SHARED_LIBRARY_LIBS += $(call EXPAND_LIBNAME_PATH,jemalloc,$(DEPTH)/memory/jemalloc)
 endif
 else
 SHARED_LIBRARY_LIBS += $(call EXPAND_LIBNAME_PATH,jemalloc,$(DEPTH)/memory/mozjemalloc)
 endif
 
 include $(topsrcdir)/config/rules.mk
rename from memory/build/extraMallocFuncs.c
rename to memory/build/jemalloc_config.c
--- a/memory/build/extraMallocFuncs.c
+++ b/memory/build/jemalloc_config.c
@@ -1,149 +1,32 @@
 /* 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/. */
 
-#include <string.h>
+#ifdef MOZ_JEMALLOC3
+
+#include "mozmemory_wrap.h"
 #include "mozilla/Types.h"
 
-#ifdef MOZ_WIDGET_ANDROID
-#define wrap(a) __wrap_ ## a
-#elif defined(XP_WIN) || defined(XP_MACOSX)
-#define wrap(a) je_ ## a
-#elif defined(MOZ_WIDGET_GONK)
-#define wrap(a) a
-#endif
-
-#ifdef wrap
-void *wrap(malloc)(size_t);
-void wrap(free)(void *);
-#endif
-
-#ifdef ANDROID
-/* operator new(unsigned int) */
-MOZ_EXPORT void *
-wrap(_Znwj)(unsigned int size)
-{
-  return wrap(malloc)(size);
-}
-/* operator new[](unsigned int) */
-MOZ_EXPORT void *
-wrap(_Znaj)(unsigned int size)
-{
-  return wrap(malloc)(size);
-}
-/* operator delete(void*) */
-MOZ_EXPORT void
-wrap(_ZdlPv)(void *ptr)
-{
-  wrap(free)(ptr);
-}
-/* operator delete[](void*) */
-MOZ_EXPORT void
-wrap(_ZdaPv)(void *ptr)
-{
-  wrap(free)(ptr);
-}
-/*operator new(unsigned int, std::nothrow_t const&)*/
-MOZ_EXPORT void *
-wrap(_ZnwjRKSt9nothrow_t)(unsigned int size)
-{
-  return wrap(malloc)(size);
-}
-/*operator new[](unsigned int, std::nothrow_t const&)*/
-MOZ_EXPORT void *
-wrap(_ZnajRKSt9nothrow_t)(unsigned int size)
-{
-  return wrap(malloc)(size);
-}
-/* operator delete(void*, std::nothrow_t const&) */
-MOZ_EXPORT void
-wrap(_ZdlPvRKSt9nothrow_t)(void *ptr)
-{
-  wrap(free)(ptr);
-}
-/* operator delete[](void*, std::nothrow_t const&) */
-MOZ_EXPORT void
-wrap(_ZdaPvRKSt9nothrow_t)(void *ptr)
-{
-  wrap(free)(ptr);
-}
-#endif
-
-#ifdef wrap
-MOZ_EXPORT char *
-wrap(strndup)(const char *src, size_t len)
-{
-  char* dst = (char*) wrap(malloc)(len + 1);
-  if (dst)
-    strncpy(dst, src, len + 1);
-  return dst; 
-}
-
-MOZ_EXPORT char *
-wrap(strdup)(const char *src)
-{
-  size_t len = strlen(src);
-  return wrap(strndup)(src, len);
-}
-
-#ifdef XP_WIN
-/*
- *  There's a fun allocator mismatch in (at least) the VS 2010 CRT
- *  (see the giant comment in this directory's Makefile.in
- *  that gets redirected here to avoid a crash on shutdown.
- */
-void
-wrap(dumb_free_thunk)(void *ptr)
-{
-  return; /* shutdown leaks that we don't care about */
-}
-
-#include <wchar.h>
-
-/*
- *  We also need to provide our own impl of wcsdup so that we don't ask
- *  the CRT for memory from its heap (which will then be unfreeable).
- */
-wchar_t *
-wrap(wcsdup)(const wchar_t *src)
-{
-  size_t len = wcslen(src);
-  wchar_t *dst = (wchar_t*) wrap(malloc)((len + 1) * sizeof(wchar_t));
-  if (dst)
-    wcsncpy(dst, src, len + 1);
-  return dst;
-}
-#endif /* XP_WIN */
-
-#endif
-
-#ifdef MOZ_JEMALLOC
-
-#undef wrap
-#if defined(MOZ_NATIVE_JEMALLOC)
-#define wrap(a) a
-#else
-#define wrap(a) je_ ## a
-#endif
-
 /* Override some jemalloc defaults */
-MOZ_EXPORT const char * wrap(malloc_conf) = "narenas:1,lg_chunk:20";
+MFBT_DATA const char * je_(malloc_conf) = "narenas:1,lg_chunk:20";
 
 #ifdef ANDROID
 #include <android/log.h>
 
 static void
 _je_malloc_message(void *cbopaque, const char *s)
 {
   __android_log_print(ANDROID_LOG_INFO, "GeckoJemalloc", "%s", s);
 }
 
-void (*je_malloc_message)(void *, const char *s) = _je_malloc_message;
+void (*je_(malloc_message))(void *, const char *s) = _je_malloc_message;
 #endif
-#endif /* MOZ_JEMALLOC */
 
+#endif /* MOZ_JEMALLOC3 */
+
+/* Provide an abort function for use in jemalloc code */
 #include <mozilla/Assertions.h>
 
 void moz_abort() {
   MOZ_CRASH();
 }
new file mode 100644
--- /dev/null
+++ b/memory/build/malloc_decls.h
@@ -0,0 +1,36 @@
+/* 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/. */
+
+/*
+ * Helper header to declare all the supported malloc functions.
+ * MALLOC_DECL arguments are:
+ *   - function name
+ *   - return type
+ *   - argument types
+ */
+
+#ifndef malloc_decls_h
+#  define malloc_decls_h
+
+#  ifdef __linux__
+typedef void * usable_ptr_t;
+#  else
+typedef const void * usable_ptr_t;
+#  endif
+#endif /* malloc_decls_h */
+
+#ifdef MALLOC_DECL
+MALLOC_DECL(malloc, void *, size_t)
+MALLOC_DECL(posix_memalign, int, void **, size_t, size_t)
+MALLOC_DECL(aligned_alloc, void *, size_t, size_t)
+MALLOC_DECL(calloc, void *, size_t, size_t)
+MALLOC_DECL(realloc, void *, void *, size_t)
+MALLOC_DECL(free, void, void *)
+MALLOC_DECL(memalign, void *, size_t, size_t)
+MALLOC_DECL(valloc, void *, size_t)
+MALLOC_DECL(malloc_usable_size, size_t, usable_ptr_t)
+MALLOC_DECL(malloc_good_size, size_t, size_t)
+#endif /* MALLOC_DECL */
+
+#undef MALLOC_DECL
--- a/memory/build/mozjemalloc_compat.c
+++ b/memory/build/mozjemalloc_compat.c
@@ -1,50 +1,71 @@
 /* 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_JEMALLOC3
+#  error Should only compile this file when building with jemalloc 3
+#endif
+
+#include "mozmemory_wrap.h"
+#include "jemalloc_types.h"
 #include "mozilla/Types.h"
-#include "jemalloc_types.h"
 
 #if defined(MOZ_NATIVE_JEMALLOC)
-#define wrap(a) a
+
+MOZ_IMPORT_API int
+je_(mallctl)(const char*, void*, size_t*, void*, size_t);
+MOZ_IMPORT_API int
+je_(mallctlnametomib)(const char *name, size_t *mibp, size_t *miblenp);
+MOZ_IMPORT_API int
+je_(mallctlbymib)(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen);
+MOZ_IMPORT_API int
+je_(nallocm)(size_t *rsize, size_t size, int flags);
+
 #else
-#define wrap(a) je_ ## a
+#  include "jemalloc/jemalloc.h"
 #endif
 
 /*
  *  CTL_* macros are from memory/jemalloc/src/src/stats.c with changes:
  *  - drop `t' argument to avoid redundancy in calculating type size
  *  - require `i' argument for arena number explicitly
  */
 
 #define	CTL_GET(n, v) do {						\
 	size_t sz = sizeof(v);						\
-	wrap(mallctl)(n, &v, &sz, NULL, 0);				\
+	je_(mallctl)(n, &v, &sz, NULL, 0);				\
 } while (0)
 
 #define	CTL_I_GET(n, v, i) do {						\
 	size_t mib[6];							\
 	size_t miblen = sizeof(mib) / sizeof(mib[0]);			\
 	size_t sz = sizeof(v);						\
-	wrap(mallctlnametomib)(n, mib, &miblen);			\
+	je_(mallctlnametomib)(n, mib, &miblen);			\
 	mib[2] = i;							\
-	wrap(mallctlbymib)(mib, miblen, &v, &sz, NULL, 0);		\
+	je_(mallctlbymib)(mib, miblen, &v, &sz, NULL, 0);		\
 } while (0)
 
-MOZ_IMPORT_API int
-wrap(mallctl)(const char*, void*, size_t*, void*, size_t);
-MOZ_IMPORT_API int
-wrap(mallctlnametomib)(const char *name, size_t *mibp, size_t *miblenp);
-MOZ_IMPORT_API int
-wrap(mallctlbymib)(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen);
+MOZ_MEMORY_API size_t
+malloc_good_size_impl(size_t size)
+{
+  size_t ret;
+  /* je_nallocm crashes when given a size of 0. As
+   * malloc_usable_size(malloc(0)) and malloc_usable_size(malloc(1))
+   * return the same value, use a size of 1. */
+  if (size == 0)
+    size = 1;
+  if (!je_(nallocm)(&ret, size, 0))
+    return ret;
+  return size;
+}
 
-MOZ_EXPORT void
-jemalloc_stats(jemalloc_stats_t *stats)
+MOZ_JEMALLOC_API void
+jemalloc_stats_impl(jemalloc_stats_t *stats)
 {
   unsigned narenas;
   size_t active, allocated, mapped, page, pdirty;
 
   CTL_GET("arenas.narenas", narenas);
   CTL_GET("arenas.page", page);
   CTL_GET("stats.active", active);
   CTL_GET("stats.allocated", allocated);
@@ -53,8 +74,19 @@ jemalloc_stats(jemalloc_stats_t *stats)
   /* get the summation for all arenas, i == narenas */
   CTL_I_GET("stats.arenas.0.pdirty", pdirty, narenas);
 
   stats->allocated = allocated;
   stats->mapped = mapped;
   stats->dirty = pdirty * page;
   stats->committed = active + stats->dirty;
 }
+
+MOZ_JEMALLOC_API void
+jemalloc_purge_freed_pages_impl()
+{
+}
+
+MOZ_JEMALLOC_API void
+jemalloc_free_dirty_pages_impl()
+{
+  je_(mallctl)("arenas.purge", NULL, 0, NULL, 0);
+}
rename from memory/mozjemalloc/jemalloc.h
rename to memory/build/mozmemory.h
--- a/memory/mozjemalloc/jemalloc.h
+++ b/memory/build/mozmemory.h
@@ -1,94 +1,60 @@
-/* -*- Mode: C; tab-width: 8; c-basic-offset: 8 -*- */
-/* vim:set softtabstop=8 shiftwidth=8: */
-/*-
- * Copyright (C) 2006-2008 Jason Evans <jasone@FreeBSD.org>.
- * All rights reserved.
- *
- * 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.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice(s), this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+/* 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 mozmemory_h
+#define mozmemory_h
+
+/*
+ * This header is meant to be used when the following functions are
+ * necessary:
+ *   - malloc_good_size (used to be called je_malloc_usable_in_advance)
+ *   - jemalloc_stats
+ *   - jemalloc_purge_freed_pages
+ *   - jemalloc_free_dirty_pages
  */
 
-#ifndef _JEMALLOC_H_
-#define _JEMALLOC_H_
+#ifndef MOZ_MEMORY
+#  error Should not include mozmemory.h when MOZ_MEMORY is not set
+#endif
 
-#if defined(MOZ_MEMORY_DARWIN)
-#include <malloc/malloc.h>
-#endif
+#include "mozmemory_wrap.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/Types.h"
 #include "jemalloc_types.h"
 
-#if defined(MOZ_NATIVE_JEMALLOC)
-#define wrap(a) a
+MOZ_BEGIN_EXTERN_C
+
+/*
+ * On OSX, malloc/malloc.h contains the declaration for malloc_good_size,
+ * which will call back in jemalloc, through the zone allocator so just use it.
+ */
+#ifdef XP_DARWIN
+#  include <malloc/malloc.h>
 #else
-#define wrap(a) je_ ## a
-#endif
+MOZ_MEMORY_API size_t malloc_good_size_impl(size_t size);
+
+/* Note: the MOZ_GLUE_IN_PROGRAM ifdef below is there to avoid -Werror turning
+ * the protective if into errors. MOZ_GLUE_IN_PROGRAM is what triggers MFBT_API
+ * to use weak imports. */
 
-#ifdef __cplusplus
-extern "C" {
+static MOZ_INLINE size_t _malloc_good_size(size_t size) {
+#  if defined(MOZ_GLUE_IN_PROGRAM) && !defined(IMPL_MFBT)
+  if (!malloc_good_size)
+    return size;
+#  endif
+  return malloc_good_size_impl(size);
+}
+
+#  define malloc_good_size _malloc_good_size
 #endif
 
-#if defined(MOZ_NATIVE_JEMALLOC) \
-  || defined(MOZ_MEMORY_LINUX) || defined(MOZ_MEMORY_BSD)
-__attribute__((weak))
-#endif
-void	jemalloc_stats(jemalloc_stats_t *stats);
-
-/* Computes the usable size in advance. */
-#if !defined(MOZ_MEMORY_DARWIN)
-#if defined(MOZ_MEMORY_LINUX) || defined(MOZ_MEMORY_BSD)
-__attribute__((weak))
-#endif
-#if defined(MOZ_JEMALLOC)
-MOZ_IMPORT_API int wrap(nallocm)(size_t *rsize, size_t size, int flags);
-#else
-size_t je_malloc_good_size(size_t size);
-#endif
-#endif
-
-static inline size_t je_malloc_usable_size_in_advance(size_t size) {
-#if defined(MOZ_MEMORY_DARWIN)
-  return malloc_good_size(size);
-#elif defined(MOZ_JEMALLOC)
-  if (wrap(nallocm)) {
-    size_t ret;
-    if (size == 0)
-      size = 1;
-    if (!wrap(nallocm)(&ret, size, 0))
-      return ret;
-  }
-  return size;
-#else
-  if (je_malloc_good_size)
-    return je_malloc_good_size(size);
-  else
-    return size;
-#endif
-}
+MOZ_JEMALLOC_API void jemalloc_stats(jemalloc_stats_t *stats);
 
 /*
  * On some operating systems (Mac), we use madvise(MADV_FREE) to hand pages
  * back to the operating system.  On Mac, the operating system doesn't take
  * this memory back immediately; instead, the OS takes it back only when the
  * machine is running out of physical memory.
  *
  * This is great from the standpoint of efficiency, but it makes measuring our
@@ -105,35 +71,21 @@ static inline size_t je_malloc_usable_si
  *
  * This function is also expensive in that the next time we go to access a page
  * which we've just explicitly decommitted, the operating system has to attach
  * to it a physical page!  If we hadn't run this function, the OS would have
  * less work to do.
  *
  * If MALLOC_DOUBLE_PURGE is not defined, this function does nothing.
  */
-#if defined(MOZ_MEMORY_LINUX) || defined(MOZ_JEMALLOC)
-static inline void jemalloc_purge_freed_pages() { }
-#else
-void    jemalloc_purge_freed_pages();
-#endif
+MOZ_JEMALLOC_API void jemalloc_purge_freed_pages();
 
 /*
  * Free all unused dirty pages in all arenas. Calling this function will slow
  * down subsequent allocations so it is recommended to use it only when
  * memory needs to be reclaimed at all costs (see bug 805855). This function
  * provides functionality similar to mallctl("arenas.purge") in jemalloc 3.
  */
-
-#if !defined(MOZ_NATIVE_JEMALLOC)
-#if defined(MOZ_MEMORY_LINUX) || defined(MOZ_MEMORY_BSD)
-__attribute__((weak))
-#endif /* defined(MOZ_MEMORY_LINUX) || defined(MOZ_MEMORY_BSD) */
-void    jemalloc_free_dirty_pages();
-#endif /* !defined(MOZ_NATIVE_JEMALLOC) */
+MOZ_JEMALLOC_API void jemalloc_free_dirty_pages();
 
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
+MOZ_END_EXTERN_C
 
-#undef wrap
-
-#endif /* _JEMALLOC_H_ */
+#endif /* mozmemory_h */
copy from memory/build/extraMallocFuncs.c
copy to memory/build/mozmemory_wrap.c
--- a/memory/build/extraMallocFuncs.c
+++ b/memory/build/mozmemory_wrap.c
@@ -1,149 +1,116 @@
 /* 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/. */
 
 #include <string.h>
+#include "mozmemory_wrap.h"
 #include "mozilla/Types.h"
 
-#ifdef MOZ_WIDGET_ANDROID
-#define wrap(a) __wrap_ ## a
-#elif defined(XP_WIN) || defined(XP_MACOSX)
-#define wrap(a) je_ ## a
-#elif defined(MOZ_WIDGET_GONK)
-#define wrap(a) a
-#endif
+/* Declare malloc implementation functions with the right return and
+ * argument types. */
+#define MALLOC_DECL(name, return_type, ...) \
+  MOZ_MEMORY_API return_type name ## _impl(__VA_ARGS__);
+#include "malloc_decls.h"
 
-#ifdef wrap
-void *wrap(malloc)(size_t);
-void wrap(free)(void *);
-#endif
-
-#ifdef ANDROID
+#ifdef MOZ_WRAP_NEW_DELETE
 /* operator new(unsigned int) */
-MOZ_EXPORT void *
-wrap(_Znwj)(unsigned int size)
+MOZ_MEMORY_API void *
+mozmem_malloc_impl(_Znwj)(unsigned int size)
 {
-  return wrap(malloc)(size);
+  return malloc_impl(size);
 }
 /* operator new[](unsigned int) */
-MOZ_EXPORT void *
-wrap(_Znaj)(unsigned int size)
+MOZ_MEMORY_API void *
+mozmem_malloc_impl(_Znaj)(unsigned int size)
 {
-  return wrap(malloc)(size);
+  return malloc_impl(size);
 }
 /* operator delete(void*) */
-MOZ_EXPORT void
-wrap(_ZdlPv)(void *ptr)
+MOZ_MEMORY_API void
+mozmem_malloc_impl(_ZdlPv)(void *ptr)
 {
-  wrap(free)(ptr);
+  free_impl(ptr);
 }
 /* operator delete[](void*) */
-MOZ_EXPORT void
-wrap(_ZdaPv)(void *ptr)
+MOZ_MEMORY_API void
+mozmem_malloc_impl(_ZdaPv)(void *ptr)
 {
-  wrap(free)(ptr);
+  free_impl(ptr);
 }
 /*operator new(unsigned int, std::nothrow_t const&)*/
-MOZ_EXPORT void *
-wrap(_ZnwjRKSt9nothrow_t)(unsigned int size)
+MOZ_MEMORY_API void *
+mozmem_malloc_impl(_ZnwjRKSt9nothrow_t)(unsigned int size)
 {
-  return wrap(malloc)(size);
+  return malloc_impl(size);
 }
 /*operator new[](unsigned int, std::nothrow_t const&)*/
-MOZ_EXPORT void *
-wrap(_ZnajRKSt9nothrow_t)(unsigned int size)
+MOZ_MEMORY_API void *
+mozmem_malloc_impl(_ZnajRKSt9nothrow_t)(unsigned int size)
 {
-  return wrap(malloc)(size);
+  return malloc_impl(size);
 }
 /* operator delete(void*, std::nothrow_t const&) */
-MOZ_EXPORT void
-wrap(_ZdlPvRKSt9nothrow_t)(void *ptr)
+MOZ_MEMORY_API void
+mozmem_malloc_impl(_ZdlPvRKSt9nothrow_t)(void *ptr)
 {
-  wrap(free)(ptr);
+  free_impl(ptr);
 }
 /* operator delete[](void*, std::nothrow_t const&) */
-MOZ_EXPORT void
-wrap(_ZdaPvRKSt9nothrow_t)(void *ptr)
+MOZ_MEMORY_API void
+mozmem_malloc_impl(_ZdaPvRKSt9nothrow_t)(void *ptr)
 {
-  wrap(free)(ptr);
+  free_impl(ptr);
 }
 #endif
 
-#ifdef wrap
-MOZ_EXPORT char *
-wrap(strndup)(const char *src, size_t len)
+/* strndup and strdup may be defined as macros in string.h, which would
+ * clash with the definitions below. */
+#undef strndup
+#undef strdup
+
+#ifndef XP_DARWIN
+MOZ_MEMORY_API char *
+strndup_impl(const char *src, size_t len)
 {
-  char* dst = (char*) wrap(malloc)(len + 1);
+  char* dst = (char*) malloc_impl(len + 1);
   if (dst)
     strncpy(dst, src, len + 1);
-  return dst; 
+  return dst;
 }
 
-MOZ_EXPORT char *
-wrap(strdup)(const char *src)
+MOZ_MEMORY_API char *
+strdup_impl(const char *src)
 {
   size_t len = strlen(src);
-  return wrap(strndup)(src, len);
+  return strndup_impl(src, len);
 }
+#endif /* XP_DARWIN */
 
 #ifdef XP_WIN
 /*
  *  There's a fun allocator mismatch in (at least) the VS 2010 CRT
- *  (see the giant comment in this directory's Makefile.in
+ *  (see the giant comment in $(topsrcdir)/mozglue/build/Makefile.in)
  *  that gets redirected here to avoid a crash on shutdown.
  */
 void
-wrap(dumb_free_thunk)(void *ptr)
+dumb_free_thunk(void *ptr)
 {
   return; /* shutdown leaks that we don't care about */
 }
 
 #include <wchar.h>
 
 /*
  *  We also need to provide our own impl of wcsdup so that we don't ask
  *  the CRT for memory from its heap (which will then be unfreeable).
  */
 wchar_t *
-wrap(wcsdup)(const wchar_t *src)
+wcsdup_impl(const wchar_t *src)
 {
   size_t len = wcslen(src);
-  wchar_t *dst = (wchar_t*) wrap(malloc)((len + 1) * sizeof(wchar_t));
+  wchar_t *dst = (wchar_t*) malloc_impl((len + 1) * sizeof(wchar_t));
   if (dst)
     wcsncpy(dst, src, len + 1);
   return dst;
 }
 #endif /* XP_WIN */
-
-#endif
-
-#ifdef MOZ_JEMALLOC
-
-#undef wrap
-#if defined(MOZ_NATIVE_JEMALLOC)
-#define wrap(a) a
-#else
-#define wrap(a) je_ ## a
-#endif
-
-/* Override some jemalloc defaults */
-MOZ_EXPORT const char * wrap(malloc_conf) = "narenas:1,lg_chunk:20";
-
-#ifdef ANDROID
-#include <android/log.h>
-
-static void
-_je_malloc_message(void *cbopaque, const char *s)
-{
-  __android_log_print(ANDROID_LOG_INFO, "GeckoJemalloc", "%s", s);
-}
-
-void (*je_malloc_message)(void *, const char *s) = _je_malloc_message;
-#endif
-#endif /* MOZ_JEMALLOC */
-
-#include <mozilla/Assertions.h>
-
-void moz_abort() {
-  MOZ_CRASH();
-}
new file mode 100644
--- /dev/null
+++ b/memory/build/mozmemory_wrap.h
@@ -0,0 +1,186 @@
+/* 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 mozmemory_wrap_h
+#define mozmemory_wrap_h
+
+/*
+ * This header contains #defines which tweak the names of various memory
+ * allocation functions.
+ *
+ * There are several types of functions related to memory allocation
+ * that are meant to be used publicly by the Gecko codebase:
+ *
+ * - malloc implementation functions:
+ *   - malloc
+ *   - posix_memalign
+ *   - aligned_alloc
+ *   - calloc
+ *   - realloc
+ *   - free
+ *   - memalign
+ *   - valloc
+ *   - malloc_usable_size
+ *   - malloc_good_size
+ *   Some of these functions are specific to some systems, but for
+ *   convenience, they are treated as being cross-platform, and available
+ *   as such.
+ *
+ * - duplication functions:
+ *   - strndup
+ *   - strdup
+ *   - wcsdup (Windows only)
+ *
+ * - jemalloc specific functions:
+ *   - jemalloc_stats
+ *   - jemalloc_purge_freed_pages
+ *   - jemalloc_free_dirty_pages
+ *   (these functions are native to mozjemalloc, and have compatibility
+ *   implementations for jemalloc3)
+ *
+ * These functions are all exported as part of libmozglue (see
+ * $(topsrcdir)/mozglue/build/Makefile.in), with a few implementation
+ * peculiarities:
+ *
+ * - On Windows, the malloc implementation functions are all prefixed with
+ *   "je_", the duplication functions are prefixed with "wrap_", and jemalloc
+ *   specific functions are left unprefixed. All these functions are however
+ *   aliased when exporting them, such that the resulting mozglue.dll exports
+ *   them unprefixed (see $(topsrcdir)/mozglue/build/mozglue.def.in). The
+ *   prefixed malloc implementation and duplication functions are not
+ *   exported.
+ *
+ * - On MacOSX, the system libc has a zone allocator, which allows us to
+ *   hook custom malloc implementation functions without exporting them.
+ *   The malloc implementation functions are all prefixed with "je_" and used
+ *   this way from the custom zone allocator. They are not exported.
+ *   Duplication functions are not included, since they will call the custom
+ *   zone allocator anyways. Jemalloc-specific functions are also left
+ *   unprefixed.
+ *
+ * - On Android, both malloc implementation and duplication functions are
+ *   prefixed with "__wrap_". Additionally, C++ allocation functions
+ *   (operator new/delete) are also exported and prefixed with "__wrap_".
+ *   Jemalloc specific functions are left unprefixed.
+ *
+ * - On Gonk, all functions are left unprefixed. Additionally, C++ allocation
+ *   functions (operator new/delete) are also exported and unprefixed.
+ *
+ * - On other systems (mostly Linux), all functions are left unprefixed.
+ *
+ * Only Android and Gonk add C++ allocation functions.
+ *
+ * Proper exporting of the various functions is done with the MOZ_MEMORY_API
+ * and MOZ_JEMALLOC_API macros. MOZ_MEMORY_API is meant to be used for malloc
+ * implementation and duplication functions, while MOZ_JEMALLOC_API is
+ * dedicated to jemalloc specific functions.
+ *
+ *
+ * All these functions are meant to be called with no prefix from Gecko code.
+ * In most cases, this is because that's how they are available at runtime.
+ * However, on Android, "__wrap_" prefixing is left to the build-time linker
+ * (with -Wl,--wrap), or to the mozmemory.h header for malloc_good_size and
+ * jemalloc specific functions.
+ *
+ *
+ * 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".
+ *
+ * While mozjemalloc uses these "_impl" suffixed helpers, jemalloc3, being
+ * third-party code, doesn't, but instead has an elaborate way to mangle
+ * individual functions. See under "Run jemalloc configure script" in
+ * $(topsrcdir)/configure.in.
+ */
+
+#ifndef MOZ_MEMORY
+#  error Should only include mozmemory_wrap.h when MOZ_MEMORY is set.
+#endif
+
+#if defined(MOZ_MEMORY_IMPL) && !defined(IMPL_MFBT)
+#  ifdef MFBT_API /* mozilla/Types.h was already included */
+#    error mozmemory_wrap.h has to be included before mozilla/Types.h when MOZ_MEMORY_IMPL is set and IMPL_MFBT is not.
+#  endif
+#  define IMPL_MFBT
+#endif
+
+#include "mozilla/Types.h"
+
+#if !defined(MOZ_NATIVE_JEMALLOC)
+#  ifdef MOZ_MEMORY_IMPL
+#    define MOZ_JEMALLOC_API MFBT_API
+#    ifdef XP_WIN
+#      define mozmem_malloc_impl(a)   je_ ## a
+#      define mozmem_dup_impl(a)      wrap_ ## a
+#    elif defined(XP_DARWIN)
+#      define mozmem_malloc_impl(a)   je_ ## a
+#    else
+#      define MOZ_MEMORY_API MFBT_API
+#      if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
+#        define MOZ_WRAP_NEW_DELETE
+#      endif
+#    endif
+#  endif
+
+#  if defined(MOZ_WIDGET_ANDROID)
+#    define mozmem_malloc_impl(a)   __wrap_ ## a
+#    define mozmem_dup_impl(a)      __wrap_ ## a
+#  endif
+
+/* All other jemalloc3 functions are prefixed with "je_", except when
+ * building against an unprefixed system jemalloc library */
+#  define je_(a) je_ ## a
+#else /* defined(MOZ_NATIVE_JEMALLOC) */
+#  define je_(a) a
+#endif
+
+#if !defined(MOZ_MEMORY_IMPL) || defined(MOZ_NATIVE_JEMALLOC)
+#  define MOZ_MEMORY_API MFBT_API
+#  define MOZ_JEMALLOC_API MFBT_API
+#endif
+
+#ifndef MOZ_MEMORY_API
+#  define MOZ_MEMORY_API
+#endif
+#ifndef MOZ_JEMALLOC_API
+#  define MOZ_JEMALLOC_API
+#endif
+
+#ifndef mozmem_malloc_impl
+#  define mozmem_malloc_impl(a)   a
+#endif
+#ifndef mozmem_dup_impl
+#  define mozmem_dup_impl(a)      a
+#endif
+#ifndef mozmem_jemalloc_impl
+#  define mozmem_jemalloc_impl(a) a
+#endif
+
+/* Malloc implementation functions */
+#define malloc_impl              mozmem_malloc_impl(malloc)
+#define posix_memalign_impl      mozmem_malloc_impl(posix_memalign)
+#define aligned_alloc_impl       mozmem_malloc_impl(aligned_alloc)
+#define calloc_impl              mozmem_malloc_impl(calloc)
+#define realloc_impl             mozmem_malloc_impl(realloc)
+#define free_impl                mozmem_malloc_impl(free)
+#define memalign_impl            mozmem_malloc_impl(memalign)
+#define valloc_impl              mozmem_malloc_impl(valloc)
+#define malloc_usable_size_impl  mozmem_malloc_impl(malloc_usable_size)
+#define malloc_good_size_impl    mozmem_malloc_impl(malloc_good_size)
+
+/* Duplication functions */
+#define strndup_impl   mozmem_dup_impl(strndup)
+#define strdup_impl    mozmem_dup_impl(strdup)
+#ifdef XP_WIN
+#  define wcsdup_impl  mozmem_dup_impl(wcsdup)
+#endif
+
+/* Jemalloc specific function */
+#define jemalloc_stats_impl              mozmem_jemalloc_impl(jemalloc_stats)
+#define jemalloc_purge_freed_pages_impl  mozmem_jemalloc_impl(jemalloc_purge_freed_pages)
+#define jemalloc_free_dirty_pages_impl   mozmem_jemalloc_impl(jemalloc_free_dirty_pages)
+
+#endif /* mozmemory_wrap_h */
--- a/memory/mozjemalloc/Makefile.in
+++ b/memory/mozjemalloc/Makefile.in
@@ -7,23 +7,19 @@ DEPTH		= @DEPTH@
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE		= jemalloc
 
-EXPORTS = jemalloc.h jemalloc_types.h
+EXPORTS = jemalloc_types.h
 
-ifndef MOZ_JEMALLOC
-# jemalloc.c properly uses 'static', so don't burden it with manually exposing
-# symbols.
-VISIBILITY_FLAGS=
-
+ifndef MOZ_JEMALLOC3
 CSRCS = jemalloc.c
 
 LIBRARY_NAME = jemalloc
 FORCE_STATIC_LIB= 1
 
 ifeq ($(OS_ARCH),SunOS)
 ifndef GNU_CC
 MODULE_OPTIMIZE_FLAGS = -xO5
@@ -32,18 +28,22 @@ endif
 
 ifeq (Linux,$(OS_TARGET))
 #XXX: PGO on Linux causes problems here
 # See bug 419470
 NO_PROFILE_GUIDED_OPTIMIZE = 1
 endif
 endif
 
+LOCAL_INCLUDES += -I$(topsrcdir)/memory/build
+
 # For non release/esr builds, enable (some) fatal jemalloc assertions.  This
 # helps us catch memory errors.  See bug 764192 for details on what
 # MOZ_TEMP_INVESTIGATION is for.
 ifeq (,$(filter release esr,$(MOZ_UPDATE_CHANNEL)))
 DEFINES	+= -DMOZ_JEMALLOC_HARD_ASSERTS -DMOZ_TEMP_INVESTIGATION
 endif
 
 DEFINES += -Dabort=moz_abort
 
+DEFINES += -DMOZ_MEMORY_IMPL
+
 include $(topsrcdir)/config/rules.mk
--- a/memory/mozjemalloc/jemalloc.c
+++ b/memory/mozjemalloc/jemalloc.c
@@ -118,18 +118,18 @@
  * absence of memory pressure, the contribution from the heap to RSS will not
  * decrease due to our madvise calls.
  *
  * We therefore define MALLOC_DOUBLE_PURGE on Mac.  This causes jemalloc to
  * track which pages have been MADV_FREE'd.  You can then call
  * jemalloc_purge_freed_pages(), which will force the OS to release those
  * MADV_FREE'd pages, making the process's RSS reflect its true memory usage.
  *
- * The jemalloc_purge_freed_pages definition in jemalloc.h needs to be
- * adjusted if MALLOC_DOUBLE_PURGE is ever enabled on Linux.
+ * The jemalloc_purge_freed_pages definition in memory/build/mozmemory.h needs
+ * to be adjusted if MALLOC_DOUBLE_PURGE is ever enabled on Linux.
  */
 #ifdef MOZ_MEMORY_DARWIN
 #define MALLOC_DOUBLE_PURGE
 #endif
 
 /*
  * MALLOC_PRODUCTION disables assertions and statistics gathering.  It also
  * defaults the A and J runtime options to off.  These settings are appropriate
@@ -385,16 +385,17 @@ typedef long ssize_t;
 #ifndef MOZ_MEMORY
 #include "un-namespace.h"
 #endif
 
 #endif
 
 #include "jemalloc_types.h"
 #include "linkedlist.h"
+#include "mozmemory_wrap.h"
 
 /* Some tools, such as /dev/dsp wrappers, LD_PRELOAD libraries that
  * happen to override mmap() and call dlsym() from their overridden
  * mmap(). The problem is that dlsym() calls malloc(), and this ends
  * up in a dead lock in jemalloc.
  * On these systems, we prefer to directly use the system call.
  * We do that for Linux systems and kfreebsd with GNU userland.
  * Note sanity checks are not done (alignment of offset, ...) because
@@ -1284,16 +1285,17 @@ static __thread arena_t	*arenas_map;
 /* Chunk statistics. */
 static chunk_stats_t	stats_chunks;
 #endif
 
 /*******************************/
 /*
  * Runtime configuration options.
  */
+MOZ_JEMALLOC_API
 const char	*_malloc_options = MOZ_MALLOC_OPTIONS;
 
 #ifndef MALLOC_PRODUCTION
 static bool	opt_abort = true;
 #ifdef MALLOC_FILL
 static bool	opt_junk = true;
 #endif
 #else
@@ -1540,16 +1542,17 @@ wrtmessage(const char *p1, const char *p
 #define	_write	write
 #endif
 	_write(STDERR_FILENO, p1, (unsigned int) strlen(p1));
 	_write(STDERR_FILENO, p2, (unsigned int) strlen(p2));
 	_write(STDERR_FILENO, p3, (unsigned int) strlen(p3));
 	_write(STDERR_FILENO, p4, (unsigned int) strlen(p4));
 }
 
+MOZ_JEMALLOC_API
 void	(*_malloc_message)(const char *p1, const char *p2, const char *p3,
 	    const char *p4) = wrtmessage;
 
 #ifdef MALLOC_DEBUG
 #  define assert(e) do {						\
 	if (!(e)) {							\
 		char line_buf[UMAX2S_BUFSIZE];				\
 		_malloc_message(__FILE__, ":", umax2s(__LINE__, 10,	\
@@ -6235,45 +6238,16 @@ malloc_shutdown()
  * End general internal functions.
  */
 /******************************************************************************/
 /*
  * Begin malloc(3)-compatible functions.
  */
 
 /*
- * Mangle standard interfaces, in order to avoid linking problems.
- */
-#ifndef MOZ_MEMORY_GONK
-#if defined(MOZ_MEMORY_DARWIN) || defined(MOZ_MEMORY_WINDOWS) || \
-    defined(MOZ_MEMORY_ANDROID)
-
-#ifdef MOZ_MEMORY_ANDROID
-/*
- * On Android, we use __wrap_* instead of je_* to accomodate with the
- * linker's --wrap option we use. That option prefixes the function
- * names it is given with __wrap_.
- */
-#define wrap(a) __wrap_ ## a
-#else
-#define wrap(a) je_ ## a
-#endif
-
-#define malloc(a)               wrap(malloc)(a)
-#define memalign(a, b)          wrap(memalign)(a, b)
-#define posix_memalign(a, b, c) wrap(posix_memalign)(a, b, c)
-#define valloc(a)               wrap(valloc)(a)
-#define calloc(a, b)            wrap(calloc)(a, b)
-#define realloc(a, b)           wrap(realloc)(a, b)
-#define free(a)                 wrap(free)(a)
-#define malloc_usable_size(a)   wrap(malloc_usable_size)(a)
-#endif
-#endif
-
-/*
  * Even though we compile with MOZ_MEMORY, we may have to dynamically decide
  * not to use jemalloc, as discussed above. However, we call jemalloc
  * functions directly from mozalloc. Since it's pretty dangerous to mix the
  * allocators, we need to call the OSX allocators from the functions below,
  * when osx_use_jemalloc is not (dynamically) set.
  *
  * Note that we assume jemalloc is enabled on i386.  This is safe because the
  * only i386 versions of MacOS are 10.5 and 10.6, which we support.  We have to
@@ -6282,18 +6256,18 @@ malloc_shutdown()
  * This means that NO_MAC_JEMALLOC doesn't work on i386.
  */
 #if defined(MOZ_MEMORY_DARWIN) && !defined(__i386__)
 #define DARWIN_ONLY(A) if (!osx_use_jemalloc) { A; }
 #else
 #define DARWIN_ONLY(A)
 #endif
 
-void *
-malloc(size_t size)
+MOZ_MEMORY_API void *
+malloc_impl(size_t size)
 {
 	void *ret;
 
 	DARWIN_ONLY(return (szone->malloc)(szone, size));
 
 	if (malloc_init()) {
 		ret = NULL;
 		goto RETURN;
@@ -6344,34 +6318,37 @@ RETURN:
 
 #if defined(__GNUC__) && !defined(MOZ_MEMORY_DARWIN)
 #define MOZ_MEMORY_ELF
 #endif
 
 #ifdef MOZ_MEMORY_SOLARIS
 #  ifdef __SUNPRO_C
 void *
-memalign(size_t alignment, size_t size);
-#pragma no_inline(memalign)
+memalign_impl(size_t alignment, size_t size);
+#pragma no_inline(memalign_impl)
 #  elif (defined(__GNUC__))
 __attribute__((noinline))
 #  endif
 #else
 #if (defined(MOZ_MEMORY_ELF))
 __attribute__((visibility ("hidden")))
 #endif
 #endif
 
 
 #ifdef MOZ_MEMORY_ELF
 #define MEMALIGN memalign_internal
 #else
-#define MEMALIGN memalign
-#endif
-
+#define MEMALIGN memalign_impl
+#endif
+
+#ifndef MOZ_MEMORY_ELF
+MOZ_MEMORY_API
+#endif
 void *
 MEMALIGN(size_t alignment, size_t size)
 {
 	void *ret;
 
 	DARWIN_ONLY(return (szone->memalign)(szone, alignment, size));
 
 	assert(((alignment - 1) & alignment) == 0);
@@ -6406,21 +6383,21 @@ RETURN:
 	}
 #endif
 	UTRACE(0, size, ret);
 	return (ret);
 }
 
 #ifdef MOZ_MEMORY_ELF
 extern void *
-memalign(size_t alignment, size_t size) __attribute__((alias ("memalign_internal"), visibility ("default")));
-#endif
-
-int
-posix_memalign(void **memptr, size_t alignment, size_t size)
+memalign_impl(size_t alignment, size_t size) __attribute__((alias ("memalign_internal"), visibility ("default")));
+#endif
+
+MOZ_MEMORY_API int
+posix_memalign_impl(void **memptr, size_t alignment, size_t size)
 {
 	void *result;
 
 	/* Make sure that alignment is a large enough power of 2. */
 	if (((alignment - 1) & alignment) != 0 || alignment < sizeof(void *)) {
 #ifdef MALLOC_XMALLOC
 		if (opt_xmalloc) {
 			_malloc_message(_getprogname(),
@@ -6438,24 +6415,41 @@ posix_memalign(void **memptr, size_t ali
 
 	if (result == NULL)
 		return (ENOMEM);
 
 	*memptr = result;
 	return (0);
 }
 
-void *
-valloc(size_t size)
+MOZ_MEMORY_API void *
+aligned_alloc_impl(size_t alignment, size_t size)
+{
+	if (size % alignment) {
+#ifdef MALLOC_XMALLOC
+		if (opt_xmalloc) {
+			_malloc_message(_getprogname(),
+			    ": (malloc) Error in aligned_alloc(): "
+			    "size is not multiple of alignment\n", "", "");
+			abort();
+		}
+#endif
+		return (NULL);
+	}
+	return MEMALIGN(alignment, size);
+}
+
+MOZ_MEMORY_API void *
+valloc_impl(size_t size)
 {
 	return (MEMALIGN(pagesize, size));
 }
 
-void *
-calloc(size_t num, size_t size)
+MOZ_MEMORY_API void *
+calloc_impl(size_t num, size_t size)
 {
 	void *ret;
 	size_t num_size;
 
 	DARWIN_ONLY(return (szone->calloc)(szone, num, size));
 
 	if (malloc_init()) {
 		num_size = 0;
@@ -6501,18 +6495,18 @@ RETURN:
 #endif
 		errno = ENOMEM;
 	}
 
 	UTRACE(0, num_size, ret);
 	return (ret);
 }
 
-void *
-realloc(void *ptr, size_t size)
+MOZ_MEMORY_API void *
+realloc_impl(void *ptr, size_t size)
 {
 	void *ret;
 
 	DARWIN_ONLY(return (szone->realloc)(szone, ptr, size));
 
 	if (size == 0) {
 #ifdef MALLOC_SYSV
 		if (opt_sysv == false)
@@ -6565,18 +6559,18 @@ realloc(void *ptr, size_t size)
 
 #ifdef MALLOC_SYSV
 RETURN:
 #endif
 	UTRACE(ptr, size, ret);
 	return (ret);
 }
 
-void
-free(void *ptr)
+MOZ_MEMORY_API void
+free_impl(void *ptr)
 {
 	size_t offset;
 	
 	DARWIN_ONLY((szone->free)(szone, ptr); return);
 
 	UTRACE(ptr, 0, 0);
 
 	/*
@@ -6597,19 +6591,21 @@ free(void *ptr)
 /******************************************************************************/
 /*
  * Begin non-standard functions.
  */
 
 /* This was added by Mozilla for use by SQLite. */
 #ifdef MOZ_MEMORY_DARWIN
 static
+#else
+MOZ_MEMORY_API
 #endif
 size_t
-je_malloc_good_size(size_t size)
+malloc_good_size_impl(size_t size)
 {
 	/*
 	 * This duplicates the logic in imalloc(), arena_malloc() and
 	 * arena_malloc_small().
 	 */
 	if (size < small_min) {
 		/* Small (tiny). */
 		size = pow2_ceil(size);
@@ -6629,45 +6625,45 @@ je_malloc_good_size(size_t size)
 	} else if (size <= arena_maxclass) {
 		/* Large. */
 		size = PAGE_CEILING(size);
 	} else {
 		/*
 		 * Huge.  We use PAGE_CEILING to get psize, instead of using
 		 * CHUNK_CEILING to get csize.  This ensures that this
 		 * malloc_usable_size(malloc(n)) always matches
-		 * je_malloc_good_size(n).
+		 * malloc_good_size(n).
 		 */
 		size = PAGE_CEILING(size);
 	}
 	return size;
 }
 
 
 #ifdef MOZ_MEMORY_ANDROID
-size_t
-malloc_usable_size(void *ptr)
+MOZ_MEMORY_API size_t
+malloc_usable_size_impl(void *ptr)
 #else
-size_t
-malloc_usable_size(const void *ptr)
+MOZ_MEMORY_API size_t
+malloc_usable_size_impl(const void *ptr)
 #endif
 {
 	DARWIN_ONLY(return (szone->size)(szone, ptr));
 
 #ifdef MALLOC_VALIDATE
 	return (isalloc_validate(ptr));
 #else
 	assert(ptr != NULL);
 
 	return (isalloc(ptr));
 #endif
 }
 
-void
-jemalloc_stats(jemalloc_stats_t *stats)
+MOZ_JEMALLOC_API void
+jemalloc_stats_impl(jemalloc_stats_t *stats)
 {
 	size_t i;
 
 	assert(stats != NULL);
 
 	/*
 	 * Gather runtime settings.
 	 */
@@ -6795,31 +6791,31 @@ hard_purge_arena(arena_t *arena)
 				       arena_chunk_t, chunks_madvised_elem);
 		hard_purge_chunk(chunk);
 		LinkedList_Remove(&chunk->chunks_madvised_elem);
 	}
 
 	malloc_spin_unlock(&arena->lock);
 }
 
-void
-jemalloc_purge_freed_pages()
+MOZ_JEMALLOC_API void
+jemalloc_purge_freed_pages_impl()
 {
 	size_t i;
 	for (i = 0; i < narenas; i++) {
 		arena_t *arena = arenas[i];
 		if (arena != NULL)
 			hard_purge_arena(arena);
 	}
 }
 
 #else /* !defined MALLOC_DOUBLE_PURGE */
 
-void
-jemalloc_purge_freed_pages()
+MOZ_JEMALLOC_API void
+jemalloc_purge_freed_pages_impl()
 {
 	/* Do nothing. */
 }
 
 #endif /* defined MALLOC_DOUBLE_PURGE */
 
 
 
@@ -6859,22 +6855,22 @@ void*
 
 	return NULL;
 }
 
 size_t
 _msize(const void *ptr)
 {
 
-	return malloc_usable_size(ptr);
-}
-#endif
-
-void
-jemalloc_free_dirty_pages(void)
+	return malloc_usable_size_impl(ptr);
+}
+#endif
+
+MOZ_JEMALLOC_API void
+jemalloc_free_dirty_pages_impl(void)
 {
 	size_t i;
 	for (i = 0; i < narenas; i++) {
 		arena_t *arena = arenas[i];
 
 		if (arena != NULL) {
 			malloc_spin_lock(&arena->lock);
 			arena_purge(arena, true);
@@ -6940,96 +6936,96 @@ static void
 #endif
 
 #ifdef MOZ_MEMORY_DARWIN
 
 static void *
 zone_malloc(malloc_zone_t *zone, size_t size)
 {
 
-	return (malloc(size));
+	return (malloc_impl(size));
 }
 
 static void *
 zone_calloc(malloc_zone_t *zone, size_t num, size_t size)
 {
 
-	return (calloc(num, size));
+	return (calloc_impl(num, size));
 }
 
 static void *
 zone_valloc(malloc_zone_t *zone, size_t size)
 {
 	void *ret = NULL; /* Assignment avoids useless compiler warning. */
 
-	posix_memalign(&ret, pagesize, size);
+	posix_memalign_impl(&ret, pagesize, size);
 
 	return (ret);
 }
 
 static void *
 zone_memalign(malloc_zone_t *zone, size_t alignment, size_t size)
 {
-	return (memalign(alignment, size));
+	return (memalign_impl(alignment, size));
 }
 
 static void *
 zone_destroy(malloc_zone_t *zone)
 {
 
 	/* This function should never be called. */
 	assert(false);
 	return (NULL);
 }
 
 static size_t
 zone_good_size(malloc_zone_t *zone, size_t size)
 {
-	return je_malloc_good_size(size);
+	return malloc_good_size_impl(size);
 }
 
 static size_t
 ozone_size(malloc_zone_t *zone, void *ptr)
 {
 	size_t ret = isalloc_validate(ptr);
 	if (ret == 0)
 		ret = szone->size(zone, ptr);
 
 	return ret;
 }
 
 static void
 ozone_free(malloc_zone_t *zone, void *ptr)
 {
 	if (isalloc_validate(ptr) != 0)
-		free(ptr);
+		free_impl(ptr);
 	else {
 		size_t size = szone->size(zone, ptr);
 		if (size != 0)
 			(szone->free)(zone, ptr);
 		/* Otherwise we leak. */
 	}
 }
 
 static void *
 ozone_realloc(malloc_zone_t *zone, void *ptr, size_t size)
 {
     size_t oldsize;
 	if (ptr == NULL)
-		return (malloc(size));
+		return (malloc_impl(size));
 
 	oldsize = isalloc_validate(ptr);
 	if (oldsize != 0)
-		return (realloc(ptr, size));
+		return (realloc_impl(ptr, size));
 	else {
 		oldsize = szone->size(zone, ptr);
 		if (oldsize == 0)
-			return (malloc(size));
+			return (malloc_impl(size));
 		else {
-			void *ret = malloc(size);
+			void *ret = malloc_impl(size);
 			if (ret != NULL) {
 				memcpy(ret, ptr, (oldsize < size) ? oldsize :
 				    size);
 				(szone->free)(zone, ptr);
 			}
 			return (ret);
 		}
 	}
@@ -7052,17 +7048,17 @@ ozone_batch_free(malloc_zone_t *zone, vo
 		ozone_free(zone, to_be_freed[i]);
 }
 
 static void
 ozone_free_definite_size(malloc_zone_t *zone, void *ptr, size_t size)
 {
 	if (isalloc_validate(ptr) != 0) {
 		assert(isalloc_validate(ptr) == size);
-		free(ptr);
+		free_impl(ptr);
 	} else {
 		assert(size == szone->size(zone, ptr));
 		l_szone.m16(zone, ptr, size);
 	}
 }
 
 static void
 ozone_force_lock(malloc_zone_t *zone)
@@ -7174,20 +7170,20 @@ jemalloc_darwin_init(void)
  * 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.
  */
-void (*__free_hook)(void *ptr) = free;
-void *(*__malloc_hook)(size_t size) = malloc;
-void *(*__realloc_hook)(void *ptr, size_t size) = realloc;
-void *(*__memalign_hook)(size_t alignment, size_t size) = MEMALIGN;
+MOZ_MEMORY_API void (*__free_hook)(void *ptr) = free;
+MOZ_MEMORY_API void *(*__malloc_hook)(size_t size) = malloc;
+MOZ_MEMORY_API void *(*__realloc_hook)(void *ptr, size_t size) = realloc;
+MOZ_MEMORY_API void *(*__memalign_hook)(size_t alignment, size_t size) = MEMALIGN;
 
 #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."
--- a/mozglue/build/mozglue.def.in
+++ b/mozglue/build/mozglue.def.in
@@ -7,24 +7,20 @@ LIBRARY mozglue.dll
 EXPORTS
 #ifdef MOZ_MEMORY
   ; symbols that are actually useful
   malloc=je_malloc
   calloc=je_calloc
   realloc=je_realloc
   free=je_free
   posix_memalign=je_posix_memalign
-  strndup=je_strndup
-  strdup=je_strdup
-  _strdup=je_strdup
-  wcsdup=je_wcsdup
-  _wcsdup=je_wcsdup
   malloc_usable_size=je_malloc_usable_size
-#ifdef MOZ_JEMALLOC
-  je_nallocm
-#else
-  je_malloc_good_size
-#endif
+  malloc_good_size=je_malloc_good_size
+  strndup=wrap_strndup
+  strdup=wrap_strdup
+  _strdup=wrap_strdup
+  wcsdup=wrap_wcsdup
+  _wcsdup=wrap_wcsdup
   jemalloc_stats
   jemalloc_free_dirty_pages
   ; A hack to work around the CRT (see giant comment in Makefile.in)
-  frex=je_dumb_free_thunk
+  frex=dumb_free_thunk
 #endif
--- a/storage/src/mozStorageService.cpp
+++ b/storage/src/mozStorageService.cpp
@@ -491,17 +491,17 @@ void
 Service::shutdown()
 {
   NS_IF_RELEASE(sXPConnect);
 }
 
 sqlite3_vfs *ConstructTelemetryVFS();
 
 #ifdef MOZ_STORAGE_MEMORY
-#  include "jemalloc.h"
+#  include "mozmemory.h"
 
 namespace {
 
 // By default, SQLite tracks the size of all its heap blocks by adding an extra
 // 8 bytes at the start of the block to hold the size.  Unfortunately, this
 // causes a lot of 2^N-sized allocations to be rounded up by jemalloc
 // allocator, wasting memory.  For example, a request for 1024 bytes has 8
 // bytes added, becoming a request for 1032 bytes, and jemalloc rounds this up
@@ -530,17 +530,17 @@ static void *sqliteMemRealloc(void *p, i
 
 static int sqliteMemSize(void *p)
 {
   return ::moz_malloc_usable_size(p);
 }
 
 static int sqliteMemRoundup(int n)
 {
-  n = je_malloc_usable_size_in_advance(n);
+  n = malloc_good_size(n);
 
   // jemalloc can return blocks of size 2 and 4, but SQLite requires that all
   // allocations be 8-aligned.  So we round up sub-8 requests to 8.  This
   // wastes a small amount of memory but is obviously safe.
   return n <= 8 ? 8 : n;
 }
 
 static int sqliteMemInit(void *p)
--- a/xpcom/base/AvailableMemoryTracker.cpp
+++ b/xpcom/base/AvailableMemoryTracker.cpp
@@ -22,17 +22,17 @@
 #include "mozilla/Services.h"
 
 #if defined(XP_WIN)
 #   include "nsWindowsDllInterceptor.h"
 #   include <windows.h>
 #endif
 
 #if defined(MOZ_MEMORY)
-#   include "jemalloc.h"
+#   include "mozmemory.h"
 #endif  // MOZ_MEMORY
 
 using namespace mozilla;
 
 namespace {
 
 #if defined(XP_WIN)
 
@@ -493,19 +493,17 @@ public:
 
 NS_IMPL_ISUPPORTS1(nsJemallocFreeDirtyPagesRunnable, nsIRunnable)
 
 NS_IMETHODIMP
 nsJemallocFreeDirtyPagesRunnable::Run()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-#if defined(MOZ_JEMALLOC)
-  mallctl("arenas.purge", nullptr, 0, nullptr, 0);
-#elif defined(MOZ_MEMORY)
+#if defined(MOZ_MEMORY)
   jemalloc_free_dirty_pages();
 #endif
 
   return NS_OK;
 }
 
 /**
  * The memory pressure watcher is used for listening to memory-pressure events
--- a/xpcom/base/nsMemoryReporterManager.cpp
+++ b/xpcom/base/nsMemoryReporterManager.cpp
@@ -25,17 +25,17 @@
 #ifndef XP_WIN
 #include <unistd.h>
 #endif
 
 using namespace mozilla;
 
 #if defined(MOZ_MEMORY)
 #  define HAVE_JEMALLOC_STATS 1
-#  include "jemalloc.h"
+#  include "mozmemory.h"
 #endif  // MOZ_MEMORY
 
 #ifdef XP_UNIX
 
 #include <sys/time.h>
 #include <sys/resource.h>
 
 #define HAVE_PAGE_FAULT_REPORTERS 1
--- a/xpcom/tests/TestJemalloc.cpp
+++ b/xpcom/tests/TestJemalloc.cpp
@@ -5,27 +5,27 @@
 
 /*
  * Ideally, this test would be in memory/test/.  But I couldn't get it to build
  * there (couldn't find TestHarness.h).  I think memory/ is processed too early
  * in the build.  So it's here.
  */
 
 #include "TestHarness.h"
-#include "jemalloc.h"
+#include "mozmemory.h"
 
 static inline bool
 TestOne(size_t size)
 {
     size_t req = size;
-    size_t adv = je_malloc_usable_size_in_advance(req);
+    size_t adv = malloc_good_size(req);
     char* p = (char*)malloc(req);
     size_t usable = moz_malloc_usable_size(p);
     if (adv != usable) {
-      fail("je_malloc_usable_size_in_advance(%d) --> %d; "
+      fail("malloc_good_size(%d) --> %d; "
            "malloc_usable_size(%d) --> %d",
            req, adv, req, usable);
       return false;
     }
     free(p);
     return true;
 }
 
@@ -53,17 +53,17 @@ TestJemallocUsableSizeInAdvance()
   for (size_t n = 16 K; n < 1 M; n += 4 K)
     if (!TestThree(n))
       return NS_ERROR_UNEXPECTED;
 
   for (size_t n = 1 M; n < 8 M; n += 128 K)
     if (!TestThree(n))
       return NS_ERROR_UNEXPECTED;
 
-  passed("je_malloc_usable_size_in_advance");
+  passed("malloc_good_size");
 
   return NS_OK;
 }
 
 int main(int argc, char** argv)
 {
   int rv = 0;
   ScopedXPCOM xpcom("jemalloc");