LCOV - code coverage report
Current view: top level - js/src/vm - MallocProvider.h (source / functions) Hit Total Coverage
Test: output.info Lines: 40 67 59.7 %
Date: 2017-07-14 16:53:18 Functions: 110 219 50.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : /*
       8             :  * Hierarchy of SpiderMonkey system memory allocators:
       9             :  *
      10             :  *   - System {m,c,re}alloc/new/free: Overridden by jemalloc in most
      11             :  *     environments. Do not use these functions directly.
      12             :  *
      13             :  *   - js_{m,c,re}alloc/new/free: Wraps the system allocators and adds a
      14             :  *     failure injection framework for use by the fuzzers as well as templated,
      15             :  *     typesafe variants. See js/public/Utility.h.
      16             :  *
      17             :  *   - AllocPolicy: An interface for the js allocators, for use with templates.
      18             :  *     These allocators are for system memory whose lifetime is not associated
      19             :  *     with a GC thing. See js/src/jsalloc.h.
      20             :  *
      21             :  *       - SystemAllocPolicy: No extra functionality over bare allocators.
      22             :  *
      23             :  *       - TempAllocPolicy: Adds automatic error reporting to the provided
      24             :  *         JSContext when allocations fail.
      25             :  *
      26             :  *       - RuntimeAllocPolicy: Forwards to the JSRuntime MallocProvider.
      27             :  *
      28             :  *       - ZoneAllocPolicy: Forwards to the Zone MallocProvider.
      29             :  *
      30             :  *   - MallocProvider. A mixin base class that handles automatically updating
      31             :  *     the GC's state in response to allocations that are tied to a GC lifetime
      32             :  *     or are for a particular GC purpose. These allocators must only be used
      33             :  *     for memory that will be freed when a GC thing is swept.
      34             :  *
      35             :  *       - gc::Zone:  Automatically triggers zone GC.
      36             :  *       - JSRuntime: Automatically triggers full GC.
      37             :  *       - JSContext: Dispatches directly to the runtime.
      38             :  */
      39             : 
      40             : #ifndef vm_MallocProvider_h
      41             : #define vm_MallocProvider_h
      42             : 
      43             : #include "mozilla/Attributes.h"
      44             : #include "mozilla/Likely.h"
      45             : 
      46             : #include "js/UniquePtr.h"
      47             : #include "js/Utility.h"
      48             : 
      49             : namespace js {
      50             : 
      51             : template<class Client>
      52          75 : struct MallocProvider
      53             : {
      54             :     template <class T>
      55       94955 :     T* maybe_pod_malloc(size_t numElems) {
      56       94955 :         T* p = js_pod_malloc<T>(numElems);
      57       94955 :         if (MOZ_LIKELY(p))
      58       94955 :             client()->updateMallocCounter(numElems * sizeof(T));
      59       94955 :         return p;
      60             :     }
      61             : 
      62             :     template <class T>
      63       52619 :     T* maybe_pod_calloc(size_t numElems) {
      64       52619 :         T* p = js_pod_calloc<T>(numElems);
      65       52620 :         if (MOZ_LIKELY(p))
      66       52620 :             client()->updateMallocCounter(numElems * sizeof(T));
      67       52620 :         return p;
      68             :     }
      69             : 
      70             :     template <class T>
      71        5835 :     T* maybe_pod_realloc(T* prior, size_t oldSize, size_t newSize) {
      72        5835 :         T* p = js_pod_realloc(prior, oldSize, newSize);
      73        5835 :         if (MOZ_LIKELY(p)) {
      74             :             // For compatibility we do not account for realloc that decreases
      75             :             // previously allocated memory.
      76        5835 :             if (newSize > oldSize)
      77        5801 :                 client()->updateMallocCounter((newSize - oldSize) * sizeof(T));
      78             :         }
      79        5835 :         return p;
      80             :     }
      81             : 
      82             :     template <class T>
      83             :     T* pod_malloc() {
      84             :         return pod_malloc<T>(1);
      85             :     }
      86             : 
      87             :     template <class T>
      88       94956 :     T* pod_malloc(size_t numElems) {
      89       94956 :         T* p = maybe_pod_malloc<T>(numElems);
      90       94956 :         if (MOZ_LIKELY(p))
      91       94956 :             return p;
      92             :         size_t bytes;
      93           0 :         if (MOZ_UNLIKELY(!CalculateAllocSize<T>(numElems, &bytes))) {
      94           0 :             client()->reportAllocationOverflow();
      95           0 :             return nullptr;
      96             :         }
      97           0 :         p = (T*)client()->onOutOfMemory(AllocFunction::Malloc, bytes);
      98           0 :         if (p)
      99           0 :             client()->updateMallocCounter(bytes);
     100           0 :         return p;
     101             :     }
     102             : 
     103             :     template <class T, class U>
     104         723 :     T* pod_malloc_with_extra(size_t numExtra) {
     105             :         size_t bytes;
     106         723 :         if (MOZ_UNLIKELY((!CalculateAllocSizeWithExtra<T, U>(numExtra, &bytes)))) {
     107           0 :             client()->reportAllocationOverflow();
     108           0 :             return nullptr;
     109             :         }
     110         723 :         T* p = static_cast<T*>(js_malloc(bytes));
     111         723 :         if (MOZ_LIKELY(p)) {
     112         723 :             client()->updateMallocCounter(bytes);
     113         723 :             return p;
     114             :         }
     115           0 :         p = (T*)client()->onOutOfMemory(AllocFunction::Malloc, bytes);
     116           0 :         if (p)
     117           0 :             client()->updateMallocCounter(bytes);
     118           0 :         return p;
     119             :     }
     120             : 
     121             :     template <class T>
     122             :     UniquePtr<T[], JS::FreePolicy>
     123        1791 :     make_pod_array(size_t numElems) {
     124        1791 :         return UniquePtr<T[], JS::FreePolicy>(pod_malloc<T>(numElems));
     125             :     }
     126             : 
     127             :     template <class T>
     128             :     T* pod_calloc() {
     129             :         return pod_calloc<T>(1);
     130             :     }
     131             : 
     132             :     template <class T>
     133       52548 :     T* pod_calloc(size_t numElems) {
     134       52548 :         T* p = maybe_pod_calloc<T>(numElems);
     135       52549 :         if (MOZ_LIKELY(p))
     136       52549 :             return p;
     137             :         size_t bytes;
     138           0 :         if (MOZ_UNLIKELY(!CalculateAllocSize<T>(numElems, &bytes))) {
     139           0 :             client()->reportAllocationOverflow();
     140           0 :             return nullptr;
     141             :         }
     142           0 :         p = (T*)client()->onOutOfMemory(AllocFunction::Calloc, bytes);
     143           0 :         if (p)
     144           0 :             client()->updateMallocCounter(bytes);
     145           0 :         return p;
     146             :     }
     147             : 
     148             :     template <class T, class U>
     149             :     T* pod_calloc_with_extra(size_t numExtra) {
     150             :         size_t bytes;
     151             :         if (MOZ_UNLIKELY((!CalculateAllocSizeWithExtra<T, U>(numExtra, &bytes)))) {
     152             :             client()->reportAllocationOverflow();
     153             :             return nullptr;
     154             :         }
     155             :         T* p = static_cast<T*>(js_calloc(bytes));
     156             :         if (p) {
     157             :             client()->updateMallocCounter(bytes);
     158             :             return p;
     159             :         }
     160             :         p = (T*)client()->onOutOfMemory(AllocFunction::Calloc, bytes);
     161             :         if (p)
     162             :             client()->updateMallocCounter(bytes);
     163             :         return p;
     164             :     }
     165             : 
     166             :     template <class T>
     167             :     UniquePtr<T[], JS::FreePolicy>
     168             :     make_zeroed_pod_array(size_t numElems)
     169             :     {
     170             :         return UniquePtr<T[], JS::FreePolicy>(pod_calloc<T>(numElems));
     171             :     }
     172             : 
     173             :     template <class T>
     174        5835 :     T* pod_realloc(T* prior, size_t oldSize, size_t newSize) {
     175        5835 :         T* p = maybe_pod_realloc(prior, oldSize, newSize);
     176        5835 :         if (MOZ_LIKELY(p))
     177        5835 :             return p;
     178             :         size_t bytes;
     179           0 :         if (MOZ_UNLIKELY(!CalculateAllocSize<T>(newSize, &bytes))) {
     180           0 :             client()->reportAllocationOverflow();
     181           0 :             return nullptr;
     182             :         }
     183           0 :         p = (T*)client()->onOutOfMemory(AllocFunction::Realloc, bytes, prior);
     184           0 :         if (p && newSize > oldSize)
     185           0 :             client()->updateMallocCounter((newSize - oldSize) * sizeof(T));
     186           0 :         return p;
     187             :     }
     188             : 
     189       12126 :     JS_DECLARE_NEW_METHODS(new_, pod_malloc<uint8_t>, MOZ_ALWAYS_INLINE)
     190         444 :     JS_DECLARE_MAKE_METHODS(make_unique, new_, MOZ_ALWAYS_INLINE)
     191             : 
     192             :   private:
     193      154227 :     Client* client() { return static_cast<Client*>(this); }
     194             : };
     195             : 
     196             : } /* namespace js */
     197             : 
     198             : #endif /* vm_MallocProvider_h */

Generated by: LCOV version 1.13