// 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.

#include "src/heap/cppgc/marking-visitor.h"

#include "src/heap/cppgc/heap.h"
#include "src/heap/cppgc/marking-state.h"

namespace cppgc {
namespace internal {

MarkingVisitorBase::MarkingVisitorBase(HeapBase& heap,
                                       MarkingStateBase& marking_state)
    : marking_state_(marking_state) {}

void MarkingVisitorBase::Visit(const void* object, TraceDescriptor desc) {
  marking_state_.MarkAndPush(object, desc);
}

void MarkingVisitorBase::VisitWeak(const void* object, TraceDescriptor desc,
                                   WeakCallback weak_callback,
                                   const void* weak_member) {
  marking_state_.RegisterWeakReferenceIfNeeded(object, desc, weak_callback,
                                               weak_member);
}

void MarkingVisitorBase::VisitEphemeron(const void* key,
                                        TraceDescriptor value_desc) {
  marking_state_.ProcessEphemeron(key, value_desc);
}

void MarkingVisitorBase::VisitWeakContainer(const void* object,
                                            TraceDescriptor strong_desc,
                                            TraceDescriptor weak_desc,
                                            WeakCallback callback,
                                            const void* data) {
  marking_state_.ProcessWeakContainer(object, weak_desc, callback, data);
}

void MarkingVisitorBase::RegisterWeakCallback(WeakCallback callback,
                                              const void* object) {
  marking_state_.RegisterWeakCallback(callback, object);
}

void MarkingVisitorBase::HandleMovableReference(const void** slot) {
  marking_state_.RegisterMovableReference(slot);
}

ConservativeMarkingVisitor::ConservativeMarkingVisitor(
    HeapBase& heap, MutatorMarkingState& marking_state, cppgc::Visitor& visitor)
    : ConservativeTracingVisitor(heap, *heap.page_backend(), visitor),
      marking_state_(marking_state) {}

void ConservativeMarkingVisitor::VisitFullyConstructedConservatively(
    HeapObjectHeader& header) {
  if (header.IsMarked()) {
    if (marking_state_.IsMarkedWeakContainer(header))
      marking_state_.PushMarkedWeakContainer(header);
    return;
  }
  ConservativeTracingVisitor::VisitFullyConstructedConservatively(header);
}

void ConservativeMarkingVisitor::VisitInConstructionConservatively(
    HeapObjectHeader& header, TraceConservativelyCallback callback) {
  DCHECK(!marking_state_.IsMarkedWeakContainer(header));
  marking_state_.MarkNoPush(header);
  marking_state_.AccountMarkedBytes(header);
  callback(this, header);
}

MutatorMarkingVisitor::MutatorMarkingVisitor(HeapBase& heap,
                                             MutatorMarkingState& marking_state)
    : MarkingVisitorBase(heap, marking_state) {}

void MutatorMarkingVisitor::VisitRoot(const void* object, TraceDescriptor desc,
                                      const SourceLocation&) {
  Visit(object, desc);
}

void MutatorMarkingVisitor::VisitWeakRoot(const void* object,
                                          TraceDescriptor desc,
                                          WeakCallback weak_callback,
                                          const void* weak_root,
                                          const SourceLocation&) {
  static_cast<MutatorMarkingState&>(marking_state_)
      .InvokeWeakRootsCallbackIfNeeded(object, desc, weak_callback, weak_root);
}

ConcurrentMarkingVisitor::ConcurrentMarkingVisitor(
    HeapBase& heap, ConcurrentMarkingState& marking_state)
    : MarkingVisitorBase(heap, marking_state) {}

void ConservativeMarkingVisitor::VisitPointer(const void* address) {
  TraceConservativelyIfNeeded(address);
}

bool ConcurrentMarkingVisitor::DeferTraceToMutatorThreadIfConcurrent(
    const void* parameter, TraceCallback callback, size_t deferred_size) {
  marking_state_.concurrent_marking_bailout_worklist().Push(
      {parameter, callback, deferred_size});
  static_cast<ConcurrentMarkingState&>(marking_state_)
      .AccountDeferredMarkedBytes(deferred_size);
  return true;
}

}  // namespace internal
}  // namespace cppgc
