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.
--- 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;