summaryrefslogtreecommitdiffstats
path: root/memory/mozalloc/mozalloc.h
diff options
context:
space:
mode:
Diffstat (limited to 'memory/mozalloc/mozalloc.h')
-rw-r--r--memory/mozalloc/mozalloc.h361
1 files changed, 361 insertions, 0 deletions
diff --git a/memory/mozalloc/mozalloc.h b/memory/mozalloc/mozalloc.h
new file mode 100644
index 000000000..f7ddb7e6d
--- /dev/null
+++ b/memory/mozalloc/mozalloc.h
@@ -0,0 +1,361 @@
+/* -*- 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/. */
+
+#ifndef mozilla_mozalloc_h
+#define mozilla_mozalloc_h
+
+/*
+ * https://bugzilla.mozilla.org/show_bug.cgi?id=427099
+ */
+
+#if defined(__cplusplus)
+# include <new>
+// Since libstdc++ 6, including the C headers (e.g. stdlib.h) instead of the
+// corresponding C++ header (e.g. cstdlib) can cause confusion in C++ code
+// using things defined there. Specifically, with stdlib.h, the use of abs()
+// in gfx/graphite2/src/inc/UtfCodec.h somehow ends up picking the wrong abs()
+# include <cstdlib>
+# include <cstring>
+#else
+# include <stdlib.h>
+# include <string.h>
+#endif
+
+#if defined(__cplusplus)
+#include "mozilla/fallible.h"
+#include "mozilla/mozalloc_abort.h"
+#include "mozilla/TemplateLib.h"
+#endif
+#include "mozilla/Attributes.h"
+#include "mozilla/Types.h"
+
+#define MOZALLOC_HAVE_XMALLOC
+
+#if defined(MOZ_ALWAYS_INLINE_EVEN_DEBUG)
+# define MOZALLOC_INLINE MOZ_ALWAYS_INLINE_EVEN_DEBUG
+#elif defined(HAVE_FORCEINLINE)
+# define MOZALLOC_INLINE __forceinline
+#else
+# define MOZALLOC_INLINE inline
+#endif
+
+/* Workaround build problem with Sun Studio 12 */
+#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
+# undef MOZ_MUST_USE
+# define MOZ_MUST_USE
+# undef MOZ_ALLOCATOR
+# define MOZ_ALLOCATOR
+#endif
+
+#if defined(__cplusplus)
+extern "C" {
+#endif /* ifdef __cplusplus */
+
+/*
+ * We need to use malloc_impl and free_impl in this file when they are
+ * defined, because of how mozglue.dll is linked on Windows, where using
+ * malloc/free would end up using the symbols from the MSVCRT instead of
+ * ours.
+ */
+#ifndef free_impl
+#define free_impl free
+#define free_impl_
+#endif
+#ifndef malloc_impl
+#define malloc_impl malloc
+#define malloc_impl_
+#endif
+
+/*
+ * Each declaration below is analogous to a "standard" allocation
+ * function, except that the out-of-memory handling is made explicit.
+ * The |moz_x| versions will never return a NULL pointer; if memory
+ * is exhausted, they abort. The |moz_| versions may return NULL
+ * pointers if memory is exhausted: their return value must be checked.
+ *
+ * All these allocation functions are *guaranteed* to return a pointer
+ * to memory allocated in such a way that that memory can be freed by
+ * passing that pointer to |free()|.
+ */
+
+MFBT_API void* moz_xmalloc(size_t size)
+ MOZ_ALLOCATOR;
+
+MFBT_API void* moz_xcalloc(size_t nmemb, size_t size)
+ MOZ_ALLOCATOR;
+
+MFBT_API void* moz_xrealloc(void* ptr, size_t size)
+ MOZ_ALLOCATOR;
+
+MFBT_API char* moz_xstrdup(const char* str)
+ MOZ_ALLOCATOR;
+
+MFBT_API size_t moz_malloc_usable_size(void *ptr);
+
+MFBT_API size_t moz_malloc_size_of(const void *ptr);
+
+#if defined(HAVE_STRNDUP)
+MFBT_API char* moz_xstrndup(const char* str, size_t strsize)
+ MOZ_ALLOCATOR;
+#endif /* if defined(HAVE_STRNDUP) */
+
+
+#if defined(HAVE_POSIX_MEMALIGN)
+MFBT_API MOZ_MUST_USE
+int moz_xposix_memalign(void **ptr, size_t alignment, size_t size);
+
+MFBT_API MOZ_MUST_USE
+int moz_posix_memalign(void **ptr, size_t alignment, size_t size);
+#endif /* if defined(HAVE_POSIX_MEMALIGN) */
+
+
+#if defined(HAVE_MEMALIGN)
+MFBT_API void* moz_xmemalign(size_t boundary, size_t size)
+ MOZ_ALLOCATOR;
+#endif /* if defined(HAVE_MEMALIGN) */
+
+
+#if defined(HAVE_VALLOC)
+MFBT_API void* moz_xvalloc(size_t size)
+ MOZ_ALLOCATOR;
+#endif /* if defined(HAVE_VALLOC) */
+
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif /* ifdef __cplusplus */
+
+
+#ifdef __cplusplus
+
+/*
+ * We implement the default operators new/delete as part of
+ * libmozalloc, replacing their definitions in libstdc++. The
+ * operator new* definitions in libmozalloc will never return a NULL
+ * pointer.
+ *
+ * Each operator new immediately below returns a pointer to memory
+ * that can be delete'd by any of
+ *
+ * (1) the matching infallible operator delete immediately below
+ * (2) the matching "fallible" operator delete further below
+ * (3) the matching system |operator delete(void*, std::nothrow)|
+ * (4) the matching system |operator delete(void*) throw(std::bad_alloc)|
+ *
+ * NB: these are declared |throw(std::bad_alloc)|, though they will never
+ * throw that exception. This declaration is consistent with the rule
+ * that |::operator new() throw(std::bad_alloc)| will never return NULL.
+ */
+
+/* NB: This is defined just to silence vacuous warnings about symbol
+ * visibility on OS X/gcc. These symbols are force-inline and not
+ * exported. */
+#if defined(XP_MACOSX)
+# define MOZALLOC_EXPORT_NEW MFBT_API
+#else
+# define MOZALLOC_EXPORT_NEW
+#endif
+
+#if defined(ANDROID)
+/*
+ * It's important to always specify 'throw()' in GCC because it's used to tell
+ * GCC that 'new' may return null. That makes GCC null-check the result before
+ * potentially initializing the memory to zero.
+ * Also, the Android minimalistic headers don't include std::bad_alloc.
+ */
+#define MOZALLOC_THROW_IF_HAS_EXCEPTIONS throw()
+#define MOZALLOC_THROW_BAD_ALLOC_IF_HAS_EXCEPTIONS
+#elif defined(_MSC_VER)
+/*
+ * Suppress build warning spam (bug 578546).
+ */
+#define MOZALLOC_THROW_IF_HAS_EXCEPTIONS
+#define MOZALLOC_THROW_BAD_ALLOC_IF_HAS_EXCEPTIONS
+#else
+#define MOZALLOC_THROW_IF_HAS_EXCEPTIONS throw()
+#define MOZALLOC_THROW_BAD_ALLOC_IF_HAS_EXCEPTIONS throw(std::bad_alloc)
+#endif
+
+#define MOZALLOC_THROW_BAD_ALLOC MOZALLOC_THROW_BAD_ALLOC_IF_HAS_EXCEPTIONS
+
+MOZALLOC_EXPORT_NEW
+#if defined(__GNUC__) && !defined(__clang__) && defined(__SANITIZE_ADDRESS__)
+/* gcc's asan somehow doesn't like always_inline on this function. */
+__attribute__((gnu_inline)) inline
+#else
+MOZALLOC_INLINE
+#endif
+void* operator new(size_t size) MOZALLOC_THROW_BAD_ALLOC
+{
+ return moz_xmalloc(size);
+}
+
+MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
+void* operator new(size_t size, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
+{
+ return malloc_impl(size);
+}
+
+MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
+void* operator new[](size_t size) MOZALLOC_THROW_BAD_ALLOC
+{
+ return moz_xmalloc(size);
+}
+
+MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
+void* operator new[](size_t size, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
+{
+ return malloc_impl(size);
+}
+
+MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
+void operator delete(void* ptr) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
+{
+ return free_impl(ptr);
+}
+
+MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
+void operator delete(void* ptr, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
+{
+ return free_impl(ptr);
+}
+
+MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
+void operator delete[](void* ptr) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
+{
+ return free_impl(ptr);
+}
+
+MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
+void operator delete[](void* ptr, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
+{
+ return free_impl(ptr);
+}
+
+
+/*
+ * We also add a new allocator variant: "fallible operator new."
+ * Unlike libmozalloc's implementations of the standard nofail
+ * allocators, this allocator is allowed to return NULL. It can be used
+ * as follows
+ *
+ * Foo* f = new (mozilla::fallible) Foo(...);
+ *
+ * operator delete(fallible) is defined for completeness only.
+ *
+ * Each operator new below returns a pointer to memory that can be
+ * delete'd by any of
+ *
+ * (1) the matching "fallible" operator delete below
+ * (2) the matching infallible operator delete above
+ * (3) the matching system |operator delete(void*, std::nothrow)|
+ * (4) the matching system |operator delete(void*) throw(std::bad_alloc)|
+ */
+
+MOZALLOC_INLINE
+void* operator new(size_t size, const mozilla::fallible_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
+{
+ return malloc_impl(size);
+}
+
+MOZALLOC_INLINE
+void* operator new[](size_t size, const mozilla::fallible_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
+{
+ return malloc_impl(size);
+}
+
+MOZALLOC_INLINE
+void operator delete(void* ptr, const mozilla::fallible_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
+{
+ free_impl(ptr);
+}
+
+MOZALLOC_INLINE
+void operator delete[](void* ptr, const mozilla::fallible_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
+{
+ free_impl(ptr);
+}
+
+
+/*
+ * This policy is identical to MallocAllocPolicy, except it uses
+ * moz_xmalloc/moz_xcalloc/moz_xrealloc instead of
+ * malloc/calloc/realloc.
+ */
+class InfallibleAllocPolicy
+{
+public:
+ template <typename T>
+ T* maybe_pod_malloc(size_t aNumElems)
+ {
+ return pod_malloc<T>(aNumElems);
+ }
+
+ template <typename T>
+ T* maybe_pod_calloc(size_t aNumElems)
+ {
+ return pod_calloc<T>(aNumElems);
+ }
+
+ template <typename T>
+ T* maybe_pod_realloc(T* aPtr, size_t aOldSize, size_t aNewSize)
+ {
+ return pod_realloc<T>(aPtr, aOldSize, aNewSize);
+ }
+
+ template <typename T>
+ T* pod_malloc(size_t aNumElems)
+ {
+ if (aNumElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
+ reportAllocOverflow();
+ }
+ return static_cast<T*>(moz_xmalloc(aNumElems * sizeof(T)));
+ }
+
+ template <typename T>
+ T* pod_calloc(size_t aNumElems)
+ {
+ return static_cast<T*>(moz_xcalloc(aNumElems, sizeof(T)));
+ }
+
+ template <typename T>
+ T* pod_realloc(T* aPtr, size_t aOldSize, size_t aNewSize)
+ {
+ if (aNewSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
+ reportAllocOverflow();
+ }
+ return static_cast<T*>(moz_xrealloc(aPtr, aNewSize * sizeof(T)));
+ }
+
+ void free_(void* aPtr)
+ {
+ free_impl(aPtr);
+ }
+
+ void reportAllocOverflow() const
+ {
+ mozalloc_abort("alloc overflow");
+ }
+
+ bool checkSimulatedOOM() const
+ {
+ return true;
+ }
+};
+
+#endif /* ifdef __cplusplus */
+
+#ifdef malloc_impl_
+#undef malloc_impl_
+#undef malloc_impl
+#endif
+#ifdef free_impl_
+#undef free_impl_
+#undef free_impl
+#endif
+
+#endif /* ifndef mozilla_mozalloc_h */