LCOV - code coverage report
Current view: top level - js/src/jit - JitAllocPolicy.h (source / functions) Hit Total Coverage
Test: output.info Lines: 86 93 92.5 %
Date: 2017-07-14 16:53:18 Functions: 109 146 74.7 %
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             : #ifndef jit_JitAllocPolicy_h
       8             : #define jit_JitAllocPolicy_h
       9             : 
      10             : #include "mozilla/Attributes.h"
      11             : #include "mozilla/GuardObjects.h"
      12             : #include "mozilla/OperatorNewExtensions.h"
      13             : #include "mozilla/TypeTraits.h"
      14             : 
      15             : #include "jscntxt.h"
      16             : 
      17             : #include "ds/LifoAlloc.h"
      18             : #include "jit/InlineList.h"
      19             : #include "jit/Ion.h"
      20             : 
      21             : namespace js {
      22             : namespace jit {
      23             : 
      24        4007 : class TempAllocator
      25             : {
      26             :     LifoAllocScope lifoScope_;
      27             : 
      28             :   public:
      29             :     // Most infallible JIT allocations are small, so we use a ballast of 16
      30             :     // KiB. And with a ballast of 16 KiB, a chunk size of 32 KiB works well,
      31             :     // because TempAllocators with a peak allocation size of less than 16 KiB
      32             :     // (which is most of them) only have to allocate a single chunk.
      33             :     static const size_t BallastSize;            // 16 KiB
      34             :     static const size_t PreferredLifoChunkSize; // 32 KiB
      35             : 
      36        4660 :     explicit TempAllocator(LifoAlloc* lifoAlloc)
      37        4660 :       : lifoScope_(lifoAlloc)
      38             :     {
      39        4660 :         lifoAlloc->setAsInfallibleByDefault();
      40        4660 :     }
      41             : 
      42       69300 :     void* allocateInfallible(size_t bytes)
      43             :     {
      44       69300 :         return lifoScope_.alloc().allocInfallible(bytes);
      45             :     }
      46             : 
      47       46691 :     MOZ_MUST_USE void* allocate(size_t bytes)
      48             :     {
      49       93382 :         LifoAlloc::AutoFallibleScope fallibleAllocator(lifoAlloc());
      50       46691 :         void* p = lifoScope_.alloc().alloc(bytes);
      51       46691 :         if (!ensureBallast())
      52           0 :             return nullptr;
      53       46691 :         return p;
      54             :     }
      55             : 
      56             :     template <typename T>
      57         175 :     MOZ_MUST_USE T* allocateArray(size_t n)
      58             :     {
      59         350 :         LifoAlloc::AutoFallibleScope fallibleAllocator(lifoAlloc());
      60             :         size_t bytes;
      61         175 :         if (MOZ_UNLIKELY(!CalculateAllocSize<T>(n, &bytes)))
      62           0 :             return nullptr;
      63         175 :         T* p = static_cast<T*>(lifoScope_.alloc().alloc(bytes));
      64         175 :         if (MOZ_UNLIKELY(!ensureBallast()))
      65           0 :             return nullptr;
      66         175 :         return p;
      67             :     }
      68             : 
      69             :     // View this allocator as a fallible allocator.
      70             :     struct Fallible { TempAllocator& alloc; };
      71       22206 :     Fallible fallible() { return { *this }; }
      72             : 
      73       60673 :     LifoAlloc* lifoAlloc() {
      74       60673 :         return &lifoScope_.alloc();
      75             :     }
      76             : 
      77      114959 :     MOZ_MUST_USE bool ensureBallast() {
      78      114959 :         JS_OOM_POSSIBLY_FAIL_BOOL();
      79      114958 :         return lifoScope_.alloc().ensureUnusedApproximate(BallastSize);
      80             :     }
      81             : };
      82             : 
      83             : class JitAllocPolicy
      84             : {
      85             :     TempAllocator& alloc_;
      86             : 
      87             :   public:
      88       58651 :     MOZ_IMPLICIT JitAllocPolicy(TempAllocator& alloc)
      89       58651 :       : alloc_(alloc)
      90       58651 :     {}
      91             :     template <typename T>
      92        7912 :     T* maybe_pod_malloc(size_t numElems) {
      93             :         size_t bytes;
      94        7912 :         if (MOZ_UNLIKELY(!CalculateAllocSize<T>(numElems, &bytes)))
      95           0 :             return nullptr;
      96        7912 :         return static_cast<T*>(alloc_.allocate(bytes));
      97             :     }
      98             :     template <typename T>
      99          42 :     T* maybe_pod_calloc(size_t numElems) {
     100          42 :         T* p = maybe_pod_malloc<T>(numElems);
     101          42 :         if (MOZ_LIKELY(p))
     102          42 :             memset(p, 0, numElems * sizeof(T));
     103          42 :         return p;
     104             :     }
     105             :     template <typename T>
     106        1753 :     T* maybe_pod_realloc(T* p, size_t oldSize, size_t newSize) {
     107        1753 :         T* n = pod_malloc<T>(newSize);
     108        1753 :         if (MOZ_UNLIKELY(!n))
     109           0 :             return n;
     110        1753 :         MOZ_ASSERT(!(oldSize & mozilla::tl::MulOverflowMask<sizeof(T)>::value));
     111        1753 :         memcpy(n, p, Min(oldSize * sizeof(T), newSize * sizeof(T)));
     112        1753 :         return n;
     113             :     }
     114             :     template <typename T>
     115        7870 :     T* pod_malloc(size_t numElems) {
     116        7870 :         return maybe_pod_malloc<T>(numElems);
     117             :     }
     118             :     template <typename T>
     119          39 :     T* pod_calloc(size_t numElems) {
     120          39 :         return maybe_pod_calloc<T>(numElems);
     121             :     }
     122             :     template <typename T>
     123        1753 :     T* pod_realloc(T* ptr, size_t oldSize, size_t newSize) {
     124        1753 :         return maybe_pod_realloc<T>(ptr, oldSize, newSize);
     125             :     }
     126        3495 :     void free_(void* p) {
     127        3495 :     }
     128           0 :     void reportAllocOverflow() const {
     129           0 :     }
     130        7747 :     MOZ_MUST_USE bool checkSimulatedOOM() const {
     131        7747 :         return !js::oom::ShouldFailWithOOM();
     132             :     }
     133             : };
     134             : 
     135             : class AutoJitContextAlloc
     136             : {
     137             :     TempAllocator tempAlloc_;
     138             :     JitContext* jcx_;
     139             :     TempAllocator* prevAlloc_;
     140             : 
     141             :   public:
     142        3871 :     explicit AutoJitContextAlloc(JSContext* cx)
     143        3871 :       : tempAlloc_(&cx->tempLifoAlloc()),
     144        3871 :         jcx_(GetJitContext()),
     145        7742 :         prevAlloc_(jcx_->temp)
     146             :     {
     147        3871 :         jcx_->temp = &tempAlloc_;
     148        3871 :     }
     149             : 
     150        7742 :     ~AutoJitContextAlloc() {
     151        3871 :         MOZ_ASSERT(jcx_->temp == &tempAlloc_);
     152        3871 :         jcx_->temp = prevAlloc_;
     153        3871 :     }
     154             : };
     155             : 
     156      170744 : struct TempObject
     157             : {
     158       22206 :     inline void* operator new(size_t nbytes, TempAllocator::Fallible view) throw() {
     159       22206 :         return view.alloc.allocate(nbytes);
     160             :     }
     161       69300 :     inline void* operator new(size_t nbytes, TempAllocator& alloc) {
     162       69300 :         return alloc.allocateInfallible(nbytes);
     163             :     }
     164             :     template <class T>
     165       19133 :     inline void* operator new(size_t nbytes, T* pos) {
     166             :         static_assert(mozilla::IsConvertible<T*, TempObject*>::value,
     167             :                       "Placement new argument type must inherit from TempObject");
     168       19133 :         return pos;
     169             :     }
     170             :     template <class T>
     171       25725 :     inline void* operator new(size_t nbytes, mozilla::NotNullTag, T* pos) {
     172             :         static_assert(mozilla::IsConvertible<T*, TempObject*>::value,
     173             :                       "Placement new argument type must inherit from TempObject");
     174       25725 :         MOZ_ASSERT(pos);
     175       25725 :         return pos;
     176             :     }
     177             : };
     178             : 
     179             : template <typename T>
     180             : class TempObjectPool
     181             : {
     182             :     TempAllocator* alloc_;
     183             :     InlineForwardList<T> freed_;
     184             : 
     185             :   public:
     186        4503 :     TempObjectPool()
     187        4503 :       : alloc_(nullptr)
     188        4503 :     {}
     189        4503 :     void setAllocator(TempAllocator& alloc) {
     190        4503 :         MOZ_ASSERT(freed_.empty());
     191        4503 :         alloc_ = &alloc;
     192        4503 :     }
     193       19133 :     T* allocate() {
     194       19133 :         MOZ_ASSERT(alloc_);
     195       19133 :         if (freed_.empty())
     196        4915 :             return new(alloc_->fallible()) T();
     197       14218 :         return freed_.popFront();
     198             :     }
     199       19134 :     void free(T* obj) {
     200       19134 :         freed_.pushFront(obj);
     201       19134 :     }
     202             :     void clear() {
     203             :         freed_.clear();
     204             :     }
     205             : };
     206             : 
     207             : } // namespace jit
     208             : } // namespace js
     209             : 
     210             : #endif /* jit_JitAllocPolicy_h */

Generated by: LCOV version 1.13