// 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 #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 void Push(HeapObjectHeader*); template bool Contains(HeapObjectHeader*); template std::unordered_set Extract(); template void Clear(); template bool IsEmpty(); ~ExternalMarkingWorklist(); private: template 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 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; const void* value; 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; using NotFullyConstructedWorklist = ExternalMarkingWorklist; using PreviouslyNotFullyConstructedWorklist = heap::base::Worklist; using WeakCallbackWorklist = heap::base::Worklist; using WriteBarrierWorklist = heap::base::Worklist; using ConcurrentMarkingBailoutWorklist = heap::base::Worklist; using EphemeronPairsWorklist = heap::base::Worklist; using WeakContainersWorklist = ExternalMarkingWorklist; using RetraceMarkedObjectsWorklist = heap::base::Worklist; MarkingWorklist* marking_worklist() { return &marking_worklist_; } NotFullyConstructedWorklist* not_fully_constructed_worklist() { return ¬_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_; } RetraceMarkedObjectsWorklist* retrace_marked_objects_worklist() { return &retrace_marked_objects_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_; RetraceMarkedObjectsWorklist retrace_marked_objects_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 void MarkingWorklists::ExternalMarkingWorklist::Push(HeapObjectHeader* object) { DCHECK_NOT_NULL(object); ConditionalMutexGuard guard(&lock_); objects_.insert(object); } template bool MarkingWorklists::ExternalMarkingWorklist::Contains( HeapObjectHeader* object) { ConditionalMutexGuard guard(&lock_); return objects_.find(object) != objects_.end(); } template std::unordered_set MarkingWorklists::ExternalMarkingWorklist::Extract() { ConditionalMutexGuard guard(&lock_); std::unordered_set extracted; std::swap(extracted, objects_); DCHECK(objects_.empty()); return extracted; } template void MarkingWorklists::ExternalMarkingWorklist::Clear() { ConditionalMutexGuard guard(&lock_); objects_.clear(); } template bool MarkingWorklists::ExternalMarkingWorklist::IsEmpty() { ConditionalMutexGuard guard(&lock_); return objects_.empty(); } } // namespace internal } // namespace cppgc #endif // V8_HEAP_CPPGC_MARKING_WORKLISTS_H_