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