diff --git a/kotlin-native/runtime/src/gc/cms/cpp/Barriers.cpp b/kotlin-native/runtime/src/gc/cms/cpp/Barriers.cpp index 7c40dfac8c0..54d7ed49b76 100644 --- a/kotlin-native/runtime/src/gc/cms/cpp/Barriers.cpp +++ b/kotlin-native/runtime/src/gc/cms/cpp/Barriers.cpp @@ -68,8 +68,7 @@ ALWAYS_INLINE void gc::BarriersThreadData::onAllocation(ObjHeader* allocated) { RuntimeAssert(shouldMark == barriersEnabled, "New allocations marking must happen with and only with weak ref barriers"); if (shouldMark) { auto& objectData = alloc::objectDataForObject(allocated); - bool wasUnmarked = objectData.tryMark(); - RuntimeAssert(wasUnmarked, "No one else could mark this newly allocated object before"); + objectData.markUncontended(); markHandle_->addObject(); } } diff --git a/kotlin-native/runtime/src/gc/cms/cpp/ObjectData.hpp b/kotlin-native/runtime/src/gc/cms/cpp/ObjectData.hpp index 72a9e871ebc..f1cbe7b77f5 100644 --- a/kotlin-native/runtime/src/gc/cms/cpp/ObjectData.hpp +++ b/kotlin-native/runtime/src/gc/cms/cpp/ObjectData.hpp @@ -16,8 +16,16 @@ namespace kotlin::gc { class GC::ObjectData { + static constexpr intptr_t kNoQueueMark = 1; public: - bool tryMark() noexcept { return trySetNext(reinterpret_cast(1)); } + bool tryMark() noexcept { return trySetNext(reinterpret_cast(kNoQueueMark)); } + + void markUncontended() noexcept { + RuntimeAssert(!marked(), "Must not be marked previously"); + auto nextVal = reinterpret_cast(kNoQueueMark); + setNext(nextVal); + RuntimeAssert(next() == nextVal, "Non-atomic marking must not be contended"); + } bool marked() const noexcept { return next() != nullptr; }