AtomMarking.h (5178B)
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 #ifndef gc_AtomMarking_h 8 #define gc_AtomMarking_h 9 10 #include "mozilla/Atomics.h" 11 12 #include "NamespaceImports.h" 13 #include "gc/Cell.h" 14 #include "js/Vector.h" 15 #include "threading/ProtectedData.h" 16 17 namespace js { 18 19 class AutoLockGC; 20 class DenseBitmap; 21 22 namespace gc { 23 24 class Arena; 25 class GCRuntime; 26 27 // This class manages state used for marking atoms during GCs. 28 // See AtomMarking.cpp for details. 29 class AtomMarkingRuntime { 30 // Unused arena atom bitmap indexes. 31 js::MainThreadData<Vector<size_t, 0, SystemAllocPolicy>> freeArenaIndexes; 32 33 // Background sweep state for |freeArenaIndexes|. 34 js::GCLockData<Vector<size_t, 0, SystemAllocPolicy>> pendingFreeArenaIndexes; 35 mozilla::Atomic<bool, mozilla::Relaxed> hasPendingFreeArenaIndexes; 36 37 inline void markChildren(Zone* zone, JSAtom*); 38 inline void markChildren(Zone* zone, JS::Symbol* symbol); 39 40 public: 41 // The extent of all allocated and free words in atom mark bitmaps. 42 // This monotonically increases and may be read from without locking. 43 mozilla::Atomic<size_t, mozilla::SequentiallyConsistent> allocatedWords; 44 45 AtomMarkingRuntime() : allocatedWords(0) {} 46 47 // Allocate an index in the atom marking bitmap for a new arena. 48 size_t allocateIndex(GCRuntime* gc); 49 50 // Free an index in the atom marking bitmap. 51 void freeIndex(size_t index, const AutoLockGC& lock); 52 53 void mergePendingFreeArenaIndexes(GCRuntime* gc); 54 55 // Update the atom marking bitmaps in all collected zones according to the 56 // atoms zone mark bits. 57 void refineZoneBitmapsForCollectedZones(GCRuntime* gc); 58 59 // Get a bitmap of all atoms marked in zones that are not being collected by 60 // the current GC. On failure, mark the atoms instead. 61 UniquePtr<DenseBitmap> getOrMarkAtomsUsedByUncollectedZones(GCRuntime* gc); 62 63 // Set any bits in the chunk mark bitmaps for atoms which are marked in 64 // uncollected zones, using the bitmap returned from the previous method. 65 void markAtomsUsedByUncollectedZones(GCRuntime* gc, 66 UniquePtr<DenseBitmap> markedUnion); 67 68 // If gray unmarking fails or GC marking is aborted then the gray bits may end 69 // up in an invalid state. This updates references to all things that could be 70 // gray in the atom marking bitmaps, marking them as black if they were 71 // previously (and perhaps incorrectly) considered gray. This is always safe 72 // but loses information. 73 void unmarkAllGrayReferences(GCRuntime* gc); 74 75 // Get the index into the atom marking bitmaps for the first bit associated 76 // with an atom. 77 // This is public for testing access. 78 static size_t getAtomBit(TenuredCell* thing); 79 80 private: 81 // Fill |bitmap| with an atom marking bitmap based on the things that are 82 // currently marked in the chunks used by atoms zone arenas. This returns 83 // false on an allocation failure (but does not report an exception). 84 bool computeBitmapFromChunkMarkBits(GCRuntime* gc, DenseBitmap& bitmap); 85 86 // Update the overapproximation of the reachable atoms in |zone| in one go 87 // according to the marking state after GC. 88 void refineZoneBitmapForCollectedZone(Zone* zone, const DenseBitmap& bitmap); 89 90 // As above but called per-arena and using the mark bits directly. 91 void refineZoneBitmapForCollectedZone(Zone* zone, Arena* arena); 92 93 public: 94 // Mark an atom or id as being newly reachable by the context's zone. 95 template <typename T> 96 void markAtom(JSContext* cx, T* thing); 97 98 // Version of markAtom that's always inlined, for performance-sensitive 99 // callers. 100 template <typename T, bool Fallible> 101 MOZ_ALWAYS_INLINE bool inlinedMarkAtomInternal(Zone* zone, T* thing); 102 template <typename T> 103 MOZ_ALWAYS_INLINE void inlinedMarkAtom(Zone* zone, T* thing); 104 template <typename T> 105 [[nodiscard]] MOZ_ALWAYS_INLINE bool inlinedMarkAtomFallible(Zone* zone, 106 T* thing); 107 108 void markId(JSContext* cx, jsid id); 109 void markAtomValue(JSContext* cx, const Value& value); 110 111 // Get the mark color of |thing| in the atom marking bitmap for |zone|. 112 template <typename T> 113 CellColor getAtomMarkColor(Zone* zone, T* thing); 114 115 // Return whether |thing/id| is in the atom marking bitmap for |zone|. 116 template <typename T> 117 bool atomIsMarked(Zone* zone, T* thing) { 118 return getAtomMarkColor(zone, thing) != CellColor::White; 119 } 120 121 // For testing purposes, get the mark color associated with |bitIndex| in the 122 // atom marking bitmap for |zone|. 123 CellColor getAtomMarkColorForIndex(Zone* zone, size_t bitIndex); 124 125 // Called during (possibly parallel) marking to unmark possibly-gray symbols. 126 void maybeUnmarkGrayAtomically(Zone* zone, JS::Symbol* symbol); 127 128 #ifdef DEBUG 129 bool idIsMarked(Zone* zone, jsid id); 130 bool valueIsMarked(Zone* zone, const Value& value); 131 #endif 132 }; 133 134 } // namespace gc 135 } // namespace js 136 137 #endif // gc_AtomMarking_h