summaryrefslogtreecommitdiff
path: root/memory/mozalloc/mozalloc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'memory/mozalloc/mozalloc.cpp')
-rw-r--r--memory/mozalloc/mozalloc.cpp221
1 files changed, 221 insertions, 0 deletions
diff --git a/memory/mozalloc/mozalloc.cpp b/memory/mozalloc/mozalloc.cpp
new file mode 100644
index 0000000000..55d36d80be
--- /dev/null
+++ b/memory/mozalloc/mozalloc.cpp
@@ -0,0 +1,221 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: sw=4 ts=4 et :
+ */
+/* 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/. */
+
+#include <stddef.h> // for size_t
+
+// Building with USE_STATIC_LIBS = True sets -MT instead of -MD. -MT sets _MT,
+// while -MD sets _MT and _DLL.
+#if defined(_MT) && !defined(_DLL)
+#define MOZ_STATIC_RUNTIME
+#endif
+
+#if defined(MOZ_MEMORY) && !defined(MOZ_STATIC_RUNTIME)
+// mozalloc.cpp is part of the same library as mozmemory, thus MOZ_MEMORY_IMPL
+// is needed.
+#define MOZ_MEMORY_IMPL
+#include "mozmemory_wrap.h"
+
+#if defined(XP_DARWIN)
+#include <malloc/malloc.h> // for malloc_size
+#endif
+
+// See mozmemory_wrap.h for more details. This file is part of libmozglue, so
+// it needs to use _impl suffixes. However, with libmozglue growing, this is
+// becoming cumbersome, so we will likely use a malloc.h wrapper of some sort
+// and allow the use of the functions without a _impl suffix.
+#define MALLOC_DECL(name, return_type, ...) \
+ extern "C" MOZ_MEMORY_API return_type name ## _impl(__VA_ARGS__);
+#define MALLOC_FUNCS MALLOC_FUNCS_MALLOC
+#include "malloc_decls.h"
+
+extern "C" MOZ_MEMORY_API char *strdup_impl(const char *);
+extern "C" MOZ_MEMORY_API char *strndup_impl(const char *, size_t);
+
+#else
+// When jemalloc is disabled, or when building the static runtime variant,
+// we need not to use the suffixes.
+
+#if defined(MALLOC_H)
+# include MALLOC_H // for memalign, valloc, malloc_size, malloc_us
+#endif // if defined(MALLOC_H)
+#include <stdlib.h> // for malloc, free
+#if defined(XP_UNIX)
+# include <unistd.h> // for valloc on *BSD
+#endif //if defined(XP_UNIX)
+
+#define malloc_impl malloc
+#define posix_memalign_impl posix_memalign
+#define calloc_impl calloc
+#define realloc_impl realloc
+#define free_impl free
+#define memalign_impl memalign
+#define valloc_impl valloc
+#define malloc_usable_size_impl malloc_usable_size
+#define strdup_impl strdup
+#define strndup_impl strndup
+
+#endif
+
+#include <errno.h>
+#include <new> // for std::bad_alloc
+#include <string.h>
+
+#include <sys/types.h>
+
+#include "mozilla/mozalloc.h"
+#include "mozilla/mozalloc_oom.h" // for mozalloc_handle_oom
+
+#ifdef __GNUC__
+#define LIKELY(x) (__builtin_expect(!!(x), 1))
+#define UNLIKELY(x) (__builtin_expect(!!(x), 0))
+#else
+#define LIKELY(x) (x)
+#define UNLIKELY(x) (x)
+#endif
+
+void*
+moz_xmalloc(size_t size)
+{
+ void* ptr = malloc_impl(size);
+ if (UNLIKELY(!ptr && size)) {
+ mozalloc_handle_oom(size);
+ return moz_xmalloc(size);
+ }
+ return ptr;
+}
+
+void*
+moz_xcalloc(size_t nmemb, size_t size)
+{
+ void* ptr = calloc_impl(nmemb, size);
+ if (UNLIKELY(!ptr && nmemb && size)) {
+ mozalloc_handle_oom(size);
+ return moz_xcalloc(nmemb, size);
+ }
+ return ptr;
+}
+
+void*
+moz_xrealloc(void* ptr, size_t size)
+{
+ void* newptr = realloc_impl(ptr, size);
+ if (UNLIKELY(!newptr && size)) {
+ mozalloc_handle_oom(size);
+ return moz_xrealloc(ptr, size);
+ }
+ return newptr;
+}
+
+char*
+moz_xstrdup(const char* str)
+{
+ char* dup = strdup_impl(str);
+ if (UNLIKELY(!dup)) {
+ mozalloc_handle_oom(0);
+ return moz_xstrdup(str);
+ }
+ return dup;
+}
+
+#if defined(HAVE_STRNDUP)
+char*
+moz_xstrndup(const char* str, size_t strsize)
+{
+ char* dup = strndup_impl(str, strsize);
+ if (UNLIKELY(!dup)) {
+ mozalloc_handle_oom(strsize);
+ return moz_xstrndup(str, strsize);
+ }
+ return dup;
+}
+#endif // if defined(HAVE_STRNDUP)
+
+#if defined(HAVE_POSIX_MEMALIGN)
+int
+moz_xposix_memalign(void **ptr, size_t alignment, size_t size)
+{
+ int err = posix_memalign_impl(ptr, alignment, size);
+ if (UNLIKELY(err && ENOMEM == err)) {
+ mozalloc_handle_oom(size);
+ return moz_xposix_memalign(ptr, alignment, size);
+ }
+ // else: (0 == err) or (EINVAL == err)
+ return err;
+}
+int
+moz_posix_memalign(void **ptr, size_t alignment, size_t size)
+{
+ int code = posix_memalign_impl(ptr, alignment, size);
+ if (code)
+ return code;
+
+#if defined(XP_DARWIN)
+ // Workaround faulty OSX posix_memalign, which provides memory with the
+ // incorrect alignment sometimes, but returns 0 as if nothing was wrong.
+ size_t mask = alignment - 1;
+ if (((size_t)(*ptr) & mask) != 0) {
+ void* old = *ptr;
+ code = moz_posix_memalign(ptr, alignment, size);
+ free(old);
+ }
+#endif
+
+ return code;
+
+}
+#endif // if defined(HAVE_POSIX_MEMALIGN)
+
+#if defined(HAVE_MEMALIGN)
+void*
+moz_xmemalign(size_t boundary, size_t size)
+{
+ void* ptr = memalign_impl(boundary, size);
+ if (UNLIKELY(!ptr && EINVAL != errno)) {
+ mozalloc_handle_oom(size);
+ return moz_xmemalign(boundary, size);
+ }
+ // non-NULL ptr or errno == EINVAL
+ return ptr;
+}
+#endif // if defined(HAVE_MEMALIGN)
+
+#if defined(HAVE_VALLOC)
+void*
+moz_xvalloc(size_t size)
+{
+ void* ptr = valloc_impl(size);
+ if (UNLIKELY(!ptr)) {
+ mozalloc_handle_oom(size);
+ return moz_xvalloc(size);
+ }
+ return ptr;
+}
+#endif // if defined(HAVE_VALLOC)
+
+#ifndef MOZ_STATIC_RUNTIME
+size_t
+moz_malloc_usable_size(void *ptr)
+{
+ if (!ptr)
+ return 0;
+
+#if defined(XP_DARWIN)
+ return malloc_size(ptr);
+#elif defined(HAVE_MALLOC_USABLE_SIZE) || defined(MOZ_MEMORY)
+ return malloc_usable_size_impl(ptr);
+#elif defined(XP_WIN)
+ return _msize(ptr);
+#else
+ return 0;
+#endif
+}
+
+size_t moz_malloc_size_of(const void *ptr)
+{
+ return moz_malloc_usable_size((void *)ptr);
+}
+#endif