// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_HEAP_CPPGC_HEAP_VISITOR_H_
#define V8_HEAP_CPPGC_HEAP_VISITOR_H_

#include "src/heap/cppgc/heap-page.h"
#include "src/heap/cppgc/heap-space.h"
#include "src/heap/cppgc/raw-heap.h"

namespace cppgc {
namespace internal {

// Visitor for heap, which also implements the accept (traverse) interface.
// Implements preorder traversal of the heap. The order of traversal is defined.
// Implemented as a CRTP visitor to avoid virtual calls and support better
// inlining.
template <typename Derived>
class HeapVisitor {
 public:
  void Traverse(RawHeap* heap) {
    if (VisitHeapImpl(heap)) return;
    for (auto& space : *heap) {
      Traverse(space.get());
    }
  }

  void Traverse(BaseSpace* space) {
    const bool is_stopped =
        space->is_large()
            ? VisitLargePageSpaceImpl(LargePageSpace::From(space))
            : VisitNormalPageSpaceImpl(NormalPageSpace::From(space));
    if (is_stopped) return;
    for (auto* page : *space) {
      Traverse(page);
    }
  }

  void Traverse(BasePage* page) {
    if (page->is_large()) {
      auto* large_page = LargePage::From(page);
      if (VisitLargePageImpl(large_page)) return;
      VisitHeapObjectHeaderImpl(large_page->ObjectHeader());
    } else {
      auto* normal_page = NormalPage::From(page);
      if (VisitNormalPageImpl(normal_page)) return;
      for (auto& header : *normal_page) {
        VisitHeapObjectHeaderImpl(&header);
      }
    }
  }

 protected:
  // Visitor functions return true if no deeper processing is required.
  // Users are supposed to override functions that need special treatment.
  bool VisitHeap(RawHeap*) { return false; }
  bool VisitNormalPageSpace(NormalPageSpace*) { return false; }
  bool VisitLargePageSpace(LargePageSpace*) { return false; }
  bool VisitNormalPage(NormalPage*) { return false; }
  bool VisitLargePage(LargePage*) { return false; }
  bool VisitHeapObjectHeader(HeapObjectHeader*) { return false; }

 private:
  Derived& ToDerived() { return static_cast<Derived&>(*this); }

  bool VisitHeapImpl(RawHeap* heap) { return ToDerived().VisitHeap(heap); }
  bool VisitNormalPageSpaceImpl(NormalPageSpace* space) {
    return ToDerived().VisitNormalPageSpace(space);
  }
  bool VisitLargePageSpaceImpl(LargePageSpace* space) {
    return ToDerived().VisitLargePageSpace(space);
  }
  bool VisitNormalPageImpl(NormalPage* page) {
    return ToDerived().VisitNormalPage(page);
  }
  bool VisitLargePageImpl(LargePage* page) {
    return ToDerived().VisitLargePage(page);
  }
  bool VisitHeapObjectHeaderImpl(HeapObjectHeader* hoh) {
    return ToDerived().VisitHeapObjectHeader(hoh);
  }
};

}  // namespace internal
}  // namespace cppgc

#endif  // V8_HEAP_CPPGC_HEAP_VISITOR_H_
