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