1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* 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 mozjemalloc_h
#define mozjemalloc_h
#include <errno.h>
#include "mozjemalloc_types.h"
#include "malloc_decls.h"
#include "mozilla/MacroArgs.h"
// Macro helpers
#define MACRO_CALL(a, b) a b
// Can't use macros recursively, so we need another one doing the same as above.
#define MACRO_CALL2(a, b) a b
#define ARGS_HELPER(name, ...) \
MACRO_CALL2(MOZ_PASTE_PREFIX_AND_ARG_COUNT(name, ##__VA_ARGS__), \
(__VA_ARGS__))
#define TYPED_ARGS0()
#define TYPED_ARGS1(t1) t1 arg1
#define TYPED_ARGS2(t1, t2) TYPED_ARGS1(t1), t2 arg2
#define TYPED_ARGS3(t1, t2, t3) TYPED_ARGS2(t1, t2), t3 arg3
#define ARGS0()
#define ARGS1(t1) arg1
#define ARGS2(t1, t2) ARGS1(t1), arg2
#define ARGS3(t1, t2, t3) ARGS2(t1, t2), arg3
#ifdef MOZ_MEMORY
size_t GetKernelPageSize();
// Implement the set of alignment functions in terms of memalign.
template <void* (*memalign)(size_t, size_t)>
struct AlignedAllocator {
static inline int posix_memalign(void** aMemPtr, size_t aAlignment,
size_t aSize) {
void* result;
// alignment must be a power of two and a multiple of sizeof(void*)
if (((aAlignment - 1) & aAlignment) != 0 || aAlignment < sizeof(void*)) {
return EINVAL;
}
// The 0-->1 size promotion is done in the memalign() call below
result = memalign(aAlignment, aSize);
if (!result) {
return ENOMEM;
}
*aMemPtr = result;
return 0;
}
static inline void* aligned_alloc(size_t aAlignment, size_t aSize) {
if (aSize % aAlignment) {
return nullptr;
}
return memalign(aAlignment, aSize);
}
static inline void* valloc(size_t aSize) {
return memalign(GetKernelPageSize(), aSize);
}
};
// These classes each implement the same interface. Writing out the
// interface for each one rather than using inheritance makes things more
// explicit.
//
// Note: compilers are expected to be able to optimize out `this`.
// The MozJemalloc allocator
struct MozJemalloc {
# define MALLOC_DECL(name, return_type, ...) \
static inline return_type name(__VA_ARGS__);
# include "malloc_decls.h"
};
# ifdef MOZ_PHC
struct MozJemallocPHC : public MozJemalloc {
# define MALLOC_DECL(name, return_type, ...) \
static return_type name(__VA_ARGS__);
# define MALLOC_FUNCS MALLOC_FUNCS_MALLOC_BASE
# include "malloc_decls.h"
static inline int posix_memalign(void** aMemPtr, size_t aAlignment,
size_t aSize) {
return AlignedAllocator<memalign>::posix_memalign(aMemPtr, aAlignment,
aSize);
}
static inline void* aligned_alloc(size_t aAlignment, size_t aSize) {
return AlignedAllocator<memalign>::aligned_alloc(aAlignment, aSize);
}
static inline void* valloc(size_t aSize) {
return AlignedAllocator<memalign>::valloc(aSize);
}
static size_t malloc_usable_size(usable_ptr_t);
static void jemalloc_stats_internal(jemalloc_stats_t*, jemalloc_bin_stats_t*);
static void jemalloc_stats_lite(jemalloc_stats_lite_t*);
static void jemalloc_ptr_info(const void*, jemalloc_ptr_info_t*);
# define MALLOC_DECL(name, return_type, ...) \
static return_type name(__VA_ARGS__);
# define MALLOC_FUNCS MALLOC_FUNCS_ARENA_ALLOC
# include "malloc_decls.h"
};
# endif
# ifdef MOZ_REPLACE_MALLOC
// The replace-malloc allocator
struct ReplaceMalloc {
# define MALLOC_DECL(name, return_type, ...) \
static return_type name(__VA_ARGS__);
# include "malloc_decls.h"
};
# endif
# ifdef MOZ_PHC
using CanonicalMalloc = MozJemallocPHC;
# else
using CanonicalMalloc = MozJemalloc;
# endif
# ifdef MOZ_REPLACE_MALLOC
using DefaultMalloc = ReplaceMalloc;
# else
using DefaultMalloc = CanonicalMalloc;
# endif
// Poison - write "poison" to cells upon deallocation.
constexpr uint8_t kAllocPoison = 0xe5;
// Junk - write this junk value to freshly allocated cells.
constexpr uint8_t kAllocJunk = 0xe4;
#endif // MOZ_MEMORY
// Dummy implementation of the moz_arena_* API, falling back to a given
// implementation of the base allocator.
template <typename T>
struct DummyArenaAllocator {
static arena_id_t moz_create_arena_with_params(arena_params_t*) { return 0; }
static void moz_dispose_arena(arena_id_t) {}
static void moz_set_max_dirty_page_modifier(int32_t) {}
static bool moz_enable_deferred_purge(bool aEnable) { return false; }
static may_purge_now_result_t moz_may_purge_now(
bool aPeekOnly, uint32_t aReuseGraceMS,
const mozilla::Maybe<std::function<bool()>>& aKeepGoing) {
return may_purge_now_result_t::Done;
}
#define MALLOC_DECL(name, return_type, ...) \
static return_type moz_arena_##name( \
arena_id_t, ARGS_HELPER(TYPED_ARGS, ##__VA_ARGS__)) { \
return T::name(ARGS_HELPER(ARGS, ##__VA_ARGS__)); \
}
#define MALLOC_FUNCS MALLOC_FUNCS_MALLOC_BASE
#include "malloc_decls.h"
};
#endif
|