Bug 1414155 - Consolidate "constant/globals". r=njn
authorMike Hommey <mh+mozilla@glandium.org>
Wed, 01 Nov 2017 18:33:24 +0900
changeset 443490 5bd88f059878634b15bc89787c9bf5ebb96c669b
parent 443489 fb8fa3f4449c6a215d8f69410829930d4d271882
child 443491 f6799dfca63cab9d29ac2443d9a93504f88a2afb
push id1618
push userCallek@gmail.com
push dateThu, 11 Jan 2018 17:45:48 +0000
treeherdermozilla-release@882ca853e05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnjn
bugs1414155
milestone58.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1414155 - Consolidate "constant/globals". r=njn There is a set of "constants" that are actually globals that depend on the page size that we get at runtime, when compiling without MALLOC_STATIC_PAGESIZE, but that are actual constants when compiling with it. Their value was unfortunately duplicated. We setup a set of macros allowing to make the declarations unique.
memory/build/mozjemalloc.cpp
--- a/memory/build/mozjemalloc.cpp
+++ b/memory/build/mozjemalloc.cpp
@@ -169,16 +169,28 @@ using namespace mozilla;
 #ifdef XP_DARWIN
 #define MALLOC_DOUBLE_PURGE
 #endif
 
 #ifdef XP_WIN
 #define MALLOC_DECOMMIT
 #endif
 
+// 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 MOZ_DEBUG
+#if !defined(__ia64__) && !defined(__sparc__) && !defined(__mips__) &&         \
+  !defined(__aarch64__)
+#define MALLOC_STATIC_PAGESIZE 1
+#endif
+#endif
+
 #ifdef XP_WIN
 #define STDERR_FILENO 2
 
 // Implement getenv without using malloc.
 static char mozillaMallocOptionsBuf[64];
 
 #define getenv xgetenv
 static char*
@@ -383,108 +395,117 @@ struct arena_chunk_t
 #endif
 
 // Maximum size class that is a multiple of the quantum, but not (necessarily)
 // a power of 2.  Above this size, allocations are rounded up to the nearest
 // power of 2.
 #define SMALL_MAX_2POW_DEFAULT 9
 #define SMALL_MAX_DEFAULT (1U << SMALL_MAX_2POW_DEFAULT)
 
-// 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 MOZ_DEBUG
-#if !defined(__ia64__) && !defined(__sparc__) && !defined(__mips__) &&         \
-  !defined(__aarch64__)
-#define MALLOC_STATIC_PAGESIZE 1
-#endif
-#endif
-
 // Various quantum-related settings.
 #define QUANTUM_DEFAULT (size_t(1) << QUANTUM_2POW_MIN)
 static const size_t quantum = QUANTUM_DEFAULT;
 static const size_t quantum_mask = QUANTUM_DEFAULT - 1;
 
 // Various bin-related settings.
 static const size_t small_min = (QUANTUM_DEFAULT >> 1) + 1;
 static const size_t small_max = size_t(SMALL_MAX_DEFAULT);
 
 // Number of (2^n)-spaced tiny bins.
 static const unsigned ntbins = unsigned(QUANTUM_2POW_MIN - TINY_MIN_2POW);
 
 // Number of quantum-spaced bins.
 static const unsigned nqbins = unsigned(SMALL_MAX_DEFAULT >> QUANTUM_2POW_MIN);
 
+#define CHUNKSIZE_DEFAULT ((size_t)1 << CHUNK_2POW_DEFAULT)
+static const size_t chunksize = CHUNKSIZE_DEFAULT;
+static const size_t chunksize_mask = CHUNKSIZE_DEFAULT - 1;
+
 #ifdef MALLOC_STATIC_PAGESIZE
-
 // VM page size. It must divide the runtime CPU page size or the code
 // will abort.
 // Platform specific page size conditions copied from js/public/HeapAPI.h
 #if (defined(SOLARIS) || defined(__FreeBSD__)) &&                              \
   (defined(__sparc) || defined(__sparcv9) || defined(__ia64))
 static const size_t pagesize = 8_KiB;
 #elif defined(__powerpc64__)
 static const size_t pagesize = 64_KiB;
 #else
 static const size_t pagesize = 4_KiB;
 #endif
-#define pagesize_2pow LOG2(pagesize)
-#define pagesize_mask (pagesize - 1)
-
-// Max size class for bins.
-static const size_t bin_maxclass = pagesize >> 1;
+
+#else
+static size_t pagesize;
+#endif
+
+#ifdef MALLOC_STATIC_PAGESIZE
+#define DECLARE_GLOBAL(type, name)
+#define DEFINE_GLOBALS
+#define END_GLOBALS
+#define DEFINE_GLOBAL(type) static const type
+#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(...)                                                     \
+  MACRO_CALL(                                                                  \
+    MOZ_PASTE_PREFIX_AND_ARG_COUNT(GLOBAL_ASSERT_HELPER, __VA_ARGS__),         \
+    (__VA_ARGS__))
+#else
+#define DECLARE_GLOBAL(type, name) static type name;
+#define DEFINE_GLOBALS                                                         \
+  static void DefineGlobals()                                                  \
+  {
+#define END_GLOBALS }
+#define DEFINE_GLOBAL(type)
+#define GLOBAL_LOG2 FloorLog2
+#define GLOBAL_ASSERT MOZ_RELEASE_ASSERT
+#endif
+
+DECLARE_GLOBAL(size_t, pagesize_mask)
+DECLARE_GLOBAL(uint8_t, pagesize_2pow)
+DECLARE_GLOBAL(uint8_t, nsbins)
+DECLARE_GLOBAL(size_t, bin_maxclass)
+DECLARE_GLOBAL(size_t, chunk_npages)
+DECLARE_GLOBAL(size_t, arena_chunk_header_npages)
+DECLARE_GLOBAL(size_t, arena_maxclass)
+
+DEFINE_GLOBALS
+DEFINE_GLOBAL(size_t) pagesize_mask = pagesize - 1;
+DEFINE_GLOBAL(uint8_t) pagesize_2pow = GLOBAL_LOG2(pagesize);
 
 // Number of (2^n)-spaced sub-page bins.
-static const unsigned nsbins =
-  unsigned(pagesize_2pow - SMALL_MAX_2POW_DEFAULT - 1);
-
-#else // !MALLOC_STATIC_PAGESIZE
-
-// VM page size.
-static size_t pagesize;
-static size_t pagesize_mask;
-static size_t pagesize_2pow;
-
-// Various bin-related settings.
-static size_t bin_maxclass; // Max size class for bins.
-static unsigned nsbins;     // Number of (2^n)-spaced sub-page bins.
-#endif
-
-// Various chunk-related settings.
-
-// Compute the header size such that it is large enough to contain the page map
-// and enough nodes for the worst case: one node per non-header page plus one
-// extra for situations where we briefly have one more node allocated than we
-// will need.
-#define calculate_arena_header_size()                                          \
-  (sizeof(arena_chunk_t) + sizeof(arena_chunk_map_t) * (chunk_npages - 1))
-
-#define calculate_arena_header_pages()                                         \
-  ((calculate_arena_header_size() >> pagesize_2pow) +                          \
-   ((calculate_arena_header_size() & pagesize_mask) ? 1 : 0))
+DEFINE_GLOBAL(uint8_t)
+nsbins = pagesize_2pow - SMALL_MAX_2POW_DEFAULT - 1;
+
+// Max size class for bins.
+DEFINE_GLOBAL(size_t) bin_maxclass = pagesize >> 1;
+
+// Number of pages in a chunk.
+DEFINE_GLOBAL(size_t) chunk_npages = chunksize >> pagesize_2pow;
+
+// Number of pages necessary for a chunk header.
+DEFINE_GLOBAL(size_t)
+arena_chunk_header_npages =
+  ((sizeof(arena_chunk_t) + sizeof(arena_chunk_map_t) * (chunk_npages - 1) +
+    pagesize_mask) &
+   ~pagesize_mask) >>
+  pagesize_2pow;
 
 // Max size class for arenas.
-#define calculate_arena_maxclass()                                             \
-  (chunksize - (arena_chunk_header_npages << pagesize_2pow))
-
-#define CHUNKSIZE_DEFAULT ((size_t)1 << CHUNK_2POW_DEFAULT)
-static const size_t chunksize = CHUNKSIZE_DEFAULT;
-static const size_t chunksize_mask = CHUNKSIZE_DEFAULT - 1;
-
-#ifdef MALLOC_STATIC_PAGESIZE
-static const size_t chunk_npages = CHUNKSIZE_DEFAULT >> pagesize_2pow;
-#define arena_chunk_header_npages calculate_arena_header_pages()
-#define arena_maxclass calculate_arena_maxclass()
-#else
-static size_t chunk_npages;
-static size_t arena_chunk_header_npages;
-static size_t arena_maxclass; // Max size class for arenas.
-#endif
+DEFINE_GLOBAL(size_t)
+arena_maxclass = chunksize - (arena_chunk_header_npages << pagesize_2pow);
+
+// Various sanity checks that regard configuration.
+GLOBAL_ASSERT(1ULL << pagesize_2pow == pagesize,
+              "Page size is not a power of two");
+GLOBAL_ASSERT(quantum >= sizeof(void*));
+GLOBAL_ASSERT(quantum <= pagesize);
+GLOBAL_ASSERT(chunksize >= pagesize);
+GLOBAL_ASSERT(quantum * 4 <= chunksize);
+END_GLOBALS
 
 // Recycle at most 128 chunks. With 1 MiB chunks, this means we retain at most
 // 6.25% of the process address space on a 32-bit OS for later use.
 #define CHUNK_RECYCLE_LIMIT 128
 
 static const size_t gRecycleLimit = CHUNK_RECYCLE_LIMIT * CHUNKSIZE_DEFAULT;
 
 // The current amount of recycled bytes, updated atomically.
@@ -4112,20 +4133,17 @@ static
   if (pagesize % (size_t)result) {
     _malloc_message(
       _getprogname(),
       "Compile-time page size does not divide the runtime one.\n");
     MOZ_CRASH();
   }
 #else
   pagesize = (size_t)result;
-  pagesize_mask = (size_t)result - 1;
-  pagesize_2pow = FloorLog2(result);
-  MOZ_RELEASE_ASSERT(1ULL << pagesize_2pow == pagesize,
-                     "Page size is not a power of two");
+  DefineGlobals();
 #endif
 
   // Get runtime configuration.
   if ((opts = getenv("MALLOC_OPTIONS"))) {
     for (i = 0; opts[i] != '\0'; i++) {
       unsigned j, nreps;
       bool nseen;
 
@@ -4193,35 +4211,18 @@ static
                             cbuf,
                             "'\n");
           }
         }
       }
     }
   }
 
-#ifndef MALLOC_STATIC_PAGESIZE
-  // Set bin-related variables.
-  bin_maxclass = (pagesize >> 1);
-  nsbins = pagesize_2pow - SMALL_MAX_2POW_DEFAULT - 1;
-
-  chunk_npages = (chunksize >> pagesize_2pow);
-
-  arena_chunk_header_npages = calculate_arena_header_pages();
-  arena_maxclass = calculate_arena_maxclass();
-#endif
-
   gRecycledSize = 0;
 
-  // Various sanity checks that regard configuration.
-  MOZ_ASSERT(quantum >= sizeof(void*));
-  MOZ_ASSERT(quantum <= pagesize);
-  MOZ_ASSERT(chunksize >= pagesize);
-  MOZ_ASSERT(quantum * 4 <= chunksize);
-
   // Initialize chunks data.
   chunks_mtx.Init();
   gChunksBySize.Init();
   gChunksByAddress.Init();
 
   // Initialize huge allocation data.
   huge_mtx.Init();
   huge.Init();