diff --git a/kotlin-native/runtime/src/gc/cms/cpp/ConcurrentMarkAndSweep.cpp b/kotlin-native/runtime/src/gc/cms/cpp/ConcurrentMarkAndSweep.cpp index 86ed8fc34b4..6cd0e1d9a47 100644 --- a/kotlin-native/runtime/src/gc/cms/cpp/ConcurrentMarkAndSweep.cpp +++ b/kotlin-native/runtime/src/gc/cms/cpp/ConcurrentMarkAndSweep.cpp @@ -180,8 +180,8 @@ bool gc::ConcurrentMarkAndSweep::PerformFullGC(int64_t epoch) noexcept { scheduler.gcData().UpdateAliveSetBytes(markStats.totalObjectsSize); #ifndef CUSTOM_ALLOCATOR - mm::ExtraObjectDataFactory& extraObjectDataFactory = mm::GlobalData::Instance().extraObjectDataFactory(); - gc::SweepExtraObjects(gcHandle, extraObjectDataFactory); + auto extraObjectFactoryIterable = mm::GlobalData::Instance().extraObjectDataFactory().LockForIter(); + gc::SweepExtraObjects(gcHandle, extraObjectFactoryIterable); auto objectFactoryIterable = objectFactory_.LockForIter(); mm::ResumeThreads(); diff --git a/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtils.hpp b/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtils.hpp index 7aa968ed07e..333f7304359 100644 --- a/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtils.hpp +++ b/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtils.hpp @@ -108,11 +108,10 @@ void Mark(GCHandle handle, typename Traits::MarkQueue& markQueue) noexcept { } template -void SweepExtraObjects(GCHandle handle, typename Traits::ExtraObjectsFactory& objectFactory) noexcept { - objectFactory.ProcessDeletions(); +void SweepExtraObjects(GCHandle handle, typename Traits::ExtraObjectsFactory::Iterable& factoryIter) noexcept { auto sweepHandle = handle.sweepExtraObjects(); - auto iter = objectFactory.LockForIter(); - for (auto it = iter.begin(); it != iter.end();) { + factoryIter.ApplyDeletions(); + for (auto it = factoryIter.begin(); it != factoryIter.end();) { auto &extraObject = *it; if (!extraObject.getFlag(mm::ExtraObjectData::FLAGS_IN_FINALIZER_QUEUE) && !Traits::IsMarkedByExtraObject(extraObject)) { extraObject.ClearWeakReferenceCounter(); @@ -122,7 +121,7 @@ void SweepExtraObjects(GCHandle handle, typename Traits::ExtraObjectsFactory& ob ++it; } else { extraObject.Uninstall(); - objectFactory.EraseAndAdvance(it); + it.EraseAndAdvance(); } } else { ++it; @@ -130,6 +129,12 @@ void SweepExtraObjects(GCHandle handle, typename Traits::ExtraObjectsFactory& ob } } +template +void SweepExtraObjects(GCHandle handle, typename Traits::ExtraObjectsFactory& factory) noexcept { + auto iter = factory.LockForIter(); + return SweepExtraObjects(handle, iter); +} + template typename Traits::ObjectFactory::FinalizerQueue Sweep(GCHandle handle, typename Traits::ObjectFactory::Iterable& objectFactoryIter) noexcept { typename Traits::ObjectFactory::FinalizerQueue finalizerQueue; diff --git a/kotlin-native/runtime/src/main/cpp/MultiSourceQueue.hpp b/kotlin-native/runtime/src/main/cpp/MultiSourceQueue.hpp index e4eac71d46b..b591d6914f0 100644 --- a/kotlin-native/runtime/src/main/cpp/MultiSourceQueue.hpp +++ b/kotlin-native/runtime/src/main/cpp/MultiSourceQueue.hpp @@ -38,6 +38,7 @@ public: explicit Node(Producer* owner, Args&& ...args) noexcept : value_(std::forward(args)...), owner_(owner) {} T& operator*() noexcept { return value_; } + T* operator->() noexcept { return &value_; } static Node& fromValue(T& t) noexcept { static_assert(std::is_base_of_v, "fromValue function only makes sense for non-movable object"); @@ -111,12 +112,15 @@ public: class Iterator { public: T& operator*() noexcept { return **position_; } + T* operator->() noexcept { return &*this; } Iterator& operator++() noexcept { ++position_; return *this; } + void EraseAndAdvance() noexcept { owner_->EraseAndAdvance(*this); } + bool operator==(const Iterator& rhs) const noexcept { return position_ == rhs.position_; } bool operator!=(const Iterator& rhs) const noexcept { return position_ != rhs.position_; } @@ -124,15 +128,18 @@ public: private: friend class MultiSourceQueue; - explicit Iterator(const typename List::iterator& position) noexcept : position_(position) {} + Iterator(MultiSourceQueue& owner, const typename List::iterator& position) noexcept : owner_(&owner), position_(position) {} + MultiSourceQueue* owner_; typename List::iterator position_; }; class Iterable : MoveOnly { public: - Iterator begin() noexcept { return Iterator(owner_.queue_.begin()); } - Iterator end() noexcept { return Iterator(owner_.queue_.end()); } + Iterator begin() noexcept { return Iterator(owner_, owner_.queue_.begin()); } + Iterator end() noexcept { return Iterator(owner_, owner_.queue_.end()); } + + void ApplyDeletions() noexcept { owner_.ApplyDeletionsUnsafe(); } private: friend class MultiSourceQueue; @@ -152,6 +159,22 @@ public: // Lock `MultiSourceQueue` and apply deletions. Only deletes elements that were published. void ApplyDeletions() noexcept { std::lock_guard guard(mutex_); + ApplyDeletionsUnsafe(); + } + + // requires LockForIter + void EraseAndAdvance(Iterator& it) { it.position_ = queue_.erase(it.position_); } + + void ClearForTests() noexcept { + queue_.clear(); + deletionQueue_.clear(); + } + + size_t GetSizeUnsafe() noexcept { return queue_.size(); } + +private: + // Requires a lock to be taken externally. + void ApplyDeletionsUnsafe() noexcept { List remainingDeletions(deletionQueue_.get_allocator()); auto it = deletionQueue_.begin(); @@ -172,21 +195,6 @@ public: deletionQueue_ = std::move(remainingDeletions); } - // requires LockForIter - void EraseAndAdvance(Iterator &it) { - it.position_ = queue_.erase(it.position_); - } - - void ClearForTests() noexcept { - queue_.clear(); - deletionQueue_.clear(); - } - - size_t GetSizeUnsafe() noexcept { - return queue_.size(); - } - -private: List queue_; List deletionQueue_; Mutex mutex_;