/* 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 GLOBALS_H #define GLOBALS_H // This file contains compile-time constants that depend on sizes of structures // or the page size. Page size isn't always known at compile time so some // values defined here may be determined at runtime. #include "mozilla/Literals.h" #include "Constants.h" // Chunk.h is required for sizeof(arena_chunk_t), but it's inconvenient that // Chunk.h can't access any constants. #include "Chunk.h" #include "Mutex.h" #include "Utils.h" // Define MALLOC_RUNTIME_CONFIG depending on MOZ_DEBUG. Overriding this as // a build option allows us to build mozjemalloc/firefox without runtime asserts // but with runtime configuration. Making some testing easier. #ifdef MOZ_DEBUG # define MALLOC_RUNTIME_CONFIG #endif // Uncomment this to enable extra-vigilant assertions. These assertions may run // more expensive checks that are sometimes too slow for regular debug mode. // #define MALLOC_DEBUG_VIGILANT // When MALLOC_STATIC_PAGESIZE is defined, the page size is fixed at // compile-time for better performance, as opposed to determined at // runtime. Some platforms can have different page sizes at runtime // depending on kernel configuration, so they are opted out by default. // Debug builds are opted out too, for test coverage. #ifndef MALLOC_RUNTIME_CONFIG # if !defined(XP_MACOSX) && !defined(ANDROID) && !defined(__ia64__) && \ !defined(__sparc__) && !defined(__mips__) && !defined(__aarch64__) && \ !defined(__powerpc__) && !defined(__loongarch__) # define MALLOC_STATIC_PAGESIZE 1 # endif #endif namespace mozilla { // mozjemalloc has two values for page size. // // gPageSize: A logical page size used for mozjemalloc's own structures. // gRealPageSize The actual page size used by the OS & Hardware. // // They can be different so that we can continue to use 4KB pages on systems // with a larger page size. (WIP see Bug 1980047). // // On x86-64 they are both 4KiB. However Apple Silicon has a 16KiB page size, // so gRealPageSize will be 16KiB, but in order to keep the number of // regions-per-run to 256 we want to limit gPageSize to 4KiB. (4096 / 16 = // 256). Other platforms with different gRealPageSizes might also have // different gRealPageSize and gPageSize. // // gPageSize is always less than or equal to gRealPageSize. // #ifdef MALLOC_STATIC_PAGESIZE // Platform specific page size conditions copied from js/public/HeapAPI.h # if defined(__powerpc64__) static const size_t gRealPageSize = 64_KiB; # elif defined(__loongarch64) static const size_t gRealPageSize = 16_KiB; # else static const size_t gRealPageSize = 4_KiB; # endif static const size_t gPageSize = 4_KiB; #else // When MALLOC_OPTIONS contains one or several `P`s, gPageSize will be // doubled for each `P`. Likewise each 'p' will halve gPageSize. extern size_t gRealPageSize; extern size_t gPageSize; #endif // Return the smallest pagesize multiple that is >= s. #define PAGE_CEILING(s) \ (((s) + mozilla::gPageSizeMask) & ~mozilla::gPageSizeMask) #define REAL_PAGE_CEILING(s) (((s) + gRealPageSizeMask) & ~gRealPageSizeMask) #define PAGES_PER_REAL_PAGE_CEILING(s) \ (((s) + gPagesPerRealPage - 1) & ~(gPagesPerRealPage - 1)) #ifdef MALLOC_STATIC_PAGESIZE # define GLOBAL(type, name, value) static const type name = value; # define GLOBAL_LOG2 LOG2 # define GLOBAL_ASSERT_HELPER1(x) static_assert(x, #x) # define GLOBAL_ASSERT_HELPER2(x, y) static_assert(x, y) # define GLOBAL_ASSERT(...) \ \ MOZ_PASTE_PREFIX_AND_ARG_COUNT(GLOBAL_ASSERT_HELPER, __VA_ARGS__) \ (__VA_ARGS__) # define GLOBAL_CONSTEXPR constexpr # include "Globals.inc" # undef GLOBAL_CONSTEXPR # undef GLOBAL_ASSERT # undef GLOBAL_ASSERT_HELPER1 # undef GLOBAL_ASSERT_HELPER2 # undef GLOBAL_LOG2 # undef GLOBAL #else // We declare the globals here and initialise them in DefineGlobals() # define GLOBAL(type, name, value) extern type name; # define GLOBAL_ASSERT(...) # include "Globals.inc" # undef GLOBAL_ASSERT # undef GLOBAL void DefineGlobals(); #endif // Max size class for bins. #define gMaxBinClass (kMaxQuantumWideClass) // Return the smallest chunk multiple that is >= s. #define CHUNK_CEILING(s) (((s) + kChunkSizeMask) & ~kChunkSizeMask) // Return the smallest cacheline multiple that is >= s. #define CACHELINE_CEILING(s) \ (((s) + (kCacheLineSize - 1)) & ~(kCacheLineSize - 1)) // Return the smallest quantum multiple that is >= a. #define QUANTUM_CEILING(a) (((a) + (kQuantumMask)) & ~(kQuantumMask)) #define QUANTUM_WIDE_CEILING(a) \ (((a) + (kQuantumWideMask)) & ~(kQuantumWideMask)) // Number of all the small-allocated classes #define NUM_SMALL_CLASSES (kNumQuantumClasses + kNumQuantumWideClasses) // Return the chunk address for allocation address a. static inline arena_chunk_t* GetChunkForPtr(const void* aPtr) { return (arena_chunk_t*)(uintptr_t(aPtr) & ~kChunkSizeMask); } // Return the chunk offset of address a. static inline size_t GetChunkOffsetForPtr(const void* aPtr) { return (size_t)(uintptr_t(aPtr) & kChunkSizeMask); } // Maximum number of dirty pages per arena. #define DIRTY_MAX_DEFAULT (1U << 8) enum PoisonType { NONE, SOME, ALL, }; extern size_t opt_dirty_max; #define OPT_JUNK_DEFAULT false #define OPT_ZERO_DEFAULT false #ifdef EARLY_BETA_OR_EARLIER # define OPT_POISON_DEFAULT ALL #else # define OPT_POISON_DEFAULT SOME #endif // Keep this larger than and ideally a multiple of kCacheLineSize; #define OPT_POISON_SIZE_DEFAULT 256 #ifdef MALLOC_RUNTIME_CONFIG extern bool opt_junk; extern bool opt_zero; extern PoisonType opt_poison; extern size_t opt_poison_size; #else constexpr bool opt_junk = OPT_JUNK_DEFAULT; constexpr bool opt_zero = OPT_ZERO_DEFAULT; constexpr PoisonType opt_poison = OPT_POISON_DEFAULT; constexpr size_t opt_poison_size = OPT_POISON_SIZE_DEFAULT; static_assert(opt_poison_size >= kCacheLineSize); static_assert((opt_poison_size % kCacheLineSize) == 0); #endif extern bool opt_randomize_small; } // namespace mozilla #endif // ! GLOBALS_H