BaseAlloc.h (2381B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ 4 5 #ifndef BASEALLOC_H 6 #define BASEALLOC_H 7 8 #include "Mutex.h" 9 10 // The base allocator is a simple memory allocator used internally by 11 // mozjemalloc for its own structures. 12 class BaseAlloc { 13 public: 14 constexpr BaseAlloc() {}; 15 16 void Init() MOZ_REQUIRES(gInitLock); 17 18 void* alloc(size_t aSize); 19 20 void* calloc(size_t aNumber, size_t aSize); 21 22 Mutex mMutex; 23 24 struct Stats { 25 size_t mMapped = 0; 26 size_t mCommitted = 0; 27 }; 28 Stats GetStats() MOZ_EXCLUDES(mMutex) { 29 MutexAutoLock lock(mMutex); 30 31 MOZ_ASSERT(mStats.mMapped >= mStats.mCommitted); 32 return mStats; 33 } 34 35 private: 36 // Allocate fresh pages to satsify at least minsize. 37 bool pages_alloc(size_t minsize) MOZ_REQUIRES(mMutex); 38 39 // BaseAlloc uses bump-pointer allocation from mNextAddr. In general 40 // mNextAddr <= mNextDecommitted <= mPastAddr. 41 // 42 // If an allocation would cause mNextAddr > mPastAddr then a new chunk is 43 // required (from pages_alloc()). Else-if an allocation would case 44 // mNextAddr > mNextDecommitted then some of the memory is decommitted and 45 // pages_committ() is needed before the memory can be used. 46 uintptr_t mNextAddr MOZ_GUARDED_BY(mMutex) = 0; 47 uintptr_t mNextDecommitted MOZ_GUARDED_BY(mMutex) = 0; 48 // Address immediately past the current chunk of pages. 49 uintptr_t mPastAddr MOZ_GUARDED_BY(mMutex) = 0; 50 51 Stats mStats MOZ_GUARDED_BY(mMutex); 52 }; 53 54 extern BaseAlloc sBaseAlloc; 55 56 // A specialization of the base allocator with a free list. 57 template <typename T> 58 struct TypedBaseAlloc { 59 static T* sFirstFree; 60 61 static size_t size_of() { return sizeof(T); } 62 63 static T* alloc() { 64 { 65 MutexAutoLock lock(sBaseAlloc.mMutex); 66 T* ret = sFirstFree; 67 if (ret) { 68 sFirstFree = *(T**)ret; 69 return ret; 70 } 71 } 72 73 return (T*)sBaseAlloc.alloc(size_of()); 74 } 75 76 static void dealloc(T* aNode) { 77 MutexAutoLock lock(sBaseAlloc.mMutex); 78 *(T**)aNode = sFirstFree; 79 sFirstFree = aNode; 80 } 81 }; 82 83 template <typename T> 84 T* TypedBaseAlloc<T>::sFirstFree = nullptr; 85 86 template <typename T> 87 struct BaseAllocFreePolicy { 88 void operator()(T* aPtr) { TypedBaseAlloc<T>::dealloc(aPtr); } 89 }; 90 91 #endif /* ! BASEALLOC_H */