diff options
Diffstat (limited to 'memory/build/jemalloc_config.cpp')
-rw-r--r-- | memory/build/jemalloc_config.cpp | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/memory/build/jemalloc_config.cpp b/memory/build/jemalloc_config.cpp new file mode 100644 index 000000000..441fd8a2b --- /dev/null +++ b/memory/build/jemalloc_config.cpp @@ -0,0 +1,164 @@ +/* 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/. */ + +#ifdef MOZ_JEMALLOC4 + +#define MOZ_JEMALLOC_IMPL + +/* mozmemory_wrap.h needs to be included before MFBT headers */ +#include "mozmemory_wrap.h" +#include <mozilla/Assertions.h> +#include "mozilla/Types.h" + +#if defined(MOZ_SYSTEM_JEMALLOC) +#include MALLOC_H +#else +#define DLLEXPORT +#include "jemalloc/jemalloc.h" +#endif + +#ifdef XP_WIN +#include <windows.h> +#endif +#ifdef XP_DARWIN +#include <sys/mman.h> +#endif + +/* Override some jemalloc defaults */ +#ifdef DEBUG +#define MOZ_MALLOC_BUILD_OPTIONS ",junk:true" +#else +#define MOZ_MALLOC_BUILD_OPTIONS ",junk:free" +#endif + +#define MOZ_MALLOC_OPTIONS "narenas:1,tcache:false" +MFBT_DATA const char* je_(malloc_conf) = + MOZ_MALLOC_OPTIONS MOZ_MALLOC_BUILD_OPTIONS; + +#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 + +/* Jemalloc supports hooks that are called on chunk + * allocate/deallocate/commit/decommit/purge/etc. + * + * We currently only hook commit, decommit and purge. We do this to tweak + * the way chunks are handled so that RSS stays lower than it normally + * would with the default jemalloc uses. + * This somewhat matches the behavior of mozjemalloc, except it doesn't + * rely on a double purge on mac, instead purging directly. (Yes, this + * means we can get rid of jemalloc_purge_freed_pages at some point) + * + * The default for jemalloc is to do the following: + * - commit, decommit: nothing + * - purge: MEM_RESET on Windows, MADV_FREE on Mac/BSD, MADV_DONTNEED on Linux + * + * The hooks we setup do the following: + * on Windows: + * - commit: MEM_COMMIT + * - decommit: MEM_DECOMMIT + * on Mac: + * - purge: mmap new anonymous memory on top of the chunk + * + * We only set the above hooks, others are left with the default. + */ +#if defined(XP_WIN) || defined(XP_DARWIN) +class JemallocInit { +public: + JemallocInit() + { + chunk_hooks_t hooks; + size_t hooks_len; + unsigned narenas; + size_t mib[3]; + size_t size; + + size = sizeof(narenas); + je_(mallctl)("arenas.narenas", &narenas, &size, nullptr, 0); + + size = sizeof(mib) / sizeof(mib[0]); + je_(mallctlnametomib)("arena.0.chunk_hooks", mib, &size); + + /* Set the hooks on all the existing arenas. */ + for (unsigned arena = 0; arena < narenas; arena++) { + mib[1] = arena; + hooks_len = sizeof(hooks); + je_(mallctlbymib)(mib, size, &hooks, &hooks_len, nullptr, 0); + +#ifdef XP_WIN + hooks.commit = CommitHook; + hooks.decommit = DecommitHook; +#endif +#ifdef XP_DARWIN + hooks.purge = PurgeHook; +#endif + + je_(mallctlbymib)(mib, size, nullptr, nullptr, &hooks, hooks_len); + } + } + +private: +#ifdef XP_WIN + static bool + CommitHook(void* chunk, size_t size, size_t offset, size_t length, + unsigned arena_ind) + { + void* addr = reinterpret_cast<void*>( + reinterpret_cast<uintptr_t>(chunk) + static_cast<uintptr_t>(offset)); + + if (!VirtualAlloc(addr, length, MEM_COMMIT, PAGE_READWRITE)) + return true; + + return false; + } + + static bool + DecommitHook(void* chunk, size_t size, size_t offset, size_t length, + unsigned arena_ind) + { + void* addr = reinterpret_cast<void*>( + reinterpret_cast<uintptr_t>(chunk) + static_cast<uintptr_t>(offset)); + + if (!VirtualFree(addr, length, MEM_DECOMMIT)) + MOZ_CRASH(); + + return false; + } +#endif + +#ifdef XP_DARWIN + static bool + PurgeHook(void* chunk, size_t size, size_t offset, size_t length, + unsigned arena_ind) + { + void* addr = reinterpret_cast<void*>( + reinterpret_cast<uintptr_t>(chunk) + static_cast<uintptr_t>(offset)); + + void* new_addr = mmap(addr, length, PROT_READ | PROT_WRITE, + MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0); + return (new_addr != addr); + } +#endif +}; + +/* For the static constructor from the class above */ +JemallocInit gJemallocInit; +#endif + +#else +#include <mozilla/Assertions.h> +#endif /* MOZ_JEMALLOC4 */ + +/* Provide an abort function for use in jemalloc code */ +extern "C" void moz_abort() { + MOZ_CRASH(); +} |