зеркало из https://github.com/mozilla/gecko-dev.git
Bug 804303 part 2 - Add ability to dynamically replace or supplement jemalloc implementation. r=jlebar,r=khuey
This commit is contained in:
Родитель
c51f5d814d
Коммит
e9c6d8bfe1
|
@ -71,6 +71,11 @@ if [ ! "$LIBXUL_SDK" ]; then
|
|||
memory/build/Makefile
|
||||
"
|
||||
fi
|
||||
if [ "$MOZ_REPLACE_MALLOC_LINKAGE" = "dummy library" ]; then
|
||||
add_makefiles "
|
||||
memory/replace/dummy/Makefile
|
||||
"
|
||||
fi
|
||||
if [ "$MOZ_WIDGET_TOOLKIT" = "android" ]; then
|
||||
add_makefiles "
|
||||
other-licenses/android/Makefile
|
||||
|
|
94
configure.in
94
configure.in
|
@ -7039,8 +7039,81 @@ else
|
|||
fi
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Enable dynamic replacement of malloc implementation
|
||||
dnl ========================================================
|
||||
MOZ_ARG_ENABLE_BOOL(replace-malloc,
|
||||
[ --enable-replace-malloc Enable ability to dynamically replace the malloc implementation],
|
||||
MOZ_REPLACE_MALLOC=1,
|
||||
MOZ_REPLACE_MALLOC= )
|
||||
|
||||
if test -n "$MOZ_REPLACE_MALLOC" -a -z "$MOZ_MEMORY"; then
|
||||
dnl We don't want to enable jemalloc unconditionally because it may be a
|
||||
dnl deliberate choice not to enable it (bug 702250, for instance)
|
||||
AC_MSG_ERROR([--enable-replace-malloc requires --enable-jemalloc])
|
||||
elif test -n "$MOZ_REPLACE_MALLOC"; then
|
||||
MOZ_NATIVE_JEMALLOC=
|
||||
|
||||
dnl Replace-malloc Mac linkage quirks
|
||||
if test -n "$MACOSX_DEPLOYMENT_TARGET"; then
|
||||
AC_CACHE_CHECK([how to do weak dynamic linking],
|
||||
ac_cv_weak_dynamic_linking,
|
||||
[echo 'extern void foo() __attribute__((weak_import));int bar() { if (foo) foo(); return 0; }' > conftest.c
|
||||
if AC_TRY_COMMAND([${CC-cc} -o conftest${DLL_SUFFIX} $CFLAGS -dynamiclib $LDFLAGS -Wl,-U,_foo conftest.c $LIBS 1>&5]) &&
|
||||
test -s conftest${DLL_SUFFIX}; then
|
||||
dnl There are several ways the linker can put link edit rules in a binary:
|
||||
dnl - classic info only (for OSX < 10.6)
|
||||
dnl - dyld info only
|
||||
dnl - both
|
||||
if otool -l conftest${DLL_SUFFIX} 2> /dev/null | grep "LC_DYLD_INFO_ONLY" > /dev/null; then
|
||||
_CLASSIC_INFO=
|
||||
else
|
||||
_CLASSIC_INFO=1
|
||||
fi
|
||||
if otool -l conftest${DLL_SUFFIX} 2> /dev/null | grep "LC_DYLD_INFO" > /dev/null; then
|
||||
_DYLD_INFO=1
|
||||
else
|
||||
_DYLD_INFO=
|
||||
fi
|
||||
dnl With classic info, we need to build with -flat_namespace.
|
||||
dnl With dyld info, Xcode 4.5 does the right thing without additional flags,
|
||||
dnl but Xcode < 4.5 requires a dummy library and -flat_namespace because it
|
||||
dnl forgets to set the weak flag in the dyld info.
|
||||
dnl See http://glandium.org/blog/?p=2764 for more details.
|
||||
dnl
|
||||
dnl Values for ac_cv_weak_dynamic_linking, and subsequently
|
||||
dnl MOZ_REPLACE_MALLOC_LINKAGE are thus:
|
||||
dnl - "flat namespace" when -flat_namespace alone is needed
|
||||
dnl - "dummy library" when a dummy library and -flat_namespace are needed
|
||||
dnl - "compiler support" when nothing is needed
|
||||
if test -n "$_DYLD_INFO" && dyldinfo -bind conftest${DLL_SUFFIX} 2> /dev/null | grep "_foo (weak import)" > /dev/null; then
|
||||
if test -n "$_CLASSIC_INFO"; then
|
||||
ac_cv_weak_dynamic_linking="flat namespace"
|
||||
else
|
||||
ac_cv_weak_dynamic_linking="compiler support"
|
||||
fi
|
||||
else
|
||||
if test -n "$_DYLD_INFO"; then
|
||||
ac_cv_weak_dynamic_linking="dummy library"
|
||||
else
|
||||
ac_cv_weak_dynamic_linking="flat namespace"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
AC_ERROR([couldn't compile a simple C file])
|
||||
fi
|
||||
rm -rf conftest*])
|
||||
MOZ_REPLACE_MALLOC_LINKAGE="$ac_cv_weak_dynamic_linking"
|
||||
fi
|
||||
fi
|
||||
AC_SUBST(MOZ_REPLACE_MALLOC)
|
||||
AC_SUBST(MOZ_REPLACE_MALLOC_LINKAGE)
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Jemalloc build setup
|
||||
dnl ========================================================
|
||||
if test -z "$MOZ_MEMORY"; then
|
||||
if test -n "$MOZ_JEMALLOC3"; then
|
||||
if test -n "$MOZ_JEMALLOC3" -a -z "$MOZ_REPLACE_MALLOC"; then
|
||||
MOZ_NATIVE_JEMALLOC=1
|
||||
AC_CHECK_FUNCS(mallctl nallocm,,
|
||||
[MOZ_NATIVE_JEMALLOC=
|
||||
|
@ -8994,8 +9067,13 @@ fi
|
|||
|
||||
# Run jemalloc configure script
|
||||
|
||||
if test -z "$MOZ_NATIVE_JEMALLOC" -a "$MOZ_JEMALLOC3" -a "$MOZ_MEMORY" ; then
|
||||
if test -z "$MOZ_NATIVE_JEMALLOC" -a "$MOZ_MEMORY" -a "$MOZ_JEMALLOC3"; then
|
||||
ac_configure_args="$_SUBDIR_CONFIG_ARGS --build=$build --host=$target --enable-stats --with-jemalloc-prefix=je_"
|
||||
if test -n "$MOZ_REPLACE_MALLOC"; then
|
||||
# When using replace_malloc, we always want memalign and valloc exported from jemalloc.
|
||||
ac_configure_args="$ac_configure_args ac_cv_func_memalign=yes"
|
||||
ac_configure_args="$ac_configure_args ac_cv_func_valloc=yes"
|
||||
fi
|
||||
case "${OS_ARCH}" in
|
||||
WINNT|Darwin)
|
||||
# We want jemalloc functions to be kept hidden on both Mac and Windows
|
||||
|
@ -9003,11 +9081,13 @@ if test -z "$MOZ_NATIVE_JEMALLOC" -a "$MOZ_JEMALLOC3" -a "$MOZ_MEMORY" ; then
|
|||
ac_configure_args="$ac_configure_args --without-export"
|
||||
;;
|
||||
esac
|
||||
case "$OS_ARCH" in
|
||||
Linux|DragonFly|FreeBSD|NetBSD|OpenBSD)
|
||||
MANGLE="malloc posix_memalign aligned_alloc calloc realloc free memalign valloc malloc_usable_size"
|
||||
;;
|
||||
esac
|
||||
if test -z "$MOZ_REPLACE_MALLOC"; then
|
||||
case "$OS_ARCH" in
|
||||
Linux|DragonFly|FreeBSD|NetBSD|OpenBSD)
|
||||
MANGLE="malloc posix_memalign aligned_alloc calloc realloc free memalign valloc malloc_usable_size"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
if test -n "$MANGLE"; then
|
||||
MANGLED=
|
||||
JEMALLOC_WRAPPER=
|
||||
|
|
|
@ -19,4 +19,8 @@ endif
|
|||
|
||||
DIRS += build
|
||||
|
||||
ifeq ($(MOZ_REPLACE_MALLOC_LINKAGE),dummy library)
|
||||
DIRS += replace/dummy
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -44,4 +44,19 @@ else
|
|||
SHARED_LIBRARY_LIBS += $(call EXPAND_LIBNAME_PATH,jemalloc,$(DEPTH)/memory/mozjemalloc)
|
||||
endif
|
||||
|
||||
ifdef MOZ_REPLACE_MALLOC
|
||||
DEFINES += -DMOZ_REPLACE_MALLOC
|
||||
CSRCS += replace_malloc.c
|
||||
|
||||
EXPORTS += \
|
||||
replace_malloc.h \
|
||||
malloc_decls.h \
|
||||
$(NULL)
|
||||
|
||||
# The zone allocator for OSX needs some jemalloc internal functions
|
||||
ifeq (Darwin,$(OS_TARGET))
|
||||
LOCAL_INCLUDES += -I$(topsrcdir)/memory/jemalloc/src/include
|
||||
endif
|
||||
endif
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#ifdef MOZ_JEMALLOC3
|
||||
|
||||
#define MOZ_JEMALLOC_IMPL
|
||||
|
||||
#include "mozmemory_wrap.h"
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
|
|
|
@ -13,14 +13,30 @@
|
|||
#ifndef malloc_decls_h
|
||||
# define malloc_decls_h
|
||||
|
||||
# include "jemalloc_types.h"
|
||||
|
||||
# ifdef __linux__
|
||||
typedef void * usable_ptr_t;
|
||||
# else
|
||||
typedef const void * usable_ptr_t;
|
||||
# endif
|
||||
|
||||
# define MALLOC_FUNCS_MALLOC 1
|
||||
# define MALLOC_FUNCS_JEMALLOC 2
|
||||
# define MALLOC_FUNCS_INIT 4
|
||||
# define MALLOC_FUNCS_ALL (MALLOC_FUNCS_INIT | MALLOC_FUNCS_MALLOC | MALLOC_FUNCS_JEMALLOC)
|
||||
|
||||
#endif /* malloc_decls_h */
|
||||
|
||||
#ifndef MALLOC_FUNCS
|
||||
# define MALLOC_FUNCS (MALLOC_FUNCS_MALLOC | MALLOC_FUNCS_JEMALLOC)
|
||||
#endif
|
||||
|
||||
#ifdef MALLOC_DECL
|
||||
# if MALLOC_FUNCS & MALLOC_FUNCS_INIT
|
||||
MALLOC_DECL(init, void, const malloc_table_t *)
|
||||
# endif
|
||||
# if MALLOC_FUNCS & MALLOC_FUNCS_MALLOC
|
||||
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)
|
||||
|
@ -31,6 +47,13 @@ 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
|
||||
# if MALLOC_FUNCS & MALLOC_FUNCS_JEMALLOC
|
||||
MALLOC_DECL(jemalloc_stats, void, jemalloc_stats_t *)
|
||||
MALLOC_DECL(jemalloc_purge_freed_pages, void, void)
|
||||
MALLOC_DECL(jemalloc_free_dirty_pages, void, void)
|
||||
# endif
|
||||
#endif /* MALLOC_DECL */
|
||||
|
||||
#undef MALLOC_DECL
|
||||
#undef MALLOC_FUNCS
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
# error Should only compile this file when building with jemalloc 3
|
||||
#endif
|
||||
|
||||
#define MOZ_JEMALLOC_IMPL
|
||||
|
||||
#include "mozmemory_wrap.h"
|
||||
#include "jemalloc_types.h"
|
||||
#include "mozilla/Types.h"
|
||||
|
|
|
@ -94,12 +94,31 @@
|
|||
* 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.
|
||||
*
|
||||
*
|
||||
* 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 jemalloc/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 or
|
||||
* jemalloc3/mozjemalloc_compat, 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
|
||||
#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.
|
||||
|
@ -111,22 +130,33 @@
|
|||
|
||||
#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
|
||||
# if defined(MOZ_JEMALLOC_IMPL) && defined(MOZ_REPLACE_MALLOC)
|
||||
# define mozmem_malloc_impl(a) je_ ## a
|
||||
# define mozmem_jemalloc_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
|
||||
# define MOZ_JEMALLOC_API MFBT_API
|
||||
# if (defined(XP_WIN) || defined(XP_DARWIN))
|
||||
# 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 MFBT_API
|
||||
# if defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GONK)
|
||||
# define MOZ_WRAP_NEW_DELETE
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
# ifdef XP_WIN
|
||||
# define mozmem_dup_impl(a) wrap_ ## a
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# if defined(MOZ_WIDGET_ANDROID)
|
||||
# define mozmem_malloc_impl(a) __wrap_ ## a
|
||||
# ifndef mozmem_malloc_impl
|
||||
# define mozmem_malloc_impl(a) __wrap_ ## a
|
||||
# endif
|
||||
# define mozmem_dup_impl(a) __wrap_ ## a
|
||||
# endif
|
||||
|
||||
|
|
|
@ -0,0 +1,505 @@
|
|||
/* 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
|
||||
|
||||
#ifdef MOZ_NATIVE_JEMALLOC
|
||||
# error Should not compile this file when we want to use native jemalloc
|
||||
#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"
|
||||
/*
|
||||
* 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"
|
||||
};
|
||||
|
||||
#ifdef MOZ_NO_REPLACE_FUNC_DECL
|
||||
# define MALLOC_DECL(name, return_type, ...) \
|
||||
typedef return_type (replace_ ## name ## _impl_t)(__VA_ARGS__); \
|
||||
replace_ ## name ## _impl_t *replace_ ## name = NULL;
|
||||
# define MALLOC_FUNCS MALLOC_FUNCS_ALL
|
||||
# include "malloc_decls.h"
|
||||
|
||||
# ifdef XP_WIN
|
||||
# include <windows.h>
|
||||
static void
|
||||
replace_malloc_init_funcs()
|
||||
{
|
||||
char replace_malloc_lib[1024];
|
||||
if (GetEnvironmentVariableA("MOZ_REPLACE_MALLOC_LIB", (LPSTR)&replace_malloc_lib,
|
||||
sizeof(replace_malloc_lib)) > 0) {
|
||||
HMODULE handle = LoadLibraryA(replace_malloc_lib);
|
||||
if (handle) {
|
||||
#define MALLOC_DECL(name, ...) \
|
||||
replace_ ## name = (replace_ ## name ## _impl_t *) GetProcAddress(handle, "replace_" # name);
|
||||
|
||||
# define MALLOC_FUNCS MALLOC_FUNCS_ALL
|
||||
#include "malloc_decls.h"
|
||||
}
|
||||
}
|
||||
}
|
||||
# elif defined(MOZ_WIDGET_ANDROID)
|
||||
# include <dlfcn.h>
|
||||
static void
|
||||
replace_malloc_init_funcs()
|
||||
{
|
||||
char *replace_malloc_lib = getenv("MOZ_REPLACE_MALLOC_LIB");
|
||||
if (replace_malloc_lib && *replace_malloc_lib) {
|
||||
void *handle = dlopen(replace_malloc_lib, RTLD_LAZY);
|
||||
if (handle) {
|
||||
#define MALLOC_DECL(name, ...) \
|
||||
replace_ ## name = (replace_ ## name ## _impl_t *) dlsym(handle, "replace_" # name);
|
||||
|
||||
# define MALLOC_FUNCS MALLOC_FUNCS_ALL
|
||||
#include "malloc_decls.h"
|
||||
}
|
||||
}
|
||||
}
|
||||
# else
|
||||
# error No implementation for replace_malloc_init_funcs()
|
||||
# endif
|
||||
|
||||
#endif /* MOZ_NO_REPLACE_FUNC_DECL */
|
||||
|
||||
/*
|
||||
* Below is the malloc implementation overriding jemalloc and calling the
|
||||
* replacement functions if they exist.
|
||||
*/
|
||||
|
||||
/*
|
||||
* On OSX, MOZ_MEMORY_API is defined to nothing, because malloc functions
|
||||
* are meant to have hidden visibility. But since the functions are only
|
||||
* used locally in the zone allocator further below, we can allow the
|
||||
* compiler to optimize more by switching to static.
|
||||
*/
|
||||
#ifdef XP_DARWIN
|
||||
#undef MOZ_MEMORY_API
|
||||
#define MOZ_MEMORY_API static
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Malloc implementation functions are MOZ_MEMORY_API, and jemalloc
|
||||
* specific functions MOZ_JEMALLOC_API; see mozmemory_wrap.h
|
||||
*/
|
||||
#define MALLOC_DECL(name, return_type, ...) \
|
||||
MOZ_MEMORY_API return_type name ## _impl(__VA_ARGS__);
|
||||
#define MALLOC_FUNCS MALLOC_FUNCS_MALLOC
|
||||
#include "malloc_decls.h"
|
||||
|
||||
#define MALLOC_DECL(name, return_type, ...) \
|
||||
MOZ_JEMALLOC_API return_type name ## _impl(__VA_ARGS__);
|
||||
#define MALLOC_FUNCS MALLOC_FUNCS_JEMALLOC
|
||||
#include "malloc_decls.h"
|
||||
|
||||
static int replace_malloc_initialized = 0;
|
||||
static void
|
||||
init()
|
||||
{
|
||||
#ifdef MOZ_NO_REPLACE_FUNC_DECL
|
||||
replace_malloc_init_funcs();
|
||||
#endif
|
||||
// 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);
|
||||
}
|
||||
|
||||
void*
|
||||
malloc_impl(size_t size)
|
||||
{
|
||||
if (MOZ_UNLIKELY(!replace_malloc_initialized))
|
||||
init();
|
||||
if (MOZ_LIKELY(!replace_malloc))
|
||||
return je_malloc(size);
|
||||
return replace_malloc(size);
|
||||
}
|
||||
|
||||
int
|
||||
posix_memalign_impl(void **memptr, size_t alignment, size_t size)
|
||||
{
|
||||
if (MOZ_UNLIKELY(!replace_malloc_initialized))
|
||||
init();
|
||||
if (MOZ_LIKELY(!replace_posix_memalign))
|
||||
return je_posix_memalign(memptr, alignment, size);
|
||||
return replace_posix_memalign(memptr, alignment, size);
|
||||
}
|
||||
|
||||
void*
|
||||
aligned_alloc_impl(size_t alignment, size_t size)
|
||||
{
|
||||
if (MOZ_UNLIKELY(!replace_malloc_initialized))
|
||||
init();
|
||||
if (MOZ_LIKELY(!replace_aligned_alloc))
|
||||
return je_aligned_alloc(alignment, size);
|
||||
return replace_aligned_alloc(alignment, size);
|
||||
}
|
||||
|
||||
void*
|
||||
calloc_impl(size_t num, size_t size)
|
||||
{
|
||||
if (MOZ_UNLIKELY(!replace_malloc_initialized))
|
||||
init();
|
||||
if (MOZ_LIKELY(!replace_calloc))
|
||||
return je_calloc(num, size);
|
||||
return replace_calloc(num, size);
|
||||
}
|
||||
|
||||
void*
|
||||
realloc_impl(void *ptr, size_t size)
|
||||
{
|
||||
if (MOZ_UNLIKELY(!replace_malloc_initialized))
|
||||
init();
|
||||
if (MOZ_LIKELY(!replace_realloc))
|
||||
return je_realloc(ptr, size);
|
||||
return replace_realloc(ptr, size);
|
||||
}
|
||||
|
||||
void
|
||||
free_impl(void *ptr)
|
||||
{
|
||||
if (MOZ_UNLIKELY(!replace_malloc_initialized))
|
||||
init();
|
||||
if (MOZ_LIKELY(!replace_free))
|
||||
je_free(ptr);
|
||||
else
|
||||
replace_free(ptr);
|
||||
}
|
||||
|
||||
void*
|
||||
memalign_impl(size_t alignment, size_t size)
|
||||
{
|
||||
if (MOZ_UNLIKELY(!replace_malloc_initialized))
|
||||
init();
|
||||
if (MOZ_LIKELY(!replace_memalign))
|
||||
return je_memalign(alignment, size);
|
||||
return replace_memalign(alignment, size);
|
||||
}
|
||||
|
||||
void*
|
||||
valloc_impl(size_t size)
|
||||
{
|
||||
if (MOZ_UNLIKELY(!replace_malloc_initialized))
|
||||
init();
|
||||
if (MOZ_LIKELY(!replace_valloc))
|
||||
return je_valloc(size);
|
||||
return replace_valloc(size);
|
||||
}
|
||||
|
||||
size_t
|
||||
malloc_usable_size_impl(usable_ptr_t ptr)
|
||||
{
|
||||
if (MOZ_UNLIKELY(!replace_malloc_initialized))
|
||||
init();
|
||||
if (MOZ_LIKELY(!replace_malloc_usable_size))
|
||||
return je_malloc_usable_size(ptr);
|
||||
return replace_malloc_usable_size(ptr);
|
||||
}
|
||||
|
||||
size_t
|
||||
malloc_good_size_impl(size_t size)
|
||||
{
|
||||
if (MOZ_UNLIKELY(!replace_malloc_initialized))
|
||||
init();
|
||||
if (MOZ_LIKELY(!replace_malloc_good_size))
|
||||
return je_malloc_good_size(size);
|
||||
return replace_malloc_good_size(size);
|
||||
}
|
||||
|
||||
void
|
||||
jemalloc_stats_impl(jemalloc_stats_t *stats)
|
||||
{
|
||||
if (MOZ_UNLIKELY(!replace_malloc_initialized))
|
||||
init();
|
||||
if (MOZ_LIKELY(!replace_jemalloc_stats))
|
||||
je_jemalloc_stats(stats);
|
||||
else
|
||||
replace_jemalloc_stats(stats);
|
||||
}
|
||||
|
||||
void
|
||||
jemalloc_purge_freed_pages_impl()
|
||||
{
|
||||
if (MOZ_UNLIKELY(!replace_malloc_initialized))
|
||||
init();
|
||||
if (MOZ_LIKELY(!replace_jemalloc_purge_freed_pages))
|
||||
je_jemalloc_purge_freed_pages();
|
||||
else
|
||||
replace_jemalloc_purge_freed_pages();
|
||||
}
|
||||
|
||||
void
|
||||
jemalloc_free_dirty_pages_impl()
|
||||
{
|
||||
if (MOZ_UNLIKELY(!replace_malloc_initialized))
|
||||
init();
|
||||
if (MOZ_LIKELY(!replace_jemalloc_free_dirty_pages))
|
||||
je_jemalloc_free_dirty_pages();
|
||||
else
|
||||
replace_jemalloc_free_dirty_pages();
|
||||
}
|
||||
|
||||
/* 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
|
||||
|
||||
/*
|
||||
* The following is a OSX zone allocator implementation.
|
||||
* /!\ WARNING. It assumes the underlying malloc implementation's
|
||||
* malloc_usable_size returns 0 when the given pointer is not owned by
|
||||
* the allocator. Sadly, OSX does call zone_size with pointers not
|
||||
* owned by the allocator.
|
||||
*/
|
||||
|
||||
#ifdef XP_DARWIN
|
||||
#include <stdlib.h>
|
||||
#include <malloc/malloc.h>
|
||||
#include "mozilla/Assertions.h"
|
||||
|
||||
static size_t
|
||||
zone_size(malloc_zone_t *zone, void *ptr)
|
||||
{
|
||||
return malloc_usable_size_impl(ptr);
|
||||
}
|
||||
|
||||
static void *
|
||||
zone_malloc(malloc_zone_t *zone, size_t size)
|
||||
{
|
||||
return malloc_impl(size);
|
||||
}
|
||||
|
||||
static void *
|
||||
zone_calloc(malloc_zone_t *zone, size_t num, size_t size)
|
||||
{
|
||||
return calloc_impl(num, size);
|
||||
}
|
||||
|
||||
static void *
|
||||
zone_realloc(malloc_zone_t *zone, void *ptr, size_t size)
|
||||
{
|
||||
if (malloc_usable_size_impl(ptr))
|
||||
return realloc_impl(ptr, size);
|
||||
return realloc(ptr, size);
|
||||
}
|
||||
|
||||
static void
|
||||
zone_free(malloc_zone_t *zone, void *ptr)
|
||||
{
|
||||
if (malloc_usable_size_impl(ptr)) {
|
||||
free_impl(ptr);
|
||||
return;
|
||||
}
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
static void
|
||||
zone_free_definite_size(malloc_zone_t *zone, void *ptr, size_t size)
|
||||
{
|
||||
size_t current_size = malloc_usable_size_impl(ptr);
|
||||
if (current_size) {
|
||||
MOZ_ASSERT(current_size == size);
|
||||
free_impl(ptr);
|
||||
return;
|
||||
}
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
static void *
|
||||
zone_memalign(malloc_zone_t *zone, size_t alignment, size_t size)
|
||||
{
|
||||
void *ptr;
|
||||
if (posix_memalign_impl(&ptr, alignment, size) == 0)
|
||||
return ptr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *
|
||||
zone_valloc(malloc_zone_t *zone, size_t size)
|
||||
{
|
||||
return valloc_impl(size);
|
||||
}
|
||||
|
||||
static void *
|
||||
zone_destroy(malloc_zone_t *zone)
|
||||
{
|
||||
/* This function should never be called. */
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
static size_t
|
||||
zone_good_size(malloc_zone_t *zone, size_t size)
|
||||
{
|
||||
return malloc_good_size_impl(size);
|
||||
}
|
||||
|
||||
#ifdef MOZ_JEMALLOC
|
||||
|
||||
#include "jemalloc/internal/jemalloc_internal.h"
|
||||
|
||||
static void
|
||||
zone_force_lock(malloc_zone_t *zone)
|
||||
{
|
||||
/* /!\ This calls into jemalloc. It works because we're linked in the
|
||||
* same library. Stolen from jemalloc's zone.c. */
|
||||
if (isthreaded)
|
||||
jemalloc_prefork();
|
||||
}
|
||||
|
||||
static void
|
||||
zone_force_unlock(malloc_zone_t *zone)
|
||||
{
|
||||
/* /!\ This calls into jemalloc. It works because we're linked in the
|
||||
* same library. Stolen from jemalloc's zone.c. */
|
||||
if (isthreaded)
|
||||
jemalloc_postfork_parent();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define JEMALLOC_ZONE_VERSION 6
|
||||
|
||||
/* Empty implementations are needed, because fork() calls zone->force_(un)lock
|
||||
* unconditionally. */
|
||||
static void
|
||||
zone_force_lock(malloc_zone_t *zone)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
zone_force_unlock(malloc_zone_t *zone)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static malloc_zone_t zone;
|
||||
static struct malloc_introspection_t zone_introspect;
|
||||
|
||||
__attribute__((constructor)) void
|
||||
register_zone(void)
|
||||
{
|
||||
zone.size = (void *)zone_size;
|
||||
zone.malloc = (void *)zone_malloc;
|
||||
zone.calloc = (void *)zone_calloc;
|
||||
zone.valloc = (void *)zone_valloc;
|
||||
zone.free = (void *)zone_free;
|
||||
zone.realloc = (void *)zone_realloc;
|
||||
zone.destroy = (void *)zone_destroy;
|
||||
zone.zone_name = "replace_malloc_zone";
|
||||
zone.batch_malloc = NULL;
|
||||
zone.batch_free = NULL;
|
||||
zone.introspect = &zone_introspect;
|
||||
zone.version = JEMALLOC_ZONE_VERSION;
|
||||
zone.memalign = zone_memalign;
|
||||
zone.free_definite_size = zone_free_definite_size;
|
||||
#if (JEMALLOC_ZONE_VERSION >= 8)
|
||||
zone.pressure_relief = NULL;
|
||||
#endif
|
||||
zone_introspect.enumerator = NULL;
|
||||
zone_introspect.good_size = (void *)zone_good_size;
|
||||
zone_introspect.check = NULL;
|
||||
zone_introspect.print = NULL;
|
||||
zone_introspect.log = NULL;
|
||||
zone_introspect.force_lock = (void *)zone_force_lock;
|
||||
zone_introspect.force_unlock = (void *)zone_force_unlock;
|
||||
zone_introspect.statistics = NULL;
|
||||
zone_introspect.zone_locked = NULL;
|
||||
#if (JEMALLOC_ZONE_VERSION >= 7)
|
||||
zone_introspect.enable_discharge_checking = NULL;
|
||||
zone_introspect.disable_discharge_checking = NULL;
|
||||
zone_introspect.discharge = NULL;
|
||||
#ifdef __BLOCKS__
|
||||
zone_introspect.enumerate_discharged_pointers = NULL;
|
||||
#else
|
||||
zone_introspect.enumerate_unavailable_without_blocks = NULL;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The default purgeable zone is created lazily by OSX's libc. It uses
|
||||
* the default zone when it is created for "small" allocations
|
||||
* (< 15 KiB), but assumes the default zone is a scalable_zone. This
|
||||
* obviously fails when the default zone is the jemalloc zone, so
|
||||
* malloc_default_purgeable_zone is called beforehand so that the
|
||||
* default purgeable zone is created when the default zone is still
|
||||
* a scalable_zone. As purgeable zones only exist on >= 10.6, we need
|
||||
* to check for the existence of malloc_default_purgeable_zone() at
|
||||
* run time.
|
||||
*/
|
||||
malloc_default_purgeable_zone();
|
||||
|
||||
/* Register the custom zone. At this point it won't be the default. */
|
||||
malloc_zone_register(&zone);
|
||||
|
||||
/*
|
||||
* Unregister and reregister the default zone. On OSX >= 10.6,
|
||||
* unregistering takes the last registered zone and places it at the
|
||||
* location of the specified zone. Unregistering the default zone thus
|
||||
* makes the last registered one the default. On OSX < 10.6,
|
||||
* unregistering shifts all registered zones. The first registered zone
|
||||
* then becomes the default.
|
||||
*/
|
||||
do {
|
||||
malloc_zone_t *default_zone = malloc_default_zone();
|
||||
malloc_zone_unregister(default_zone);
|
||||
malloc_zone_register(default_zone);
|
||||
} while (malloc_default_zone() != &zone);
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,139 @@
|
|||
/* 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 replace_malloc_h
|
||||
#define replace_malloc_h
|
||||
|
||||
/*
|
||||
* The replace_malloc facility allows an external library to replace or
|
||||
* supplement the jemalloc implementation.
|
||||
*
|
||||
* The external library may be hooked by setting one of the following
|
||||
* environment variables to the library path:
|
||||
* - LD_PRELOAD on Linux,
|
||||
* - DYLD_INSERT_LIBRARIES on OSX,
|
||||
* - MOZ_REPLACE_MALLOC_LIB on Windows and Android.
|
||||
*
|
||||
* An initialization function is called before any malloc replacement
|
||||
* function, and has the following declaration:
|
||||
*
|
||||
* void replace_init(const malloc_table_t *)
|
||||
*
|
||||
* The const malloc_table_t pointer given to that function is a table
|
||||
* containing pointers to the original jemalloc implementation, so that
|
||||
* replacement functions can call them back if they need to. The pointer
|
||||
* itself can safely be kept around (no need to copy the table itself).
|
||||
*
|
||||
* The functions to be implemented in the external library are of the form:
|
||||
*
|
||||
* void *replace_malloc(size_t size)
|
||||
* {
|
||||
* // Fiddle with the size if necessary.
|
||||
* // orig->malloc doesn't have to be called if the external library
|
||||
* // provides its own allocator, but in this case it will have to
|
||||
* // implement all functions.
|
||||
* void *ptr = orig->malloc(size);
|
||||
* // Do whatever you want with the ptr.
|
||||
* return ptr;
|
||||
* }
|
||||
*
|
||||
* where "orig" is the pointer obtained from replace_init.
|
||||
*
|
||||
* See malloc_decls.h for a list of functions that can be replaced this
|
||||
* way. The implementations are all in the form:
|
||||
* return_type replace_name(arguments [,...])
|
||||
*
|
||||
* They don't all need to be provided.
|
||||
*
|
||||
* Building a replace-malloc library is like rocket science. It can end up
|
||||
* with things blowing up, especially when trying to use complex types, and
|
||||
* even more especially when these types come from XPCOM or other parts of the
|
||||
* Mozilla codebase.
|
||||
* It is recommended to add the following to a replace-malloc implementation's
|
||||
* Makefile.in:
|
||||
* MOZ_GLUE_LDFLAGS = # Don't link against mozglue
|
||||
* WRAP_LDFLAGS = # Never wrap malloc function calls with -Wl,--wrap
|
||||
* STL_FLAGS = # Avoid STL wrapping
|
||||
*
|
||||
* If your replace-malloc implementation lives under memory/replace, these
|
||||
* are taken care of by memory/replace/defs.mk.
|
||||
*/
|
||||
|
||||
/* Implementing a replace-malloc library is incompatible with using mozalloc. */
|
||||
#define MOZ_NO_MOZALLOC 1
|
||||
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
MOZ_BEGIN_EXTERN_C
|
||||
|
||||
#define MALLOC_DECL(name, return_type, ...) \
|
||||
typedef return_type(name ## _impl_t)(__VA_ARGS__);
|
||||
|
||||
#include "malloc_decls.h"
|
||||
|
||||
#define MALLOC_DECL(name, return_type, ...) \
|
||||
name ## _impl_t * name;
|
||||
|
||||
typedef struct {
|
||||
#include "malloc_decls.h"
|
||||
} malloc_table_t;
|
||||
|
||||
|
||||
/* MOZ_NO_REPLACE_FUNC_DECL and MOZ_REPLACE_WEAK are only defined in
|
||||
* replace_malloc.c. Normally including this header will add function
|
||||
* definitions. */
|
||||
#ifndef MOZ_NO_REPLACE_FUNC_DECL
|
||||
|
||||
# ifndef MOZ_REPLACE_WEAK
|
||||
# define MOZ_REPLACE_WEAK
|
||||
# endif
|
||||
|
||||
# define MALLOC_DECL(name, return_type, ...) \
|
||||
MOZ_EXPORT return_type replace_ ## name(__VA_ARGS__) MOZ_REPLACE_WEAK;
|
||||
|
||||
# define MALLOC_FUNCS MALLOC_FUNCS_ALL
|
||||
# include "malloc_decls.h"
|
||||
|
||||
#endif /* MOZ_NO_REPLACE_FUNC_DECL */
|
||||
|
||||
/*
|
||||
* posix_memalign, aligned_alloc, memalign and valloc all implement some
|
||||
* kind of aligned memory allocation. For convenience, replace_posix_memalign,
|
||||
* replace_aligned_alloc and replace_valloc can be automatically derived from
|
||||
* memalign when MOZ_REPLACE_ONLY_MEMALIGN is defined before including this
|
||||
* header. PAGE_SIZE also needs to be defined to the appropriate expression.
|
||||
*/
|
||||
#ifdef MOZ_REPLACE_ONLY_MEMALIGN
|
||||
#include <errno.h>
|
||||
|
||||
int replace_posix_memalign(void **ptr, size_t alignment, size_t size)
|
||||
{
|
||||
if (size == 0) {
|
||||
*ptr = NULL;
|
||||
return 0;
|
||||
}
|
||||
/* alignment must be a power of two and a multiple of sizeof(void *) */
|
||||
if (((alignment - 1) & alignment) != 0 || (alignment % sizeof(void *)))
|
||||
return EINVAL;
|
||||
*ptr = replace_memalign(alignment, size);
|
||||
return *ptr ? 0 : ENOMEM;
|
||||
}
|
||||
|
||||
void *replace_aligned_alloc(size_t alignment, size_t size)
|
||||
{
|
||||
/* size should be a multiple of alignment */
|
||||
if (size % alignment)
|
||||
return NULL;
|
||||
return replace_memalign(alignment, size);
|
||||
}
|
||||
|
||||
void *replace_valloc(size_t size)
|
||||
{
|
||||
return replace_memalign(PAGE_SIZE, size);
|
||||
}
|
||||
#endif
|
||||
|
||||
MOZ_END_EXTERN_C
|
||||
|
||||
#endif /* replace_malloc_h */
|
|
@ -20,7 +20,9 @@ DIST_INSTALL = 1
|
|||
endif
|
||||
|
||||
CSRCS := $(notdir $(wildcard $(srcdir)/src/src/*.c))
|
||||
ifneq ($(OS_TARGET),Darwin)
|
||||
# Only OSX needs the zone allocation implementation, but only if
|
||||
# replace-malloc is not enabled.
|
||||
ifneq ($(OS_TARGET)$(MOZ_REPLACE_MALLOC),Darwin)
|
||||
CSRCS := $(filter-out zone.c,$(CSRCS))
|
||||
endif
|
||||
|
||||
|
|
|
@ -44,6 +44,10 @@ endif
|
|||
|
||||
DEFINES += -Dabort=moz_abort
|
||||
|
||||
DEFINES += -DMOZ_MEMORY_IMPL
|
||||
ifdef MOZ_REPLACE_MALLOC
|
||||
DEFINES += -DMOZ_REPLACE_MALLOC
|
||||
endif
|
||||
|
||||
DEFINES += -DMOZ_JEMALLOC_IMPL
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -1472,6 +1472,7 @@ static void _malloc_postfork(void);
|
|||
* of malloc_zone_t adapted into osx_zone_types.h.
|
||||
*/
|
||||
|
||||
#ifndef MOZ_REPLACE_MALLOC
|
||||
#include "osx_zone_types.h"
|
||||
|
||||
#define LEOPARD_MALLOC_ZONE_T_VERSION 3
|
||||
|
@ -1489,6 +1490,10 @@ static malloc_introspection_t * const ozone_introspect =
|
|||
(malloc_introspection_t*)(&l_ozone_introspect);
|
||||
static void szone2ozone(malloc_zone_t *zone, size_t size);
|
||||
static size_t zone_version_size(int version);
|
||||
#else
|
||||
static const bool osx_use_jemalloc = true;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@ -6176,7 +6181,7 @@ MALLOC_OUT:
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_MEMORY_DARWIN
|
||||
#if defined(MOZ_MEMORY_DARWIN) && !defined(MOZ_REPLACE_MALLOC)
|
||||
/*
|
||||
* Overwrite the default memory allocator to use jemalloc everywhere.
|
||||
*/
|
||||
|
@ -6255,7 +6260,7 @@ malloc_shutdown()
|
|||
*
|
||||
* This means that NO_MAC_JEMALLOC doesn't work on i386.
|
||||
*/
|
||||
#if defined(MOZ_MEMORY_DARWIN) && !defined(__i386__)
|
||||
#if defined(MOZ_MEMORY_DARWIN) && !defined(__i386__) && !defined(MOZ_REPLACE_MALLOC)
|
||||
#define DARWIN_ONLY(A) if (!osx_use_jemalloc) { A; }
|
||||
#else
|
||||
#define DARWIN_ONLY(A)
|
||||
|
@ -6316,6 +6321,7 @@ RETURN:
|
|||
* Exported Symbols) in http://www.akkadia.org/drepper/dsohowto.pdf.
|
||||
*/
|
||||
|
||||
#ifndef MOZ_REPLACE_MALLOC
|
||||
#if defined(__GNUC__) && !defined(MOZ_MEMORY_DARWIN)
|
||||
#define MOZ_MEMORY_ELF
|
||||
#endif
|
||||
|
@ -6333,7 +6339,7 @@ __attribute__((noinline))
|
|||
__attribute__((visibility ("hidden")))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* MOZ_REPLACE_MALLOC */
|
||||
|
||||
#ifdef MOZ_MEMORY_ELF
|
||||
#define MEMALIGN memalign_internal
|
||||
|
@ -6594,7 +6600,7 @@ free_impl(void *ptr)
|
|||
*/
|
||||
|
||||
/* This was added by Mozilla for use by SQLite. */
|
||||
#ifdef MOZ_MEMORY_DARWIN
|
||||
#if defined(MOZ_MEMORY_DARWIN) && !defined(MOZ_REPLACE_MALLOC)
|
||||
static
|
||||
#else
|
||||
MOZ_MEMORY_API
|
||||
|
@ -6935,8 +6941,9 @@ _malloc_postfork(void)
|
|||
# include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_MEMORY_DARWIN
|
||||
#if defined(MOZ_MEMORY_DARWIN)
|
||||
|
||||
#if !defined(MOZ_REPLACE_MALLOC)
|
||||
static void *
|
||||
zone_malloc(malloc_zone_t *zone, size_t size)
|
||||
{
|
||||
|
@ -7156,6 +7163,7 @@ szone2ozone(malloc_zone_t *default_zone, size_t size)
|
|||
l_ozone_introspect.m13 = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
__attribute__((constructor))
|
||||
void
|
||||
|
@ -7165,7 +7173,18 @@ jemalloc_darwin_init(void)
|
|||
abort();
|
||||
}
|
||||
|
||||
#elif defined(__GLIBC__) && !defined(__UCLIBC__)
|
||||
#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(MOZ_MEMORY_DARWIN) && (is_malloc(malloc_impl) == 1)
|
||||
# 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
|
||||
|
@ -7175,18 +7194,19 @@ jemalloc_darwin_init(void)
|
|||
* passed an extra argument for the caller return address, which will be
|
||||
* ignored.
|
||||
*/
|
||||
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 (*__free_hook)(void *ptr) = free_impl;
|
||||
MOZ_MEMORY_API void *(*__malloc_hook)(size_t size) = malloc_impl;
|
||||
MOZ_MEMORY_API void *(*__realloc_hook)(void *ptr, size_t size) = realloc_impl;
|
||||
MOZ_MEMORY_API void *(*__memalign_hook)(size_t alignment, size_t size) = MEMALIGN;
|
||||
|
||||
#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."
|
||||
# error "Interposing malloc is unsafe on this system without libc malloc hooks."
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_MEMORY_WINDOWS
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
MOZ_GLUE_LDFLAGS = # Don't link against mozglue
|
||||
WRAP_LDFLAGS = # Never wrap malloc function calls with -Wl,--wrap
|
||||
STL_FLAGS = # Avoid STL wrapping
|
|
@ -0,0 +1,19 @@
|
|||
# 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
|
||||
|
||||
MODULE = memory
|
||||
LIBRARY_NAME = replace_malloc
|
||||
FORCE_SHARED_LIB = 1
|
||||
NO_DIST_INSTALL = 1
|
||||
|
||||
CSRCS = dummy_replace_malloc.c
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
|
@ -0,0 +1,15 @@
|
|||
/* 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 "mozilla/Types.h"
|
||||
|
||||
/*
|
||||
* Dummy functions for linking purpose on OSX with older XCode.
|
||||
* See details in configure.in, under "Replace-malloc Mac linkage quirks"
|
||||
*/
|
||||
#define MALLOC_FUNCS MALLOC_FUNCS_ALL
|
||||
#define MALLOC_DECL(name, ...) \
|
||||
MOZ_EXPORT void replace_ ## name() { }
|
||||
|
||||
#include "malloc_decls.h"
|
|
@ -48,7 +48,7 @@ ifeq (WINNT,$(OS_TARGET))
|
|||
DEFFILE = mozglue.def
|
||||
|
||||
mozglue.def: mozglue.def.in
|
||||
$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(ACDEFINES) $< > $@
|
||||
$(PYTHON) $(topsrcdir)/config/Preprocessor.py $(if $(MOZ_REPLACE_MALLOC),-DMOZ_REPLACE_MALLOC) $(ACDEFINES) $< > $@
|
||||
|
||||
GARBAGE += mozglue.def
|
||||
|
||||
|
@ -60,6 +60,32 @@ endif
|
|||
EXTRA_DSO_LDOPTS += $(MOZ_ZLIB_LIBS)
|
||||
endif
|
||||
|
||||
ifeq (Darwin_1,$(OS_TARGET)_$(MOZ_REPLACE_MALLOC))
|
||||
EXTRA_DSO_LDOPTS += \
|
||||
-Wl,-U,_replace_init \
|
||||
-Wl,-U,_replace_malloc \
|
||||
-Wl,-U,_replace_posix_memalign \
|
||||
-Wl,-U,_replace_aligned_alloc \
|
||||
-Wl,-U,_replace_calloc \
|
||||
-Wl,-U,_replace_realloc \
|
||||
-Wl,-U,_replace_free \
|
||||
-Wl,-U,_replace_memalign \
|
||||
-Wl,-U,_replace_valloc \
|
||||
-Wl,-U,_replace_malloc_usable_size \
|
||||
-Wl,-U,_replace_malloc_good_size \
|
||||
-Wl,-U,_replace_jemalloc_stats \
|
||||
-Wl,-U,_replace_jemalloc_purge_freed_pages \
|
||||
-Wl,-U,_replace_jemalloc_free_dirty_pages \
|
||||
$(NULL)
|
||||
|
||||
ifneq ($(MOZ_REPLACE_MALLOC_LINKAGE),compiler support)
|
||||
EXTRA_DSO_LDOPTS += -flat_namespace
|
||||
endif
|
||||
ifeq ($(MOZ_REPLACE_MALLOC_LINKAGE),dummy library)
|
||||
EXTRA_DSO_LDOPTS += -Wl,-weak_library,$(DEPTH)/memory/replace/dummy/$(DLL_PREFIX)replace_malloc$(DLL_SUFFIX)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq (Android,$(OS_TARGET))
|
||||
CPPSRCS += BionicGlue.cpp
|
||||
SHARED_LIBRARY_LIBS += $(call EXPAND_LIBNAME_PATH,android,$(DEPTH)/other-licenses/android)
|
||||
|
|
|
@ -7,6 +7,15 @@ 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
|
||||
#else
|
||||
malloc=je_malloc
|
||||
calloc=je_calloc
|
||||
realloc=je_realloc
|
||||
|
@ -14,6 +23,7 @@ EXPORTS
|
|||
posix_memalign=je_posix_memalign
|
||||
malloc_usable_size=je_malloc_usable_size
|
||||
malloc_good_size=je_malloc_good_size
|
||||
#endif
|
||||
strndup=wrap_strndup
|
||||
strdup=wrap_strdup
|
||||
_strdup=wrap_strdup
|
||||
|
|
Загрузка…
Ссылка в новой задаче