BaseAlloc.cpp (2247B)
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 #include "BaseAlloc.h" 6 7 #include <cstring> 8 9 #include "Globals.h" 10 11 using namespace mozilla; 12 13 constinit BaseAlloc sBaseAlloc; 14 15 // Initialize base allocation data structures. 16 void BaseAlloc::Init() MOZ_REQUIRES(gInitLock) { mMutex.Init(); } 17 18 bool BaseAlloc::pages_alloc(size_t minsize) MOZ_REQUIRES(mMutex) { 19 MOZ_ASSERT(minsize != 0); 20 size_t csize = CHUNK_CEILING(minsize); 21 uintptr_t base_pages = 22 reinterpret_cast<uintptr_t>(chunk_alloc(csize, kChunkSize, true)); 23 if (base_pages == 0) { 24 return false; 25 } 26 mNextAddr = reinterpret_cast<uintptr_t>(base_pages); 27 mPastAddr = base_pages + csize; 28 // Leave enough pages for minsize committed, since otherwise they would 29 // have to be immediately recommitted. 30 size_t pminsize = REAL_PAGE_CEILING(minsize); 31 mNextDecommitted = base_pages + pminsize; 32 if (pminsize < csize) { 33 pages_decommit(reinterpret_cast<void*>(mNextDecommitted), csize - pminsize); 34 } 35 mStats.mMapped += csize; 36 mStats.mCommitted += pminsize; 37 38 return true; 39 } 40 41 void* BaseAlloc::alloc(size_t aSize) { 42 // Round size up to nearest multiple of the cacheline size. 43 size_t csize = CACHELINE_CEILING(aSize); 44 45 MutexAutoLock lock(mMutex); 46 // Make sure there's enough space for the allocation. 47 if (mNextAddr + csize > mPastAddr) { 48 if (!pages_alloc(csize)) { 49 return nullptr; 50 } 51 } 52 // Allocate. 53 void* ret = reinterpret_cast<void*>(mNextAddr); 54 mNextAddr = mNextAddr + csize; 55 // Make sure enough pages are committed for the new allocation. 56 if (mNextAddr > mNextDecommitted) { 57 uintptr_t pbase_next_addr = REAL_PAGE_CEILING(mNextAddr); 58 59 if (!pages_commit(reinterpret_cast<void*>(mNextDecommitted), 60 mNextAddr - mNextDecommitted)) { 61 return nullptr; 62 } 63 64 mStats.mCommitted += pbase_next_addr - mNextDecommitted; 65 mNextDecommitted = pbase_next_addr; 66 } 67 68 return ret; 69 } 70 71 void* BaseAlloc::calloc(size_t aNumber, size_t aSize) { 72 void* ret = alloc(aNumber * aSize); 73 if (ret) { 74 memset(ret, 0, aNumber * aSize); 75 } 76 return ret; 77 }