summaryrefslogtreecommitdiffstats
path: root/memory/build/jemalloc_config.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'memory/build/jemalloc_config.cpp')
-rw-r--r--memory/build/jemalloc_config.cpp164
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();
+}