1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 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 file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef StackArena_h 8 #define StackArena_h 9 10 #include "nsError.h" 11 #include "mozilla/Assertions.h" 12 #include "mozilla/MemoryReporting.h" 13 14 namespace mozilla { 15 16 struct StackBlock; 17 struct StackMark; 18 class AutoStackArena; 19 20 // Private helper class for AutoStackArena. 21 class StackArena { 22 private: 23 friend class AutoStackArena; 24 StackArena(); 25 ~StackArena(); 26 27 // Memory management functions. 28 void* Allocate(size_t aSize); 29 void Push(); 30 void Pop(); 31 32 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; 33 34 // Our current position in memory. 35 size_t mPos; 36 37 // A list of memory blocks. Usually there is only one 38 // but if we overrun our stack size we can get more memory. 39 StackBlock* mBlocks; 40 41 // The current block. 42 StackBlock* mCurBlock; 43 44 // Our stack of mark where push has been called. 45 StackMark* mMarks; 46 47 // The current top of the mark list. 48 uint32_t mStackTop; 49 50 // The size of the mark array. 51 uint32_t mMarkLength; 52 }; 53 54 // Class for stack scoped arena memory allocations. 55 // 56 // Callers who wish to allocate memory whose lifetime corresponds to the 57 // lifetime of a stack-allocated object can use this class. First, 58 // declare an AutoStackArena object on the stack. Then all subsequent 59 // calls to Allocate will allocate memory from an arena pool that will 60 // be freed when that variable goes out of scope. Nesting is allowed. 61 // 62 // Individual allocations cannot exceed StackBlock::MAX_USABLE_SIZE 63 // bytes. 64 // 65 class MOZ_RAII AutoStackArena { 66 public: AutoStackArena()67 AutoStackArena() : mOwnsStackArena(false) { 68 if (!gStackArena) { 69 gStackArena = new StackArena(); 70 mOwnsStackArena = true; 71 } 72 gStackArena->Push(); 73 } 74 ~AutoStackArena()75 ~AutoStackArena() { 76 gStackArena->Pop(); 77 if (mOwnsStackArena) { 78 delete gStackArena; 79 gStackArena = nullptr; 80 } 81 } 82 Allocate(size_t aSize)83 static void* Allocate(size_t aSize) { return gStackArena->Allocate(aSize); } 84 85 private: 86 static StackArena* gStackArena; 87 bool mOwnsStackArena; 88 }; 89 90 } // namespace mozilla 91 92 #endif 93