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 * hoh)80 bool VisitHeapObjectHeaderImpl(HeapObjectHeader* hoh) { 81 return ToDerived().VisitHeapObjectHeader(hoh); 82 } 83 }; 84 85 } // namespace internal 86 } // namespace cppgc 87 88 #endif // V8_HEAP_CPPGC_HEAP_VISITOR_H_ 89