Bug 1368932 - Handle missing replace_posix_memalign at the replace-malloc level. r?njn draft
authorMike Hommey <mh+mozilla@glandium.org>
Wed, 31 May 2017 13:47:17 +0900
changeset 587420 d9a1d1747ae1d1e08de5b6b79d3069ef7224ab89
parent 587419 f8199b5fe0a2e549e3f2d20919b6cebb044db3be
child 587421 e8ff2c54dcc2287970e22a1ccac9408a2e034eed
child 587426 eb9c26d64487a9fae8ebed3d5a13b561c0fee3fd
push id61698
push userbmo:mh+mozilla@glandium.org
push dateThu, 01 Jun 2017 00:41:06 +0000
reviewersnjn
bugs1368932
milestone55.0a1
Bug 1368932 - Handle missing replace_posix_memalign at the replace-malloc level. r?njn Replace-malloc libraries, such as DMD, don't really need to care about the details of implementing all the variants of aligned memory allocation functions. Currently, by defining MOZ_REPLACE_ONLY_MEMALIGN before including replace_malloc.h, they get predefined functions. Instead of making that an opt-in at build time, we make the replace-malloc initialization just fill the replace-malloc malloc_table_t with implementations that rely on the replace_memalign the library provides.
memory/build/replace_malloc.c
memory/build/replace_malloc.h
memory/replace/dmd/DMD.cpp
--- a/memory/build/replace_malloc.c
+++ b/memory/build/replace_malloc.c
@@ -14,16 +14,20 @@
 
 /* Declare all je_* functions */
 #define MALLOC_DECL(name, return_type, ...) \
   return_type je_ ## name(__VA_ARGS__);
 #include "malloc_decls.h"
 
 #include "mozilla/Likely.h"
 #include "mozilla/MacroArgs.h"
+#include <errno.h>
+#ifndef XP_WIN
+#include <unistd.h>
+#endif
 
 /*
  * Windows doesn't come with weak imports as they are possible with
  * LD_PRELOAD or DYLD_INSERT_LIBRARIES on Linux/OSX. On this platform,
  * the replacement functions are defined as variable pointers to the
  * function resolved with GetProcAddress() instead of weak definitions
  * of functions. On Android, the same needs to happen as well, because
  * the Android linker doesn't handle weak linking with non LD_PRELOADed
@@ -205,16 +209,60 @@ typedef void *(* __memalign_hook_type)(s
 
 MOZ_MEMORY_API __free_hook_type __free_hook = free_impl;
 MOZ_MEMORY_API __malloc_hook_type __malloc_hook = malloc_impl;
 MOZ_MEMORY_API __realloc_hook_type __realloc_hook = realloc_impl;
 MOZ_MEMORY_API __memalign_hook_type __memalign_hook = memalign_impl;
 
 #endif
 
+/*
+ * posix_memalign, aligned_alloc, memalign and valloc all implement some kind
+ * of aligned memory allocation. For convenience, a replace-malloc library can
+ * skip defining replace_posix_memalign, replace_aligned_alloc and
+ * replace_valloc, and default implementations will be automatically derived
+ * from replace_memalign.
+ */
+static int
+default_posix_memalign(void** ptr, size_t alignment, size_t size)
+{
+  if (size == 0) {
+    *ptr = NULL;
+    return 0;
+  }
+  /* alignment must be a power of two and a multiple of sizeof(void *) */
+  if (((alignment - 1) & alignment) != 0 || (alignment % sizeof(void *)))
+    return EINVAL;
+  *ptr = replace_malloc_table.memalign(alignment, size);
+  return *ptr ? 0 : ENOMEM;
+}
+
+static void*
+default_aligned_alloc(size_t alignment, size_t size)
+{
+  /* size should be a multiple of alignment */
+  if (size % alignment)
+    return NULL;
+  return replace_malloc_table.memalign(alignment, size);
+}
+
+// Nb: sysconf() is expensive, but valloc is obsolete and rarely used.
+static void*
+default_valloc(size_t size)
+{
+#ifdef XP_WIN
+  SYSTEM_INFO si;
+  GetSystemInfo(&si);
+  size_t page_size = si.dwPageSize;
+#else
+  size_t page_size = sysconf(_SC_PAGE_SIZE);
+#endif
+  return replace_malloc_table.memalign(page_size, size);
+}
+
 static void
 replace_malloc_init_funcs()
 {
   replace_malloc_handle_t handle = replace_malloc_handle();
   if (handle) {
 #ifdef MOZ_NO_REPLACE_FUNC_DECL
 #  define MALLOC_DECL(name, ...) \
     replace_ ## name = REPLACE_MALLOC_GET_FUNC(handle, name);
@@ -223,14 +271,23 @@ replace_malloc_init_funcs()
 #  include "malloc_decls.h"
 #endif
 
 #define MALLOC_DECL(name, ...) \
   replace_malloc_table.name = REPLACE_MALLOC_GET_FUNC(handle, name);
 #include "malloc_decls.h"
   }
 
+  if (!replace_malloc_table.posix_memalign && replace_malloc_table.memalign)
+    replace_malloc_table.posix_memalign = default_posix_memalign;
+
+  if (!replace_malloc_table.aligned_alloc && replace_malloc_table.memalign)
+    replace_malloc_table.aligned_alloc = default_aligned_alloc;
+
+  if (!replace_malloc_table.valloc && replace_malloc_table.memalign)
+    replace_malloc_table.valloc = default_valloc;
+
 #define MALLOC_DECL(name, ...) \
   if (!replace_malloc_table.name) { \
     replace_malloc_table.name = je_ ## name; \
   }
 #include "malloc_decls.h"
 }
--- a/memory/build/replace_malloc.h
+++ b/memory/build/replace_malloc.h
@@ -86,48 +86,11 @@ MOZ_BEGIN_EXTERN_C
 #  define MALLOC_DECL(name, return_type, ...) \
     MOZ_EXPORT return_type replace_ ## name(__VA_ARGS__) MOZ_REPLACE_WEAK;
 
 #  define MALLOC_FUNCS MALLOC_FUNCS_ALL
 #  include "malloc_decls.h"
 
 #endif /* MOZ_NO_REPLACE_FUNC_DECL */
 
-/*
- * posix_memalign, aligned_alloc, memalign and valloc all implement some
- * kind of aligned memory allocation. For convenience, replace_posix_memalign,
- * replace_aligned_alloc and replace_valloc can be automatically derived from
- * memalign when MOZ_REPLACE_ONLY_MEMALIGN is defined before including this
- * header. PAGE_SIZE also needs to be defined to the appropriate expression.
- */
-#ifdef MOZ_REPLACE_ONLY_MEMALIGN
-#include <errno.h>
-
-int replace_posix_memalign(void **ptr, size_t alignment, size_t size)
-{
-  if (size == 0) {
-    *ptr = NULL;
-    return 0;
-  }
-  /* alignment must be a power of two and a multiple of sizeof(void *) */
-  if (((alignment - 1) & alignment) != 0 || (alignment % sizeof(void *)))
-    return EINVAL;
-  *ptr = replace_memalign(alignment, size);
-  return *ptr ? 0 : ENOMEM;
-}
-
-void *replace_aligned_alloc(size_t alignment, size_t size)
-{
-  /* size should be a multiple of alignment */
-  if (size % alignment)
-    return NULL;
-  return replace_memalign(alignment, size);
-}
-
-void *replace_valloc(size_t size)
-{
-  return replace_memalign(PAGE_SIZE, size);
-}
-#endif
-
 MOZ_END_EXTERN_C
 
 #endif /* replace_malloc_h */
--- a/memory/replace/dmd/DMD.cpp
+++ b/memory/replace/dmd/DMD.cpp
@@ -44,43 +44,17 @@
 #include "mozilla/MemoryReporting.h"
 
 // CodeAddressService is defined entirely in the header, so this does not make
 // DMD depend on XPCOM's object file.
 #include "CodeAddressService.h"
 
 // replace_malloc.h needs to be included before replace_malloc_bridge.h,
 // which DMD.h includes, so DMD.h needs to be included after replace_malloc.h.
-// MOZ_REPLACE_ONLY_MEMALIGN saves us from having to define
-// replace_{posix_memalign,aligned_alloc,valloc}.  It requires defining
-// PAGE_SIZE.  Nb: sysconf() is expensive, but it's only used for (the obsolete
-// and rarely used) valloc.
-#define MOZ_REPLACE_ONLY_MEMALIGN 1
-
-#ifndef PAGE_SIZE
-#define DMD_DEFINED_PAGE_SIZE
-#ifdef XP_WIN
-#define PAGE_SIZE GetPageSize()
-static long GetPageSize()
-{
-  SYSTEM_INFO si;
-  GetSystemInfo(&si);
-  return si.dwPageSize;
-}
-#else // XP_WIN
-#define PAGE_SIZE sysconf(_SC_PAGESIZE)
-#endif // XP_WIN
-#endif // PAGE_SIZE
 #include "replace_malloc.h"
-#undef MOZ_REPLACE_ONLY_MEMALIGN
-#ifdef DMD_DEFINED_PAGE_SIZE
-#undef DMD_DEFINED_PAGE_SIZE
-#undef PAGE_SIZE
-#endif // DMD_DEFINED_PAGE_SIZE
-
 #include "DMD.h"
 
 namespace mozilla {
 namespace dmd {
 
 class DMDBridge : public ReplaceMallocBridge
 {
   virtual DMDFuncs* GetDMDFuncs() override;