// 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_MARKING_WORKLISTS_H_
#define V8_HEAP_CPPGC_MARKING_WORKLISTS_H_

#include <unordered_set>

#include "include/cppgc/visitor.h"
#include "src/base/platform/mutex.h"
#include "src/heap/base/worklist.h"
#include "src/heap/cppgc/heap-object-header.h"

namespace cppgc {
namespace internal {

class MarkingWorklists {
 private:
  class V8_EXPORT_PRIVATE ExternalMarkingWorklist {
   public:
    template <AccessMode = AccessMode::kNonAtomic>
    void Push(HeapObjectHeader*);
    template <AccessMode = AccessMode::kNonAtomic>
    void Erase(HeapObjectHeader*);
    template <AccessMode = AccessMode::kNonAtomic>
    bool Contains(HeapObjectHeader*);
    template <AccessMode = AccessMode::kNonAtomic>
    std::unordered_set<HeapObjectHeader*> Extract();
    template <AccessMode = AccessMode::kNonAtomic>
    void Clear();
    template <AccessMode = AccessMode::kNonAtomic>
    bool IsEmpty();

    ~ExternalMarkingWorklist();

   private:
    template <AccessMode>
    struct ConditionalMutexGuard;

    void* operator new(size_t) = delete;
    void* operator new[](size_t) = delete;
    void operator delete(void*) = delete;
    void operator delete[](void*) = delete;

    v8::base::Mutex lock_;
    std::unordered_set<HeapObjectHeader*> objects_;
  };

 public:
  static constexpr int kMutatorThreadId = 0;

  using MarkingItem = cppgc::TraceDescriptor;

  struct WeakCallbackItem {
    cppgc::WeakCallback callback;
    const void* parameter;
  };

  struct ConcurrentMarkingBailoutItem {
    const void* parameter;
    TraceCallback callback;
    size_t bailedout_size;
  };

  struct EphemeronPairItem {
    const void* key;
    TraceDescriptor value_desc;
  };

  // Segment size of 512 entries necessary to avoid throughput regressions.
  // Since the work list is currently a temporary object this is not a problem.
  using MarkingWorklist =
      heap::base::Worklist<MarkingItem, 512 /* local entries */>;
  using NotFullyConstructedWorklist = ExternalMarkingWorklist;
  using PreviouslyNotFullyConstructedWorklist =
      heap::base::Worklist<HeapObjectHeader*, 16 /* local entries */>;
  using WeakCallbackWorklist =
      heap::base::Worklist<WeakCallbackItem, 64 /* local entries */>;
  using WriteBarrierWorklist =
      heap::base::Worklist<HeapObjectHeader*, 64 /*local entries */>;
  using ConcurrentMarkingBailoutWorklist =
      heap::base::Worklist<ConcurrentMarkingBailoutItem,
                           64 /* local entries */>;
  using EphemeronPairsWorklist =
      heap::base::Worklist<EphemeronPairItem, 64 /* local entries */>;
  using WeakContainersWorklist = ExternalMarkingWorklist;

  MarkingWorklist* marking_worklist() { return &marking_worklist_; }
  NotFullyConstructedWorklist* not_fully_constructed_worklist() {
    return &not_fully_constructed_worklist_;
  }
  PreviouslyNotFullyConstructedWorklist*
  previously_not_fully_constructed_worklist() {
    return &previously_not_fully_constructed_worklist_;
  }
  WriteBarrierWorklist* write_barrier_worklist() {
    return &write_barrier_worklist_;
  }
  WeakCallbackWorklist* weak_callback_worklist() {
    return &weak_callback_worklist_;
  }
  ConcurrentMarkingBailoutWorklist* concurrent_marking_bailout_worklist() {
    return &concurrent_marking_bailout_worklist_;
  }
  EphemeronPairsWorklist* discovered_ephemeron_pairs_worklist() {
    return &discovered_ephemeron_pairs_worklist_;
  }
  EphemeronPairsWorklist* ephemeron_pairs_for_processing_worklist() {
    return &ephemeron_pairs_for_processing_worklist_;
  }
  WeakContainersWorklist* weak_containers_worklist() {
    return &weak_containers_worklist_;
  }

  void ClearForTesting();

 private:
  MarkingWorklist marking_worklist_;
  NotFullyConstructedWorklist not_fully_constructed_worklist_;
  PreviouslyNotFullyConstructedWorklist
      previously_not_fully_constructed_worklist_;
  WriteBarrierWorklist write_barrier_worklist_;
  WeakCallbackWorklist weak_callback_worklist_;
  ConcurrentMarkingBailoutWorklist concurrent_marking_bailout_worklist_;
  EphemeronPairsWorklist discovered_ephemeron_pairs_worklist_;
  EphemeronPairsWorklist ephemeron_pairs_for_processing_worklist_;
  WeakContainersWorklist weak_containers_worklist_;
};

template <>
struct MarkingWorklists::ExternalMarkingWorklist::ConditionalMutexGuard<
    AccessMode::kNonAtomic> {
  explicit ConditionalMutexGuard(v8::base::Mutex*) {}
};

template <>
struct MarkingWorklists::ExternalMarkingWorklist::ConditionalMutexGuard<
    AccessMode::kAtomic> {
  explicit ConditionalMutexGuard(v8::base::Mutex* lock) : guard_(lock) {}

 private:
  v8::base::MutexGuard guard_;
};

template <AccessMode mode>
void MarkingWorklists::ExternalMarkingWorklist::Push(HeapObjectHeader* object) {
  DCHECK_NOT_NULL(object);
  ConditionalMutexGuard<mode> guard(&lock_);
  objects_.insert(object);
}

template <AccessMode mode>
void MarkingWorklists::ExternalMarkingWorklist::Erase(
    HeapObjectHeader* object) {
  DCHECK_NOT_NULL(object);
  ConditionalMutexGuard<mode> guard(&lock_);
  objects_.erase(object);
}

template <AccessMode mode>
bool MarkingWorklists::ExternalMarkingWorklist::Contains(
    HeapObjectHeader* object) {
  ConditionalMutexGuard<mode> guard(&lock_);
  return objects_.find(object) != objects_.end();
}

template <AccessMode mode>
std::unordered_set<HeapObjectHeader*>
MarkingWorklists::ExternalMarkingWorklist::Extract() {
  ConditionalMutexGuard<mode> guard(&lock_);
  std::unordered_set<HeapObjectHeader*> extracted;
  std::swap(extracted, objects_);
  DCHECK(objects_.empty());
  return extracted;
}

template <AccessMode mode>
void MarkingWorklists::ExternalMarkingWorklist::Clear() {
  ConditionalMutexGuard<mode> guard(&lock_);
  objects_.clear();
}

template <AccessMode mode>
bool MarkingWorklists::ExternalMarkingWorklist::IsEmpty() {
  ConditionalMutexGuard<mode> guard(&lock_);
  return objects_.empty();
}

}  // namespace internal
}  // namespace cppgc

#endif  // V8_HEAP_CPPGC_MARKING_WORKLISTS_H_
