LCOV - code coverage report
Current view: top level - memory/mozalloc - mozalloc.h (source / functions) Hit Total Coverage
Test: output.info Lines: 21 25 84.0 %
Date: 2017-07-14 16:53:18 Functions: 11 17 64.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: sw=4 ts=4 et :
       3             :  */
       4             : /* This Source Code Form is subject to the terms of the Mozilla Public
       5             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       6             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       7             : 
       8             : #ifndef mozilla_mozalloc_h
       9             : #define mozilla_mozalloc_h
      10             : 
      11             : /*
      12             :  * https://bugzilla.mozilla.org/show_bug.cgi?id=427099
      13             :  */
      14             : 
      15             : #if defined(__cplusplus)
      16             : #  include <new>
      17             : // Since libstdc++ 6, including the C headers (e.g. stdlib.h) instead of the
      18             : // corresponding C++ header (e.g. cstdlib) can cause confusion in C++ code
      19             : // using things defined there. Specifically, with stdlib.h, the use of abs()
      20             : // in gfx/graphite2/src/inc/UtfCodec.h somehow ends up picking the wrong abs()
      21             : #  include <cstdlib>
      22             : #  include <cstring>
      23             : #else
      24             : #  include <stdlib.h>
      25             : #  include <string.h>
      26             : #endif
      27             : 
      28             : #if defined(__cplusplus)
      29             : #include "mozilla/fallible.h"
      30             : #include "mozilla/mozalloc_abort.h"
      31             : #include "mozilla/TemplateLib.h"
      32             : #endif
      33             : #include "mozilla/Attributes.h"
      34             : #include "mozilla/Types.h"
      35             : 
      36             : #define MOZALLOC_HAVE_XMALLOC
      37             : 
      38             : #if defined(MOZ_ALWAYS_INLINE_EVEN_DEBUG)
      39             : #  define MOZALLOC_INLINE MOZ_ALWAYS_INLINE_EVEN_DEBUG
      40             : #elif defined(HAVE_FORCEINLINE)
      41             : #  define MOZALLOC_INLINE __forceinline
      42             : #else
      43             : #  define MOZALLOC_INLINE inline
      44             : #endif
      45             : 
      46             : /* Workaround build problem with Sun Studio 12 */
      47             : #if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
      48             : #  undef MOZ_MUST_USE
      49             : #  define MOZ_MUST_USE
      50             : #  undef MOZ_ALLOCATOR
      51             : #  define MOZ_ALLOCATOR
      52             : #endif
      53             : 
      54             : #if defined(__cplusplus)
      55             : extern "C" {
      56             : #endif /* ifdef __cplusplus */
      57             : 
      58             : /*
      59             :  * We need to use malloc_impl and free_impl in this file when they are
      60             :  * defined, because of how mozglue.dll is linked on Windows, where using
      61             :  * malloc/free would end up using the symbols from the MSVCRT instead of
      62             :  * ours.
      63             :  */
      64             : #ifndef free_impl
      65             : #define free_impl free
      66             : #define free_impl_
      67             : #endif
      68             : #ifndef malloc_impl
      69             : #define malloc_impl malloc
      70             : #define malloc_impl_
      71             : #endif
      72             : 
      73             : /*
      74             :  * Each declaration below is analogous to a "standard" allocation
      75             :  * function, except that the out-of-memory handling is made explicit.
      76             :  * The |moz_x| versions will never return a NULL pointer; if memory
      77             :  * is exhausted, they abort.  The |moz_| versions may return NULL
      78             :  * pointers if memory is exhausted: their return value must be checked.
      79             :  *
      80             :  * All these allocation functions are *guaranteed* to return a pointer
      81             :  * to memory allocated in such a way that that memory can be freed by
      82             :  * passing that pointer to |free()|.
      83             :  */
      84             : 
      85             : MFBT_API void* moz_xmalloc(size_t size)
      86             :     MOZ_ALLOCATOR;
      87             : 
      88             : MFBT_API void* moz_xcalloc(size_t nmemb, size_t size)
      89             :     MOZ_ALLOCATOR;
      90             : 
      91             : MFBT_API void* moz_xrealloc(void* ptr, size_t size)
      92             :     MOZ_ALLOCATOR;
      93             : 
      94             : MFBT_API char* moz_xstrdup(const char* str)
      95             :     MOZ_ALLOCATOR;
      96             : 
      97             : MFBT_API size_t moz_malloc_usable_size(void *ptr);
      98             : 
      99             : MFBT_API size_t moz_malloc_size_of(const void *ptr);
     100             : 
     101             : #if defined(HAVE_STRNDUP)
     102             : MFBT_API char* moz_xstrndup(const char* str, size_t strsize)
     103             :     MOZ_ALLOCATOR;
     104             : #endif /* if defined(HAVE_STRNDUP) */
     105             : 
     106             : 
     107             : #if defined(HAVE_POSIX_MEMALIGN)
     108             : MFBT_API MOZ_MUST_USE
     109             : int moz_xposix_memalign(void **ptr, size_t alignment, size_t size);
     110             : 
     111             : MFBT_API MOZ_MUST_USE
     112             : int moz_posix_memalign(void **ptr, size_t alignment, size_t size);
     113             : #endif /* if defined(HAVE_POSIX_MEMALIGN) */
     114             : 
     115             : 
     116             : #if defined(HAVE_MEMALIGN)
     117             : MFBT_API void* moz_xmemalign(size_t boundary, size_t size)
     118             :     MOZ_ALLOCATOR;
     119             : #endif /* if defined(HAVE_MEMALIGN) */
     120             : 
     121             : 
     122             : #if defined(HAVE_VALLOC)
     123             : MFBT_API void* moz_xvalloc(size_t size)
     124             :     MOZ_ALLOCATOR;
     125             : #endif /* if defined(HAVE_VALLOC) */
     126             : 
     127             : 
     128             : #ifdef __cplusplus
     129             : } /* extern "C" */
     130             : #endif /* ifdef __cplusplus */
     131             : 
     132             : 
     133             : #ifdef __cplusplus
     134             : 
     135             : /*
     136             :  * We implement the default operators new/delete as part of
     137             :  * libmozalloc, replacing their definitions in libstdc++.  The
     138             :  * operator new* definitions in libmozalloc will never return a NULL
     139             :  * pointer.
     140             :  *
     141             :  * Each operator new immediately below returns a pointer to memory
     142             :  * that can be delete'd by any of
     143             :  *
     144             :  *   (1) the matching infallible operator delete immediately below
     145             :  *   (2) the matching "fallible" operator delete further below
     146             :  *   (3) the matching system |operator delete(void*, std::nothrow)|
     147             :  *   (4) the matching system |operator delete(void*) throw(std::bad_alloc)|
     148             :  *
     149             :  * NB: these are declared |throw(std::bad_alloc)|, though they will never
     150             :  * throw that exception.  This declaration is consistent with the rule
     151             :  * that |::operator new() throw(std::bad_alloc)| will never return NULL.
     152             :  */
     153             : 
     154             : /* NB: This is defined just to silence vacuous warnings about symbol
     155             :  * visibility on OS X/gcc. These symbols are force-inline and not
     156             :  * exported. */
     157             : #if defined(XP_MACOSX)
     158             : #  define MOZALLOC_EXPORT_NEW MFBT_API
     159             : #else
     160             : #  define MOZALLOC_EXPORT_NEW
     161             : #endif
     162             : 
     163             : #if defined(ANDROID)
     164             : /*
     165             :  * It's important to always specify 'throw()' in GCC because it's used to tell
     166             :  * GCC that 'new' may return null. That makes GCC null-check the result before
     167             :  * potentially initializing the memory to zero.
     168             :  * Also, the Android minimalistic headers don't include std::bad_alloc.
     169             :  */
     170             : #define MOZALLOC_THROW_IF_HAS_EXCEPTIONS throw()
     171             : #define MOZALLOC_THROW_BAD_ALLOC_IF_HAS_EXCEPTIONS
     172             : #elif defined(_MSC_VER)
     173             : /*
     174             :  * Suppress build warning spam (bug 578546).
     175             :  */
     176             : #define MOZALLOC_THROW_IF_HAS_EXCEPTIONS
     177             : #define MOZALLOC_THROW_BAD_ALLOC_IF_HAS_EXCEPTIONS
     178             : #else
     179             : #define MOZALLOC_THROW_IF_HAS_EXCEPTIONS throw()
     180             : #define MOZALLOC_THROW_BAD_ALLOC_IF_HAS_EXCEPTIONS throw(std::bad_alloc)
     181             : #endif
     182             : 
     183             : #define MOZALLOC_THROW_BAD_ALLOC MOZALLOC_THROW_BAD_ALLOC_IF_HAS_EXCEPTIONS
     184             : 
     185             : MOZALLOC_EXPORT_NEW
     186             : #if defined(__GNUC__) && !defined(__clang__) && defined(__SANITIZE_ADDRESS__)
     187             : /* gcc's asan somehow doesn't like always_inline on this function. */
     188             : __attribute__((gnu_inline)) inline
     189             : #else
     190             : MOZALLOC_INLINE
     191             : #endif
     192             : void* operator new(size_t size) MOZALLOC_THROW_BAD_ALLOC
     193             : {
     194      177095 :     return moz_xmalloc(size);
     195             : }
     196             : 
     197             : MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
     198             : void* operator new(size_t size, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
     199             : {
     200         168 :     return malloc_impl(size);
     201             : }
     202             : 
     203             : MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
     204             : void* operator new[](size_t size) MOZALLOC_THROW_BAD_ALLOC
     205             : {
     206        8109 :     return moz_xmalloc(size);
     207             : }
     208             : 
     209             : MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
     210             : void* operator new[](size_t size, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
     211             : {
     212           0 :     return malloc_impl(size);
     213             : }
     214             : 
     215             : MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
     216             : void operator delete(void* ptr) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
     217             : {
     218       50846 :     return free_impl(ptr);
     219             : }
     220             : 
     221             : MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
     222             : void operator delete(void* ptr, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
     223             : {
     224        1243 :     return free_impl(ptr);
     225             : }
     226             : 
     227             : MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
     228             : void operator delete[](void* ptr) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
     229             : {
     230        5280 :     return free_impl(ptr);
     231             : }
     232             : 
     233             : MOZALLOC_EXPORT_NEW MOZALLOC_INLINE
     234             : void operator delete[](void* ptr, const std::nothrow_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
     235             : {
     236             :     return free_impl(ptr);
     237             : }
     238             : 
     239             : 
     240             : /*
     241             :  * We also add a new allocator variant: "fallible operator new."
     242             :  * Unlike libmozalloc's implementations of the standard nofail
     243             :  * allocators, this allocator is allowed to return NULL.  It can be used
     244             :  * as follows
     245             :  *
     246             :  *   Foo* f = new (mozilla::fallible) Foo(...);
     247             :  *
     248             :  * operator delete(fallible) is defined for completeness only.
     249             :  *
     250             :  * Each operator new below returns a pointer to memory that can be
     251             :  * delete'd by any of
     252             :  *
     253             :  *   (1) the matching "fallible" operator delete below
     254             :  *   (2) the matching infallible operator delete above
     255             :  *   (3) the matching system |operator delete(void*, std::nothrow)|
     256             :  *   (4) the matching system |operator delete(void*) throw(std::bad_alloc)|
     257             :  */
     258             : 
     259             : MOZALLOC_INLINE
     260             : void* operator new(size_t size, const mozilla::fallible_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
     261             : {
     262           4 :     return malloc_impl(size);
     263             : }
     264             : 
     265             : MOZALLOC_INLINE
     266             : void* operator new[](size_t size, const mozilla::fallible_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
     267             : {
     268        1550 :     return malloc_impl(size);
     269             : }
     270             : 
     271             : MOZALLOC_INLINE
     272             : void operator delete(void* ptr, const mozilla::fallible_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
     273             : {
     274             :     free_impl(ptr);
     275             : }
     276             : 
     277             : MOZALLOC_INLINE
     278             : void operator delete[](void* ptr, const mozilla::fallible_t&) MOZALLOC_THROW_IF_HAS_EXCEPTIONS
     279             : {
     280             :     free_impl(ptr);
     281             : }
     282             : 
     283             : 
     284             : /*
     285             :  * This policy is identical to MallocAllocPolicy, except it uses
     286             :  * moz_xmalloc/moz_xcalloc/moz_xrealloc instead of
     287             :  * malloc/calloc/realloc.
     288             :  */
     289         644 : class InfallibleAllocPolicy
     290             : {
     291             : public:
     292             :     template <typename T>
     293             :     T* maybe_pod_malloc(size_t aNumElems)
     294             :     {
     295             :         return pod_malloc<T>(aNumElems);
     296             :     }
     297             : 
     298             :     template <typename T>
     299          92 :     T* maybe_pod_calloc(size_t aNumElems)
     300             :     {
     301          92 :         return pod_calloc<T>(aNumElems);
     302             :     }
     303             : 
     304             :     template <typename T>
     305             :     T* maybe_pod_realloc(T* aPtr, size_t aOldSize, size_t aNewSize)
     306             :     {
     307             :         return pod_realloc<T>(aPtr, aOldSize, aNewSize);
     308             :     }
     309             : 
     310             :     template <typename T>
     311        2461 :     T* pod_malloc(size_t aNumElems)
     312             :     {
     313         387 :         if (aNumElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
     314           0 :             reportAllocOverflow();
     315             :         }
     316        2461 :         return static_cast<T*>(moz_xmalloc(aNumElems * sizeof(T)));
     317             :     }
     318             : 
     319             :     template <typename T>
     320         397 :     T* pod_calloc(size_t aNumElems)
     321             :     {
     322         397 :         return static_cast<T*>(moz_xcalloc(aNumElems, sizeof(T)));
     323             :     }
     324             : 
     325             :     template <typename T>
     326             :     T* pod_realloc(T* aPtr, size_t aOldSize, size_t aNewSize)
     327             :     {
     328             :         if (aNewSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
     329             :             reportAllocOverflow();
     330             :         }
     331             :         return static_cast<T*>(moz_xrealloc(aPtr, aNewSize * sizeof(T)));
     332             :     }
     333             : 
     334        2425 :     void free_(void* aPtr)
     335             :     {
     336        2425 :         free_impl(aPtr);
     337        2425 :     }
     338             : 
     339           0 :     void reportAllocOverflow() const
     340             :     {
     341           0 :         mozalloc_abort("alloc overflow");
     342             :     }
     343             : 
     344        1609 :     bool checkSimulatedOOM() const
     345             :     {
     346        1609 :         return true;
     347             :     }
     348             : };
     349             : 
     350             : #endif  /* ifdef __cplusplus */
     351             : 
     352             : #ifdef malloc_impl_
     353             : #undef malloc_impl_
     354             : #undef malloc_impl
     355             : #endif
     356             : #ifdef free_impl_
     357             : #undef free_impl_
     358             : #undef free_impl
     359             : #endif
     360             : 
     361             : #endif /* ifndef mozilla_mozalloc_h */

Generated by: LCOV version 1.13