1 // Copyright 2019 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_HEAP_MARKING_VISITOR_H_ 6 #define V8_HEAP_MARKING_VISITOR_H_ 7 8 #include "src/common/globals.h" 9 #include "src/heap/marking-worklist.h" 10 #include "src/heap/marking.h" 11 #include "src/heap/objects-visiting.h" 12 #include "src/heap/spaces.h" 13 #include "src/heap/worklist.h" 14 #include "src/objects/heap-object.h" // For Worklist<HeapObject, ...> 15 #include "src/objects/js-weak-refs.h" // For Worklist<WeakCell, ...> 16 17 namespace v8 { 18 namespace internal { 19 20 struct Ephemeron { 21 HeapObject key; 22 HeapObject value; 23 }; 24 25 using EphemeronWorklist = Worklist<Ephemeron, 64>; 26 27 // Weak objects encountered during marking. 28 struct WeakObjects { 29 Worklist<TransitionArray, 64> transition_arrays; 30 31 // Keep track of all EphemeronHashTables in the heap to process 32 // them in the atomic pause. 33 Worklist<EphemeronHashTable, 64> ephemeron_hash_tables; 34 35 // Keep track of all ephemerons for concurrent marking tasks. Only store 36 // ephemerons in these Worklists if both key and value are unreachable at the 37 // moment. 38 // 39 // MarkCompactCollector::ProcessEphemeronsUntilFixpoint drains and fills these 40 // worklists. 41 // 42 // current_ephemerons is used as draining worklist in the current fixpoint 43 // iteration. 44 EphemeronWorklist current_ephemerons; 45 46 // Stores ephemerons to visit in the next fixpoint iteration. 47 EphemeronWorklist next_ephemerons; 48 49 // When draining the marking worklist new discovered ephemerons are pushed 50 // into this worklist. 51 EphemeronWorklist discovered_ephemerons; 52 53 // TODO(marja): For old space, we only need the slot, not the host 54 // object. Optimize this by adding a different storage for old space. 55 Worklist<std::pair<HeapObject, HeapObjectSlot>, 64> weak_references; 56 Worklist<std::pair<HeapObject, Code>, 64> weak_objects_in_code; 57 58 Worklist<JSWeakRef, 64> js_weak_refs; 59 Worklist<WeakCell, 64> weak_cells; 60 61 Worklist<SharedFunctionInfo, 64> bytecode_flushing_candidates; 62 Worklist<JSFunction, 64> flushed_js_functions; 63 }; 64 65 struct EphemeronMarking { 66 std::vector<HeapObject> newly_discovered; 67 bool newly_discovered_overflowed; 68 size_t newly_discovered_limit; 69 }; 70 71 template <typename ConcreteState, AccessMode access_mode> 72 class MarkingStateBase { 73 public: MarkBitFrom(HeapObject obj)74 V8_INLINE MarkBit MarkBitFrom(HeapObject obj) { 75 return MarkBitFrom(MemoryChunk::FromHeapObject(obj), obj.ptr()); 76 } 77 78 // {addr} may be tagged or aligned. MarkBitFrom(MemoryChunk * p,Address addr)79 V8_INLINE MarkBit MarkBitFrom(MemoryChunk* p, Address addr) { 80 return static_cast<ConcreteState*>(this)->bitmap(p)->MarkBitFromIndex( 81 p->AddressToMarkbitIndex(addr)); 82 } 83 Color(HeapObject obj)84 Marking::ObjectColor Color(HeapObject obj) { 85 return Marking::Color(MarkBitFrom(obj)); 86 } 87 IsImpossible(HeapObject obj)88 V8_INLINE bool IsImpossible(HeapObject obj) { 89 return Marking::IsImpossible<access_mode>(MarkBitFrom(obj)); 90 } 91 IsBlack(HeapObject obj)92 V8_INLINE bool IsBlack(HeapObject obj) { 93 return Marking::IsBlack<access_mode>(MarkBitFrom(obj)); 94 } 95 IsWhite(HeapObject obj)96 V8_INLINE bool IsWhite(HeapObject obj) { 97 return Marking::IsWhite<access_mode>(MarkBitFrom(obj)); 98 } 99 IsGrey(HeapObject obj)100 V8_INLINE bool IsGrey(HeapObject obj) { 101 return Marking::IsGrey<access_mode>(MarkBitFrom(obj)); 102 } 103 IsBlackOrGrey(HeapObject obj)104 V8_INLINE bool IsBlackOrGrey(HeapObject obj) { 105 return Marking::IsBlackOrGrey<access_mode>(MarkBitFrom(obj)); 106 } 107 WhiteToGrey(HeapObject obj)108 V8_INLINE bool WhiteToGrey(HeapObject obj) { 109 return Marking::WhiteToGrey<access_mode>(MarkBitFrom(obj)); 110 } 111 WhiteToBlack(HeapObject obj)112 V8_INLINE bool WhiteToBlack(HeapObject obj) { 113 return WhiteToGrey(obj) && GreyToBlack(obj); 114 } 115 GreyToBlack(HeapObject obj)116 V8_INLINE bool GreyToBlack(HeapObject obj) { 117 MemoryChunk* p = MemoryChunk::FromHeapObject(obj); 118 MarkBit markbit = MarkBitFrom(p, obj.address()); 119 if (!Marking::GreyToBlack<access_mode>(markbit)) return false; 120 static_cast<ConcreteState*>(this)->IncrementLiveBytes(p, obj.Size()); 121 return true; 122 } 123 ClearLiveness(MemoryChunk * chunk)124 void ClearLiveness(MemoryChunk* chunk) { 125 static_cast<ConcreteState*>(this)->bitmap(chunk)->Clear(); 126 static_cast<ConcreteState*>(this)->SetLiveBytes(chunk, 0); 127 } 128 }; 129 130 // The base class for all marking visitors. It implements marking logic with 131 // support of bytecode flushing, embedder tracing, weak and references. 132 // 133 // Derived classes are expected to provide the following: 134 // - ConcreteVisitor::marking_state method, 135 // - ConcreteVisitor::retaining_path_mode method, 136 // - ConcreteVisitor::RecordSlot method, 137 // - ConcreteVisitor::RecordRelocSlot method, 138 // - ConcreteVisitor::SynchronizePageAccess method, 139 // - ConcreteVisitor::VisitJSObjectSubclass method, 140 // - ConcreteVisitor::VisitLeftTrimmableArray method. 141 // These methods capture the difference between the concurrent and main thread 142 // marking visitors. For example, the concurrent visitor has to use the 143 // snapshotting protocol to visit JSObject and left-trimmable FixedArrays. 144 145 template <typename ConcreteVisitor, typename MarkingState> 146 class MarkingVisitorBase : public HeapVisitor<int, ConcreteVisitor> { 147 public: MarkingVisitorBase(int task_id,MarkingWorklists * marking_worklists,WeakObjects * weak_objects,Heap * heap,unsigned mark_compact_epoch,BytecodeFlushMode bytecode_flush_mode,bool is_embedder_tracing_enabled,bool is_forced_gc)148 MarkingVisitorBase(int task_id, MarkingWorklists* marking_worklists, 149 WeakObjects* weak_objects, Heap* heap, 150 unsigned mark_compact_epoch, 151 BytecodeFlushMode bytecode_flush_mode, 152 bool is_embedder_tracing_enabled, bool is_forced_gc) 153 : marking_worklists_(marking_worklists), 154 weak_objects_(weak_objects), 155 heap_(heap), 156 task_id_(task_id), 157 mark_compact_epoch_(mark_compact_epoch), 158 bytecode_flush_mode_(bytecode_flush_mode), 159 is_embedder_tracing_enabled_(is_embedder_tracing_enabled), 160 is_forced_gc_(is_forced_gc) {} 161 162 V8_INLINE int VisitBytecodeArray(Map map, BytecodeArray object); 163 V8_INLINE int VisitDescriptorArray(Map map, DescriptorArray object); 164 V8_INLINE int VisitEphemeronHashTable(Map map, EphemeronHashTable object); 165 V8_INLINE int VisitFixedArray(Map map, FixedArray object); 166 V8_INLINE int VisitFixedDoubleArray(Map map, FixedDoubleArray object); 167 V8_INLINE int VisitJSApiObject(Map map, JSObject object); 168 V8_INLINE int VisitJSArrayBuffer(Map map, JSArrayBuffer object); 169 V8_INLINE int VisitJSDataView(Map map, JSDataView object); 170 V8_INLINE int VisitJSFunction(Map map, JSFunction object); 171 V8_INLINE int VisitJSTypedArray(Map map, JSTypedArray object); 172 V8_INLINE int VisitJSWeakRef(Map map, JSWeakRef object); 173 V8_INLINE int VisitMap(Map map, Map object); 174 V8_INLINE int VisitSharedFunctionInfo(Map map, SharedFunctionInfo object); 175 V8_INLINE int VisitTransitionArray(Map map, TransitionArray object); 176 V8_INLINE int VisitWeakCell(Map map, WeakCell object); 177 178 // ObjectVisitor overrides. VisitPointer(HeapObject host,ObjectSlot p)179 V8_INLINE void VisitPointer(HeapObject host, ObjectSlot p) final { 180 VisitPointersImpl(host, p, p + 1); 181 } VisitPointer(HeapObject host,MaybeObjectSlot p)182 V8_INLINE void VisitPointer(HeapObject host, MaybeObjectSlot p) final { 183 VisitPointersImpl(host, p, p + 1); 184 } VisitPointers(HeapObject host,ObjectSlot start,ObjectSlot end)185 V8_INLINE void VisitPointers(HeapObject host, ObjectSlot start, 186 ObjectSlot end) final { 187 VisitPointersImpl(host, start, end); 188 } VisitPointers(HeapObject host,MaybeObjectSlot start,MaybeObjectSlot end)189 V8_INLINE void VisitPointers(HeapObject host, MaybeObjectSlot start, 190 MaybeObjectSlot end) final { 191 VisitPointersImpl(host, start, end); 192 } 193 V8_INLINE void VisitEmbeddedPointer(Code host, RelocInfo* rinfo) final; 194 V8_INLINE void VisitCodeTarget(Code host, RelocInfo* rinfo) final; VisitCustomWeakPointers(HeapObject host,ObjectSlot start,ObjectSlot end)195 void VisitCustomWeakPointers(HeapObject host, ObjectSlot start, 196 ObjectSlot end) final { 197 // Weak list pointers should be ignored during marking. The lists are 198 // reconstructed after GC. 199 } 200 201 protected: concrete_visitor()202 ConcreteVisitor* concrete_visitor() { 203 return static_cast<ConcreteVisitor*>(this); 204 } 205 template <typename THeapObjectSlot> 206 void ProcessStrongHeapObject(HeapObject host, THeapObjectSlot slot, 207 HeapObject heap_object); 208 template <typename THeapObjectSlot> 209 void ProcessWeakHeapObject(HeapObject host, THeapObjectSlot slot, 210 HeapObject heap_object); 211 212 template <typename TSlot> 213 V8_INLINE void VisitPointerImpl(HeapObject host, TSlot p); 214 215 template <typename TSlot> 216 V8_INLINE void VisitPointersImpl(HeapObject host, TSlot start, TSlot end); 217 218 V8_INLINE void VisitDescriptors(DescriptorArray descriptors, 219 int number_of_own_descriptors); 220 template <typename T> 221 int VisitEmbedderTracingSubclass(Map map, T object); 222 V8_INLINE int VisitFixedArrayWithProgressBar(Map map, FixedArray object, 223 MemoryChunk* chunk); 224 // Marks the descriptor array black without pushing it on the marking work 225 // list and visits its header. Returns the size of the descriptor array 226 // if it was successully marked as black. 227 V8_INLINE size_t MarkDescriptorArrayBlack(HeapObject host, 228 DescriptorArray descriptors); 229 // Marks the object grey and pushes it on the marking work list. 230 V8_INLINE void MarkObject(HeapObject host, HeapObject obj); 231 232 MarkingWorklists* const marking_worklists_; 233 WeakObjects* const weak_objects_; 234 Heap* const heap_; 235 const int task_id_; 236 const unsigned mark_compact_epoch_; 237 const BytecodeFlushMode bytecode_flush_mode_; 238 const bool is_embedder_tracing_enabled_; 239 const bool is_forced_gc_; 240 }; 241 242 } // namespace internal 243 } // namespace v8 244 245 #endif // V8_HEAP_MARKING_VISITOR_H_ 246