1 // Copyright 2020 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_CPPGC_HEAP_VISITOR_H_ 6 #define V8_HEAP_CPPGC_HEAP_VISITOR_H_ 7 8 #include "src/heap/cppgc/heap-page.h" 9 #include "src/heap/cppgc/heap-space.h" 10 #include "src/heap/cppgc/raw-heap.h" 11 12 namespace cppgc { 13 namespace internal { 14 15 // Visitor for heap, which also implements the accept (traverse) interface. 16 // Implements preorder traversal of the heap. The order of traversal is defined. 17 // Implemented as a CRTP visitor to avoid virtual calls and support better 18 // inlining. 19 template <typename Derived> 20 class HeapVisitor { 21 public: Traverse(RawHeap & heap)22 void Traverse(RawHeap& heap) { 23 if (VisitHeapImpl(heap)) return; 24 for (auto& space : heap) { 25 Traverse(*space.get()); 26 } 27 } 28 Traverse(BaseSpace & space)29 void Traverse(BaseSpace& space) { 30 const bool is_stopped = 31 space.is_large() 32 ? VisitLargePageSpaceImpl(LargePageSpace::From(space)) 33 : VisitNormalPageSpaceImpl(NormalPageSpace::From(space)); 34 if (is_stopped) return; 35 for (auto* page : space) { 36 Traverse(*page); 37 } 38 } 39 Traverse(BasePage & page)40 void Traverse(BasePage& page) { 41 if (page.is_large()) { 42 auto* large_page = LargePage::From(&page); 43 if (VisitLargePageImpl(*large_page)) return; 44 VisitHeapObjectHeaderImpl(*large_page->ObjectHeader()); 45 } else { 46 auto* normal_page = NormalPage::From(&page); 47 if (VisitNormalPageImpl(*normal_page)) return; 48 for (auto& header : *normal_page) { 49 VisitHeapObjectHeaderImpl(header); 50 } 51 } 52 } 53 54 protected: 55 // Visitor functions return true if no deeper processing is required. 56 // Users are supposed to override functions that need special treatment. VisitHeap(RawHeap &)57 bool VisitHeap(RawHeap&) { return false; } VisitNormalPageSpace(NormalPageSpace &)58 bool VisitNormalPageSpace(NormalPageSpace&) { return false; } VisitLargePageSpace(LargePageSpace &)59 bool VisitLargePageSpace(LargePageSpace&) { return false; } VisitNormalPage(NormalPage &)60 bool VisitNormalPage(NormalPage&) { return false; } VisitLargePage(LargePage &)61 bool VisitLargePage(LargePage&) { return false; } VisitHeapObjectHeader(HeapObjectHeader &)62 bool VisitHeapObjectHeader(HeapObjectHeader&) { return false; } 63 64 private: ToDerived()65 Derived& ToDerived() { return static_cast<Derived&>(*this); } 66 VisitHeapImpl(RawHeap & heap)67 bool VisitHeapImpl(RawHeap& heap) { return ToDerived().VisitHeap(heap); } VisitNormalPageSpaceImpl(NormalPageSpace & space)68 bool VisitNormalPageSpaceImpl(NormalPageSpace& space) { 69 return ToDerived().VisitNormalPageSpace(space); 70 } VisitLargePageSpaceImpl(LargePageSpace & space)71 bool VisitLargePageSpaceImpl(LargePageSpace& space) { 72 return ToDerived().VisitLargePageSpace(space); 73 } VisitNormalPageImpl(NormalPage & page)74 bool VisitNormalPageImpl(NormalPage& page) { 75 return ToDerived().VisitNormalPage(page); 76 } VisitLargePageImpl(LargePage & page)77 bool VisitLargePageImpl(LargePage& page) { 78 return ToDerived().VisitLargePage(page); 79 } VisitHeapObjectHeaderImpl(HeapObjectHeader & header)80 bool VisitHeapObjectHeaderImpl(HeapObjectHeader& header) { 81 return ToDerived().VisitHeapObjectHeader(header); 82 } 83 }; 84 85 } // namespace internal 86 } // namespace cppgc 87 88 #endif // V8_HEAP_CPPGC_HEAP_VISITOR_H_ 89