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
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6  */
7 
8 /* arena allocation for the frame tree and closely-related objects */
9 
10 #ifndef nsPresArena_h___
11 #define nsPresArena_h___
12 
13 #include "mozilla/ArenaAllocator.h"
14 #include "mozilla/ArenaObjectID.h"
15 #include "mozilla/ArenaRefPtr.h"
16 #include "mozilla/Assertions.h"
17 #include "mozilla/MemoryChecking.h"  // Note: Do not remove this, needed for MOZ_HAVE_MEM_CHECKS below
18 #include "mozilla/MemoryReporting.h"
19 #include <stdint.h>
20 #include "nscore.h"
21 #include "nsDataHashtable.h"
22 #include "nsHashKeys.h"
23 #include "nsTArray.h"
24 #include "nsTHashtable.h"
25 
26 class nsWindowSizes;
27 
28 class nsPresArena {
29  public:
30   nsPresArena();
31   ~nsPresArena();
32 
33   /**
34    * Pool allocation with recycler lists indexed by frame-type ID.
35    * Every aID must always be used with the same object size, aSize.
36    */
AllocateByFrameID(nsQueryFrame::FrameIID aID,size_t aSize)37   void* AllocateByFrameID(nsQueryFrame::FrameIID aID, size_t aSize) {
38     return Allocate(aID, aSize);
39   }
FreeByFrameID(nsQueryFrame::FrameIID aID,void * aPtr)40   void FreeByFrameID(nsQueryFrame::FrameIID aID, void* aPtr) {
41     Free(aID, aPtr);
42   }
43 
44   /**
45    * Pool allocation with recycler lists indexed by object-type ID (see above).
46    * Every aID must always be used with the same object size, aSize.
47    */
AllocateByObjectID(mozilla::ArenaObjectID aID,size_t aSize)48   void* AllocateByObjectID(mozilla::ArenaObjectID aID, size_t aSize) {
49     return Allocate(aID, aSize);
50   }
FreeByObjectID(mozilla::ArenaObjectID aID,void * aPtr)51   void FreeByObjectID(mozilla::ArenaObjectID aID, void* aPtr) {
52     Free(aID, aPtr);
53   }
54 
AllocateByCustomID(uint32_t aID,size_t aSize)55   void* AllocateByCustomID(uint32_t aID, size_t aSize) {
56     return Allocate(aID, aSize);
57   }
FreeByCustomID(uint32_t aID,void * ptr)58   void FreeByCustomID(uint32_t aID, void* ptr) { Free(aID, ptr); }
59 
60   /**
61    * Register an ArenaRefPtr to be cleared when this arena is about to
62    * be destroyed.
63    *
64    * (Defined in ArenaRefPtrInlines.h.)
65    *
66    * @param aPtr The ArenaRefPtr to clear.
67    * @param aObjectID The ArenaObjectID value that uniquely identifies
68    *   the type of object the ArenaRefPtr holds.
69    */
70   template <typename T>
71   void RegisterArenaRefPtr(mozilla::ArenaRefPtr<T>* aPtr);
72 
73   /**
74    * Deregister an ArenaRefPtr that was previously registered with
75    * RegisterArenaRefPtr.
76    */
77   template <typename T>
DeregisterArenaRefPtr(mozilla::ArenaRefPtr<T> * aPtr)78   void DeregisterArenaRefPtr(mozilla::ArenaRefPtr<T>* aPtr) {
79     MOZ_ASSERT(mArenaRefPtrs.Contains(aPtr));
80     mArenaRefPtrs.Remove(aPtr);
81   }
82 
83   /**
84    * Clears all currently registered ArenaRefPtrs.  This will be called during
85    * the destructor, but can be called by users of nsPresArena who want to
86    * ensure arena-allocated objects are released earlier.
87    */
88   void ClearArenaRefPtrs();
89 
90   /**
91    * Clears all currently registered ArenaRefPtrs for the given ArenaObjectID.
92    * This is called when we reconstruct the rule tree so that style contexts
93    * pointing into the old rule tree aren't released afterwards, triggering an
94    * assertion in ~nsStyleContext.
95    */
96   void ClearArenaRefPtrs(mozilla::ArenaObjectID aObjectID);
97 
98   /**
99    * Increment nsWindowSizes with sizes of interesting objects allocated in this
100    * arena.
101    */
102   void AddSizeOfExcludingThis(nsWindowSizes& aWindowSizes) const;
103 
Check()104   void Check() { mPool.Check(); }
105 
106  private:
107   void* Allocate(uint32_t aCode, size_t aSize);
108   void Free(uint32_t aCode, void* aPtr);
109 
110   inline void ClearArenaRefPtrWithoutDeregistering(
111       void* aPtr, mozilla::ArenaObjectID aObjectID);
112 
113   class FreeList {
114    public:
115     nsTArray<void*> mEntries;
116     size_t mEntrySize;
117     size_t mEntriesEverAllocated;
118 
FreeList()119     FreeList() : mEntrySize(0), mEntriesEverAllocated(0) {}
120 
SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf)121     size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
122       return mEntries.ShallowSizeOfExcludingThis(aMallocSizeOf);
123     }
124   };
125 
126   FreeList mFreeLists[mozilla::eArenaObjectID_COUNT];
127   mozilla::ArenaAllocator<8192, 8> mPool;
128   nsDataHashtable<nsPtrHashKey<void>, mozilla::ArenaObjectID> mArenaRefPtrs;
129 };
130 
131 #endif
132