michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef StackArena_h michael@0: #define StackArena_h michael@0: michael@0: #include "nsError.h" michael@0: #include "mozilla/Assertions.h" michael@0: #include "mozilla/MemoryReporting.h" michael@0: #include "mozilla/NullPtr.h" michael@0: michael@0: namespace mozilla { michael@0: michael@0: struct StackBlock; michael@0: struct StackMark; michael@0: class AutoStackArena; michael@0: michael@0: // Private helper class for AutoStackArena. michael@0: class StackArena { michael@0: private: michael@0: friend class AutoStackArena; michael@0: StackArena(); michael@0: ~StackArena(); michael@0: michael@0: nsresult Init() { return mBlocks ? NS_OK : NS_ERROR_OUT_OF_MEMORY; } michael@0: michael@0: // Memory management functions. michael@0: void* Allocate(size_t aSize); michael@0: void Push(); michael@0: void Pop(); michael@0: michael@0: size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; michael@0: michael@0: // Our current position in memory. michael@0: size_t mPos; michael@0: michael@0: // A list of memory blocks. Usually there is only one michael@0: // but if we overrun our stack size we can get more memory. michael@0: StackBlock* mBlocks; michael@0: michael@0: // The current block. michael@0: StackBlock* mCurBlock; michael@0: michael@0: // Our stack of mark where push has been called. michael@0: StackMark* mMarks; michael@0: michael@0: // The current top of the mark list. michael@0: uint32_t mStackTop; michael@0: michael@0: // The size of the mark array. michael@0: uint32_t mMarkLength; michael@0: }; michael@0: michael@0: // Class for stack scoped arena memory allocations. michael@0: // michael@0: // Callers who wish to allocate memory whose lifetime corresponds to the michael@0: // lifetime of a stack-allocated object can use this class. First, michael@0: // declare an AutoStackArena object on the stack. Then all subsequent michael@0: // calls to Allocate will allocate memory from an arena pool that will michael@0: // be freed when that variable goes out of scope. Nesting is allowed. michael@0: // michael@0: // Individual allocations cannot exceed StackBlock::MAX_USABLE_SIZE michael@0: // bytes. michael@0: // michael@0: class MOZ_STACK_CLASS AutoStackArena { michael@0: public: michael@0: AutoStackArena() michael@0: : mOwnsStackArena(false) michael@0: { michael@0: if (!gStackArena) { michael@0: gStackArena = new StackArena(); michael@0: mOwnsStackArena = true; michael@0: gStackArena->Init(); michael@0: } michael@0: gStackArena->Push(); michael@0: } michael@0: michael@0: ~AutoStackArena() { michael@0: gStackArena->Pop(); michael@0: if (mOwnsStackArena) { michael@0: delete gStackArena; michael@0: gStackArena = nullptr; michael@0: } michael@0: } michael@0: michael@0: static void* Allocate(size_t aSize) { michael@0: return gStackArena->Allocate(aSize); michael@0: } michael@0: michael@0: private: michael@0: static StackArena* gStackArena; michael@0: bool mOwnsStackArena; michael@0: }; michael@0: michael@0: } // namespace mozilla michael@0: michael@0: #endif