Blame memory/mozalloc/mozalloc.h

Packit f0b94e
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
Packit f0b94e
 * vim: sw=4 ts=4 et :
Packit f0b94e
 */
Packit f0b94e
/* This Source Code Form is subject to the terms of the Mozilla Public
Packit f0b94e
 * License, v. 2.0. If a copy of the MPL was not distributed with this
Packit f0b94e
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
Packit f0b94e
Packit f0b94e
#ifndef mozilla_mozalloc_h
Packit f0b94e
#define mozilla_mozalloc_h
Packit f0b94e
Packit f0b94e
/*
Packit f0b94e
 * https://bugzilla.mozilla.org/show_bug.cgi?id=427099
Packit f0b94e
 */
Packit f0b94e
Packit f0b94e
#if defined(__cplusplus)
Packit f0b94e
#include <new>
Packit f0b94e
// Since libstdc++ 6, including the C headers (e.g. stdlib.h) instead of the
Packit f0b94e
// corresponding C++ header (e.g. cstdlib) can cause confusion in C++ code
Packit f0b94e
// using things defined there. Specifically, with stdlib.h, the use of abs()
Packit f0b94e
// in gfx/graphite2/src/inc/UtfCodec.h somehow ends up picking the wrong abs()
Packit f0b94e
#include <cstdlib>
Packit f0b94e
#else
Packit f0b94e
#include <stdlib.h>
Packit f0b94e
#endif
Packit f0b94e
Packit f0b94e
#if defined(__cplusplus)
Packit f0b94e
#include "mozilla/fallible.h"
Packit f0b94e
#include "mozilla/mozalloc_abort.h"
Packit f0b94e
#include "mozilla/TemplateLib.h"
Packit f0b94e
#endif
Packit f0b94e
#include "mozilla/Attributes.h"
Packit f0b94e
#include "mozilla/Types.h"
Packit f0b94e
Packit f0b94e
MOZ_BEGIN_EXTERN_C
Packit f0b94e
Packit f0b94e
/*
Packit f0b94e
 * We need to use malloc_impl and free_impl in this file when they are
Packit f0b94e
 * defined, because of how mozglue.dll is linked on Windows, where using
Packit f0b94e
 * malloc/free would end up using the symbols from the MSVCRT instead of
Packit f0b94e
 * ours.
Packit f0b94e
 */
Packit f0b94e
#ifndef free_impl
Packit f0b94e
#define free_impl free
Packit f0b94e
#define free_impl_
Packit f0b94e
#endif
Packit f0b94e
#ifndef malloc_impl
Packit f0b94e
#define malloc_impl malloc
Packit f0b94e
#define malloc_impl_
Packit f0b94e
#endif
Packit f0b94e
Packit f0b94e
/*
Packit f0b94e
 * Each declaration below is analogous to a "standard" allocation
Packit f0b94e
 * function, except that the out-of-memory handling is made explicit.
Packit f0b94e
 * The |moz_x| versions will never return a NULL pointer; if memory
Packit f0b94e
 * is exhausted, they abort.  The |moz_| versions may return NULL
Packit f0b94e
 * pointers if memory is exhausted: their return value must be checked.
Packit f0b94e
 *
Packit f0b94e
 * All these allocation functions are *guaranteed* to return a pointer
Packit f0b94e
 * to memory allocated in such a way that that memory can be freed by
Packit f0b94e
 * passing that pointer to |free()|.
Packit f0b94e
 */
Packit f0b94e
Packit f0b94e
MFBT_API void* moz_xmalloc(size_t size) MOZ_ALLOCATOR;
Packit f0b94e
Packit f0b94e
MFBT_API void* moz_xcalloc(size_t nmemb, size_t size) MOZ_ALLOCATOR;
Packit f0b94e
Packit f0b94e
MFBT_API void* moz_xrealloc(void* ptr, size_t size) MOZ_ALLOCATOR;
Packit f0b94e
Packit f0b94e
MFBT_API char* moz_xstrdup(const char* str) MOZ_ALLOCATOR;
Packit f0b94e
Packit f0b94e
MFBT_API size_t moz_malloc_usable_size(void* ptr);
Packit f0b94e
Packit f0b94e
MFBT_API size_t moz_malloc_size_of(const void* ptr);
Packit f0b94e
Packit f0b94e
/*
Packit f0b94e
 * Like moz_malloc_size_of(), but works reliably with interior pointers, i.e.
Packit f0b94e
 * pointers into the middle of a live allocation.
Packit f0b94e
 */
Packit f0b94e
MFBT_API size_t moz_malloc_enclosing_size_of(const void* ptr);
Packit f0b94e
Packit f0b94e
#if defined(HAVE_STRNDUP)
Packit f0b94e
MFBT_API char* moz_xstrndup(const char* str, size_t strsize) MOZ_ALLOCATOR;
Packit f0b94e
#endif /* if defined(HAVE_STRNDUP) */
Packit f0b94e
Packit f0b94e
MFBT_API void* moz_xmemalign(size_t boundary, size_t size) MOZ_ALLOCATOR;
Packit f0b94e
Packit f0b94e
MOZ_END_EXTERN_C
Packit f0b94e
Packit f0b94e
#ifdef __cplusplus
Packit f0b94e
Packit f0b94e
/*
Packit f0b94e
 * We implement the default operators new/delete as part of
Packit f0b94e
 * libmozalloc, replacing their definitions in libstdc++.  The
Packit f0b94e
 * operator new* definitions in libmozalloc will never return a NULL
Packit f0b94e
 * pointer.
Packit f0b94e
 *
Packit f0b94e
 * Each operator new immediately below returns a pointer to memory
Packit f0b94e
 * that can be delete'd by any of
Packit f0b94e
 *
Packit f0b94e
 *   (1) the matching infallible operator delete immediately below
Packit f0b94e
 *   (2) the matching system |operator delete(void*, std::nothrow)|
Packit f0b94e
 *   (3) the matching system |operator delete(void*) throw(std::bad_alloc)|
Packit f0b94e
 *
Packit f0b94e
 * NB: these are declared |throw(std::bad_alloc)|, though they will never
Packit f0b94e
 * throw that exception.  This declaration is consistent with the rule
Packit f0b94e
 * that |::operator new() throw(std::bad_alloc)| will never return NULL.
Packit f0b94e
 *
Packit f0b94e
 * NB: mozilla::fallible can be used instead of std::nothrow.
Packit f0b94e
 */
Packit f0b94e
Packit f0b94e
/* NB: This is defined just to silence vacuous warnings about symbol
Packit f0b94e
 * visibility on OS X/gcc. These symbols are force-inline and not
Packit f0b94e
 * exported. */
Packit f0b94e
#if defined(XP_MACOSX)
Packit f0b94e
#define MOZALLOC_EXPORT_NEW MFBT_API
Packit f0b94e
#else
Packit f0b94e
#define MOZALLOC_EXPORT_NEW
Packit f0b94e
#endif
Packit f0b94e
Packit f0b94e
#if defined(_MSC_VER)
Packit f0b94e
/*
Packit f0b94e
 * Suppress build warning spam (bug 578546).
Packit f0b94e
 */
Packit f0b94e
#if _MSC_VER < 1912
Packit f0b94e
#define MOZALLOC_THROW_IF_HAS_EXCEPTIONS
Packit f0b94e
#else
Packit f0b94e
#define MOZALLOC_THROW_IF_HAS_EXCEPTIONS throw()
Packit f0b94e
#endif
Packit f0b94e
#define MOZALLOC_THROW_BAD_ALLOC_IF_HAS_EXCEPTIONS
Packit f0b94e
#else
Packit f0b94e
/*
Packit f0b94e
 * C++11 has deprecated exception-specifications in favour of |noexcept|.
Packit f0b94e
 */
Packit f0b94e
#define MOZALLOC_THROW_IF_HAS_EXCEPTIONS noexcept(true)
Packit f0b94e
#define MOZALLOC_THROW_BAD_ALLOC_IF_HAS_EXCEPTIONS noexcept(false)
Packit f0b94e
#endif
Packit f0b94e
Packit f0b94e
#define MOZALLOC_THROW_BAD_ALLOC MOZALLOC_THROW_BAD_ALLOC_IF_HAS_EXCEPTIONS
Packit f0b94e
Packit f0b94e
MOZALLOC_EXPORT_NEW
Packit f0b94e
#if defined(__GNUC__) && !defined(__clang__) && defined(__SANITIZE_ADDRESS__)
Packit f0b94e
/* gcc's asan somehow doesn't like always_inline on this function. */
Packit f0b94e
__attribute__((gnu_inline)) inline
Packit f0b94e
#else
Packit f0b94e
MOZ_ALWAYS_INLINE_EVEN_DEBUG
Packit f0b94e
#endif
Packit f0b94e
    void*
Packit f0b94e
    operator new(size_t size) MOZALLOC_THROW_BAD_ALLOC {
Packit f0b94e
  return moz_xmalloc(size);
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
MOZALLOC_EXPORT_NEW MOZ_ALWAYS_INLINE_EVEN_DEBUG void* operator new(
Packit f0b94e
    size_t size, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS {
Packit f0b94e
  return malloc_impl(size);
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
MOZALLOC_EXPORT_NEW MOZ_ALWAYS_INLINE_EVEN_DEBUG void* operator new[](
Packit f0b94e
    size_t size) MOZALLOC_THROW_BAD_ALLOC {
Packit f0b94e
  return moz_xmalloc(size);
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
MOZALLOC_EXPORT_NEW MOZ_ALWAYS_INLINE_EVEN_DEBUG void* operator new[](
Packit f0b94e
    size_t size, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS {
Packit f0b94e
  return malloc_impl(size);
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
MOZALLOC_EXPORT_NEW MOZ_ALWAYS_INLINE_EVEN_DEBUG void operator delete(void* ptr)
Packit f0b94e
    MOZALLOC_THROW_IF_HAS_EXCEPTIONS {
Packit f0b94e
  return free_impl(ptr);
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
MOZALLOC_EXPORT_NEW MOZ_ALWAYS_INLINE_EVEN_DEBUG void operator delete(
Packit f0b94e
    void* ptr, const std::nothrow_t&)MOZALLOC_THROW_IF_HAS_EXCEPTIONS {
Packit f0b94e
  return free_impl(ptr);
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
MOZALLOC_EXPORT_NEW MOZ_ALWAYS_INLINE_EVEN_DEBUG void operator delete[](
Packit f0b94e
    void* ptr) MOZALLOC_THROW_IF_HAS_EXCEPTIONS {
Packit f0b94e
  return free_impl(ptr);
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
MOZALLOC_EXPORT_NEW MOZ_ALWAYS_INLINE_EVEN_DEBUG void operator delete[](
Packit f0b94e
    void* ptr, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS {
Packit f0b94e
  return free_impl(ptr);
Packit f0b94e
}
Packit f0b94e
Packit f0b94e
/*
Packit f0b94e
 * This policy is identical to MallocAllocPolicy, except it uses
Packit f0b94e
 * moz_xmalloc/moz_xcalloc/moz_xrealloc instead of
Packit f0b94e
 * malloc/calloc/realloc.
Packit f0b94e
 */
Packit f0b94e
class InfallibleAllocPolicy {
Packit f0b94e
 public:
Packit f0b94e
  template <typename T>
Packit f0b94e
  T* maybe_pod_malloc(size_t aNumElems) {
Packit f0b94e
    return pod_malloc<T>(aNumElems);
Packit f0b94e
  }
Packit f0b94e
Packit f0b94e
  template <typename T>
Packit f0b94e
  T* maybe_pod_calloc(size_t aNumElems) {
Packit f0b94e
    return pod_calloc<T>(aNumElems);
Packit f0b94e
  }
Packit f0b94e
Packit f0b94e
  template <typename T>
Packit f0b94e
  T* maybe_pod_realloc(T* aPtr, size_t aOldSize, size_t aNewSize) {
Packit f0b94e
    return pod_realloc<T>(aPtr, aOldSize, aNewSize);
Packit f0b94e
  }
Packit f0b94e
Packit f0b94e
  template <typename T>
Packit f0b94e
  T* pod_malloc(size_t aNumElems) {
Packit f0b94e
    if (aNumElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
Packit f0b94e
      reportAllocOverflow();
Packit f0b94e
    }
Packit f0b94e
    return static_cast<T*>(moz_xmalloc(aNumElems * sizeof(T)));
Packit f0b94e
  }
Packit f0b94e
Packit f0b94e
  template <typename T>
Packit f0b94e
  T* pod_calloc(size_t aNumElems) {
Packit f0b94e
    return static_cast<T*>(moz_xcalloc(aNumElems, sizeof(T)));
Packit f0b94e
  }
Packit f0b94e
Packit f0b94e
  template <typename T>
Packit f0b94e
  T* pod_realloc(T* aPtr, size_t aOldSize, size_t aNewSize) {
Packit f0b94e
    if (aNewSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
Packit f0b94e
      reportAllocOverflow();
Packit f0b94e
    }
Packit f0b94e
    return static_cast<T*>(moz_xrealloc(aPtr, aNewSize * sizeof(T)));
Packit f0b94e
  }
Packit f0b94e
Packit f0b94e
  void free_(void* aPtr) { free_impl(aPtr); }
Packit f0b94e
Packit f0b94e
  void reportAllocOverflow() const { mozalloc_abort("alloc overflow"); }
Packit f0b94e
Packit f0b94e
  bool checkSimulatedOOM() const { return true; }
Packit f0b94e
};
Packit f0b94e
Packit f0b94e
#endif /* ifdef __cplusplus */
Packit f0b94e
Packit f0b94e
#ifdef malloc_impl_
Packit f0b94e
#undef malloc_impl_
Packit f0b94e
#undef malloc_impl
Packit f0b94e
#endif
Packit f0b94e
#ifdef free_impl_
Packit f0b94e
#undef free_impl_
Packit f0b94e
#undef free_impl
Packit f0b94e
#endif
Packit f0b94e
Packit f0b94e
#endif /* ifndef mozilla_mozalloc_h */