tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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