From 421ad777403d57268bf437bbe08e8b80ccf9556e Mon Sep 17 00:00:00 2001 From: Alexander Shabalin Date: Thu, 31 Mar 2022 09:43:47 +0000 Subject: [PATCH] [K/N] Simplify ObjectFactory ^KT-51436 Merge-request: KT-MR-5958 Merged-by: Alexander Shabalin --- .../src/gc/cms/cpp/ConcurrentMarkAndSweep.cpp | 6 +- .../gc/cms/cpp/ConcurrentMarkAndSweepTest.cpp | 6 +- .../runtime/src/gc/cms/cpp/GCImpl.hpp | 2 +- .../src/gc/common/cpp/MarkAndSweepUtils.hpp | 2 +- .../common/cpp/MarkAndSweepUtilsSweepTest.cpp | 81 +++++++++---------- .../runtime/src/gc/noop/cpp/GCImpl.hpp | 2 +- .../runtime/src/gc/stms/cpp/GCImpl.hpp | 2 +- .../gc/stms/cpp/SameThreadMarkAndSweep.cpp | 6 +- .../stms/cpp/SameThreadMarkAndSweepTest.cpp | 6 +- kotlin-native/runtime/src/main/cpp/Memory.h | 1 + .../runtime/src/mm/cpp/ObjectFactory.hpp | 34 +++----- .../runtime/src/mm/cpp/ObjectFactoryTest.cpp | 60 +++++--------- 12 files changed, 85 insertions(+), 123 deletions(-) diff --git a/kotlin-native/runtime/src/gc/cms/cpp/ConcurrentMarkAndSweep.cpp b/kotlin-native/runtime/src/gc/cms/cpp/ConcurrentMarkAndSweep.cpp index 521f057cd96..b76a448289b 100644 --- a/kotlin-native/runtime/src/gc/cms/cpp/ConcurrentMarkAndSweep.cpp +++ b/kotlin-native/runtime/src/gc/cms/cpp/ConcurrentMarkAndSweep.cpp @@ -42,7 +42,7 @@ struct MarkTraits { } static void enqueue(MarkQueue& queue, ObjHeader* object) noexcept { - auto& objectData = mm::ObjectFactory::NodeRef::From(object).GCObjectData(); + auto& objectData = mm::ObjectFactory::NodeRef::From(object).ObjectData(); if (objectData.color() == gc::ConcurrentMarkAndSweep::ObjectData::Color::kBlack) return; objectData.setColor(gc::ConcurrentMarkAndSweep::ObjectData::Color::kBlack); queue.push_back(object); @@ -56,12 +56,12 @@ struct SweepTraits { static bool IsMarkedByExtraObject(mm::ExtraObjectData &object) noexcept { auto *baseObject = object.GetBaseObject(); if (!baseObject->heap()) return true; - auto& objectData = mm::ObjectFactory::NodeRef::From(baseObject).GCObjectData(); + auto& objectData = mm::ObjectFactory::NodeRef::From(baseObject).ObjectData(); return objectData.color() == gc::ConcurrentMarkAndSweep::ObjectData::Color::kBlack; } static bool TryResetMark(ObjectFactory::NodeRef node) noexcept { - auto& objectData = node.GCObjectData(); + auto& objectData = node.ObjectData(); if (objectData.color() == gc::ConcurrentMarkAndSweep::ObjectData::Color::kWhite) return false; objectData.setColor(gc::ConcurrentMarkAndSweep::ObjectData::Color::kWhite); return true; diff --git a/kotlin-native/runtime/src/gc/cms/cpp/ConcurrentMarkAndSweepTest.cpp b/kotlin-native/runtime/src/gc/cms/cpp/ConcurrentMarkAndSweepTest.cpp index 03ef0e734a4..d02dbef0c25 100644 --- a/kotlin-native/runtime/src/gc/cms/cpp/ConcurrentMarkAndSweepTest.cpp +++ b/kotlin-native/runtime/src/gc/cms/cpp/ConcurrentMarkAndSweepTest.cpp @@ -190,10 +190,10 @@ test_support::Object& AllocateObjectWithFinalizer(mm::ThreadData& threa KStdVector Alive(mm::ThreadData& threadData) { KStdVector objects; for (auto node : threadData.gc().impl().objectFactoryThreadQueue()) { - objects.push_back(node.IsArray() ? node.GetArrayHeader()->obj() : node.GetObjHeader()); + objects.push_back(node.GetObjHeader()); } for (auto node : mm::GlobalData::Instance().gc().impl().objectFactory().LockForIter()) { - objects.push_back(node.IsArray() ? node.GetArrayHeader()->obj() : node.GetObjHeader()); + objects.push_back(node.GetObjHeader()); } return objects; } @@ -202,7 +202,7 @@ using Color = gc::ConcurrentMarkAndSweep::ObjectData::Color; Color GetColor(ObjHeader* objHeader) { auto nodeRef = mm::ObjectFactory::NodeRef::From(objHeader); - return nodeRef.GCObjectData().color(); + return nodeRef.ObjectData().color(); } WeakCounter& InstallWeakCounter(mm::ThreadData& threadData, ObjHeader* objHeader, ObjHeader** location) { diff --git a/kotlin-native/runtime/src/gc/cms/cpp/GCImpl.hpp b/kotlin-native/runtime/src/gc/cms/cpp/GCImpl.hpp index 61ffee7f1d0..1ed08685770 100644 --- a/kotlin-native/runtime/src/gc/cms/cpp/GCImpl.hpp +++ b/kotlin-native/runtime/src/gc/cms/cpp/GCImpl.hpp @@ -33,7 +33,7 @@ public: Impl(GC& gc, mm::ThreadData& threadData) noexcept : gcScheduler_(gc.impl_->gcScheduler().NewThreadData()), gc_(gc.impl_->gc(), threadData, gcScheduler_), - objectFactoryThreadQueue_(gc.impl_->objectFactory(), gc_) {} + objectFactoryThreadQueue_(gc.impl_->objectFactory(), gc_.CreateAllocator()) {} GCSchedulerThreadData& gcScheduler() noexcept { return gcScheduler_; } GCImpl::ThreadData& gc() noexcept { return gc_; } diff --git a/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtils.hpp b/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtils.hpp index bb0dee15229..a37cb5ab10c 100644 --- a/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtils.hpp +++ b/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtils.hpp @@ -91,7 +91,7 @@ typename Traits::ObjectFactory::FinalizerQueue Sweep(typename Traits::ObjectFact ++it; continue; } - auto* objHeader = it->IsArray() ? it->GetArrayHeader()->obj() : it->GetObjHeader(); + auto* objHeader = it->GetObjHeader(); if (HasFinalizers(objHeader)) { objectFactoryIter.MoveAndAdvance(finalizerQueue, it); } else { diff --git a/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtilsSweepTest.cpp b/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtilsSweepTest.cpp index 05c5ffbe6ba..a79ff6efc30 100644 --- a/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtilsSweepTest.cpp +++ b/kotlin-native/runtime/src/gc/common/cpp/MarkAndSweepUtilsSweepTest.cpp @@ -44,7 +44,7 @@ test_support::TypeInfoHolder typeHolder{test_support::TypeInfoHolder::ObjectBuil test_support::TypeInfoHolder typeHolderWithFinalizer{test_support::TypeInfoHolder::ObjectBuilder().addFlag(TF_HAS_FINALIZER)}; test_support::TypeInfoHolder typeHolderWeakCounter{test_support::TypeInfoHolder::ObjectBuilder()}; -struct GC { +struct ObjectFactoryTraits { struct ObjectData { enum class State { kUnmarked, @@ -55,15 +55,9 @@ struct GC { }; using Allocator = gc::AlignedAllocator; - - struct ThreadData { - void SafePointAllocation(size_t) {} - void OnOOM(size_t) {} - Allocator CreateAllocator() { return Allocator(); } - }; }; -using ObjectFactory = mm::ObjectFactory; +using ObjectFactory = mm::ObjectFactory; using ExtraObjectsDataFactory = mm::ExtraObjectDataFactory; class Object : public test_support::Object { @@ -82,12 +76,12 @@ public: return false; } - void Mark() { objectData().state = GC::ObjectData::State::kMarked; } + void Mark() { objectData().state = ObjectFactoryTraits::ObjectData::State::kMarked; } - GC::ObjectData::State state() { return objectData().state; } + ObjectFactoryTraits::ObjectData::State state() { return objectData().state; } private: - GC::ObjectData& objectData() { return ObjectFactory::NodeRef::From(header()).GCObjectData(); } + ObjectFactoryTraits::ObjectData& objectData() { return ObjectFactory::NodeRef::From(header()).ObjectData(); } }; class ObjectArray : public test_support::ObjectArray<3> { @@ -107,12 +101,12 @@ public: return false; } - void Mark() { objectData().state = GC::ObjectData::State::kMarked; } + void Mark() { objectData().state = ObjectFactoryTraits::ObjectData::State::kMarked; } - GC::ObjectData::State state() { return objectData().state; } + ObjectFactoryTraits::ObjectData::State state() { return objectData().state; } private: - GC::ObjectData& objectData() { return ObjectFactory::NodeRef::From(header()).GCObjectData(); } + ObjectFactoryTraits::ObjectData& objectData() { return ObjectFactory::NodeRef::From(header()).ObjectData(); } }; class CharArray : public test_support::CharArray<3> { @@ -132,22 +126,22 @@ public: return false; } - void Mark() { objectData().state = GC::ObjectData::State::kMarked; } + void Mark() { objectData().state = ObjectFactoryTraits::ObjectData::State::kMarked; } - GC::ObjectData::State state() { return objectData().state; } + ObjectFactoryTraits::ObjectData::State state() { return objectData().state; } private: - GC::ObjectData& objectData() { return ObjectFactory::NodeRef::From(header()).GCObjectData(); } + ObjectFactoryTraits::ObjectData& objectData() { return ObjectFactory::NodeRef::From(header()).ObjectData(); } }; using WeakCounter = test_support::Object; void MarkWeakCounter(WeakCounter& counter) { - ObjectFactory::NodeRef::From(counter.header()).GCObjectData().state = GC::ObjectData::State::kMarked; + ObjectFactory::NodeRef::From(counter.header()).ObjectData().state = ObjectFactoryTraits::ObjectData::State::kMarked; } -GC::ObjectData::State GetWeakCounterState(WeakCounter& counter) { - return ObjectFactory::NodeRef::From(counter.header()).GCObjectData().state; +ObjectFactoryTraits::ObjectData::State GetWeakCounterState(WeakCounter& counter) { + return ObjectFactory::NodeRef::From(counter.header()).ObjectData().state; } struct SweepTraits { @@ -155,19 +149,19 @@ struct SweepTraits { using ExtraObjectsFactory = mm::ExtraObjectDataFactory; static bool IsMarkedByExtraObject(mm::ExtraObjectData &object) noexcept { - auto& objectData = ObjectFactory::NodeRef::From(object.GetBaseObject()).GCObjectData(); - return objectData.state != GC::ObjectData::State::kUnmarked; + auto& objectData = ObjectFactory::NodeRef::From(object.GetBaseObject()).ObjectData(); + return objectData.state != ObjectFactoryTraits::ObjectData::State::kUnmarked; } static bool TryResetMark(ObjectFactory::NodeRef node) { - GC::ObjectData& objectData = node.GCObjectData(); + ObjectFactoryTraits::ObjectData& objectData = node.ObjectData(); switch (objectData.state) { - case GC::ObjectData::State::kUnmarked: + case ObjectFactoryTraits::ObjectData::State::kUnmarked: return false; - case GC::ObjectData::State::kMarked: - objectData.state = GC::ObjectData::State::kMarkReset; + case ObjectFactoryTraits::ObjectData::State::kMarked: + objectData.state = ObjectFactoryTraits::ObjectData::State::kMarkReset; return true; - case GC::ObjectData::State::kMarkReset: + case ObjectFactoryTraits::ObjectData::State::kMarkReset: RuntimeFail("Trying to reset mark twice."); } } @@ -184,7 +178,7 @@ public: }; for (auto& finalizerQueue : finalizers_) { for (auto node : finalizerQueue.IterForTests()) { - auto *object = node->IsArray() ? node->GetArrayHeader()->obj() : node->GetObjHeader(); + auto *object = node->GetObjHeader(); if (object->has_meta_object()) { deallocExtraObject(object); } @@ -195,7 +189,7 @@ public: // TODO: Figure out a better way to clear up the stuff. EXPECT_CALL(finalizerHook(), Call(testing::_)).Times(testing::AnyNumber()); for (auto node : objectFactory_.LockForIter()) { - auto* obj = node->IsArray() ? node->GetArrayHeader()->obj() : node->GetObjHeader(); + auto* obj = node->GetObjHeader(); if (auto* extraObject = mm::ExtraObjectData::Get(obj)) { extraObject->ClearWeakReferenceCounter(); deallocExtraObject(obj); @@ -209,7 +203,7 @@ public: auto finalizers = gc::Sweep(objectFactory_); KStdVector objects; for (auto node : finalizers.IterForTests()) { - objects.push_back(node.IsArray() ? node.GetArrayHeader()->obj() : node.GetObjHeader()); + objects.push_back(node.GetObjHeader()); } finalizers_.push_back(std::move(finalizers)); return objects; @@ -218,7 +212,7 @@ public: KStdVector Alive() { KStdVector objects; for (auto node : objectFactory_.LockForIter()) { - objects.push_back(node.IsArray() ? node.GetArrayHeader()->obj() : node.GetObjHeader()); + objects.push_back(node.GetObjHeader()); } return objects; } @@ -273,9 +267,8 @@ private: // TODO: Provide a common base class for all unit tests that require memory initializtion. kotlin::ScopedMemoryInit memoryInit; FinalizerHooksTestSupport finalizerHooks_; - GC::ThreadData gcThreadData_; ObjectFactory objectFactory_; - ObjectFactory::ThreadQueue objectFactoryThreadQueue_{objectFactory_, gcThreadData_}; + ObjectFactory::ThreadQueue objectFactoryThreadQueue_{objectFactory_, gc::AlignedAllocator()}; ExtraObjectsDataFactory extraObjectFactory_; ExtraObjectsDataFactory::ThreadQueue extraObjectFactoryThreadQueue_{extraObjectFactory_}; KStdVector finalizers_; @@ -331,7 +324,7 @@ TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedObject) { EXPECT_THAT(finalizers, testing::UnorderedElementsAre()); EXPECT_THAT(Alive(), testing::UnorderedElementsAre(object.header())); - EXPECT_THAT(object.state(), GC::ObjectData::State::kMarkReset); + EXPECT_THAT(object.state(), ObjectFactoryTraits::ObjectData::State::kMarkReset); } TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedObjectArray) { @@ -343,7 +336,7 @@ TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedObjectArray) { EXPECT_THAT(finalizers, testing::UnorderedElementsAre()); EXPECT_THAT(Alive(), testing::UnorderedElementsAre(array.header())); - EXPECT_THAT(array.state(), GC::ObjectData::State::kMarkReset); + EXPECT_THAT(array.state(), ObjectFactoryTraits::ObjectData::State::kMarkReset); } TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedCharArray) { @@ -355,7 +348,7 @@ TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedCharArray) { EXPECT_THAT(finalizers, testing::UnorderedElementsAre()); EXPECT_THAT(Alive(), testing::UnorderedElementsAre(array.header())); - EXPECT_THAT(array.state(), GC::ObjectData::State::kMarkReset); + EXPECT_THAT(array.state(), ObjectFactoryTraits::ObjectData::State::kMarkReset); } TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleObjectWithExtraData) { @@ -441,7 +434,7 @@ TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleObjectWithFinalizerHook) { EXPECT_THAT(finalizers, testing::UnorderedElementsAre(object.header())); EXPECT_THAT(Alive(), testing::UnorderedElementsAre()); - EXPECT_THAT(object.state(), GC::ObjectData::State::kUnmarked); + EXPECT_THAT(object.state(), ObjectFactoryTraits::ObjectData::State::kUnmarked); EXPECT_CALL(finalizerHook(), Call(object.header())); } @@ -455,7 +448,7 @@ TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedObjectWithFinalizerHook) { EXPECT_THAT(finalizers, testing::UnorderedElementsAre()); EXPECT_THAT(Alive(), testing::UnorderedElementsAre(object.header())); - EXPECT_THAT(object.state(), GC::ObjectData::State::kMarkReset); + EXPECT_THAT(object.state(), ObjectFactoryTraits::ObjectData::State::kMarkReset); } TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleObjectWithWeakCounter) { @@ -502,8 +495,8 @@ TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedObjectWithWeakCounter) { EXPECT_THAT(finalizers, testing::UnorderedElementsAre()); EXPECT_THAT(Alive(), testing::UnorderedElementsAre(object.header(), weakCounter.header())); - EXPECT_THAT(object.state(), GC::ObjectData::State::kMarkReset); - EXPECT_THAT(GetWeakCounterState(weakCounter), GC::ObjectData::State::kMarkReset); + EXPECT_THAT(object.state(), ObjectFactoryTraits::ObjectData::State::kMarkReset); + EXPECT_THAT(GetWeakCounterState(weakCounter), ObjectFactoryTraits::ObjectData::State::kMarkReset); EXPECT_TRUE(object.HasWeakCounter()); EXPECT_NE(weakCounter->referred, nullptr); } @@ -519,8 +512,8 @@ TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedObjectArrayWithWeakCounter) EXPECT_THAT(finalizers, testing::UnorderedElementsAre()); EXPECT_THAT(Alive(), testing::UnorderedElementsAre(array.header(), weakCounter.header())); - EXPECT_THAT(array.state(), GC::ObjectData::State::kMarkReset); - EXPECT_THAT(GetWeakCounterState(weakCounter), GC::ObjectData::State::kMarkReset); + EXPECT_THAT(array.state(), ObjectFactoryTraits::ObjectData::State::kMarkReset); + EXPECT_THAT(GetWeakCounterState(weakCounter), ObjectFactoryTraits::ObjectData::State::kMarkReset); EXPECT_TRUE(array.HasWeakCounter()); EXPECT_NE(weakCounter->referred, nullptr); } @@ -536,8 +529,8 @@ TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedCharArrayWithWeakCounter) { EXPECT_THAT(finalizers, testing::UnorderedElementsAre()); EXPECT_THAT(Alive(), testing::UnorderedElementsAre(array.header(), weakCounter.header())); - EXPECT_THAT(array.state(), GC::ObjectData::State::kMarkReset); - EXPECT_THAT(GetWeakCounterState(weakCounter), GC::ObjectData::State::kMarkReset); + EXPECT_THAT(array.state(), ObjectFactoryTraits::ObjectData::State::kMarkReset); + EXPECT_THAT(GetWeakCounterState(weakCounter), ObjectFactoryTraits::ObjectData::State::kMarkReset); EXPECT_TRUE(array.HasWeakCounter()); EXPECT_NE(weakCounter->referred, nullptr); } diff --git a/kotlin-native/runtime/src/gc/noop/cpp/GCImpl.hpp b/kotlin-native/runtime/src/gc/noop/cpp/GCImpl.hpp index 61df62fe855..28b07466c6b 100644 --- a/kotlin-native/runtime/src/gc/noop/cpp/GCImpl.hpp +++ b/kotlin-native/runtime/src/gc/noop/cpp/GCImpl.hpp @@ -33,7 +33,7 @@ public: Impl(GC& gc, mm::ThreadData& threadData) noexcept : gcScheduler_(gc.impl_->gcScheduler().NewThreadData()), gc_(gc.impl_->gc(), threadData, gcScheduler_), - objectFactoryThreadQueue_(gc.impl_->objectFactory(), gc_) {} + objectFactoryThreadQueue_(gc.impl_->objectFactory(), gc_.CreateAllocator()) {} GCSchedulerThreadData& gcScheduler() noexcept { return gcScheduler_; } GCImpl::ThreadData& gc() noexcept { return gc_; } diff --git a/kotlin-native/runtime/src/gc/stms/cpp/GCImpl.hpp b/kotlin-native/runtime/src/gc/stms/cpp/GCImpl.hpp index 69c151e214c..8cf02282d38 100644 --- a/kotlin-native/runtime/src/gc/stms/cpp/GCImpl.hpp +++ b/kotlin-native/runtime/src/gc/stms/cpp/GCImpl.hpp @@ -33,7 +33,7 @@ public: Impl(GC& gc, mm::ThreadData& threadData) noexcept : gcScheduler_(gc.impl_->gcScheduler().NewThreadData()), gc_(gc.impl_->gc(), threadData, gcScheduler_), - objectFactoryThreadQueue_(gc.impl_->objectFactory(), gc_) {} + objectFactoryThreadQueue_(gc.impl_->objectFactory(), gc_.CreateAllocator()) {} GCSchedulerThreadData& gcScheduler() noexcept { return gcScheduler_; } GCImpl::ThreadData& gc() noexcept { return gc_; } diff --git a/kotlin-native/runtime/src/gc/stms/cpp/SameThreadMarkAndSweep.cpp b/kotlin-native/runtime/src/gc/stms/cpp/SameThreadMarkAndSweep.cpp index 11bf1fdea04..960ed326698 100644 --- a/kotlin-native/runtime/src/gc/stms/cpp/SameThreadMarkAndSweep.cpp +++ b/kotlin-native/runtime/src/gc/stms/cpp/SameThreadMarkAndSweep.cpp @@ -40,7 +40,7 @@ struct MarkTraits { } static void enqueue(MarkQueue& queue, ObjHeader* object) noexcept { - auto& objectData = mm::ObjectFactory::NodeRef::From(object).GCObjectData(); + auto& objectData = mm::ObjectFactory::NodeRef::From(object).ObjectData(); if (objectData.color() == gc::SameThreadMarkAndSweep::ObjectData::Color::kBlack) return; objectData.setColor(gc::SameThreadMarkAndSweep::ObjectData::Color::kBlack); queue.push_back(object); @@ -54,12 +54,12 @@ struct SweepTraits { static bool IsMarkedByExtraObject(mm::ExtraObjectData &object) noexcept { auto *baseObject = object.GetBaseObject(); if (!baseObject->heap()) return true; - auto& objectData = mm::ObjectFactory::NodeRef::From(baseObject).GCObjectData(); + auto& objectData = mm::ObjectFactory::NodeRef::From(baseObject).ObjectData(); return objectData.color() == gc::SameThreadMarkAndSweep::ObjectData::Color::kBlack; } static bool TryResetMark(ObjectFactory::NodeRef node) noexcept { - auto& objectData = node.GCObjectData(); + auto& objectData = node.ObjectData(); if (objectData.color() == gc::SameThreadMarkAndSweep::ObjectData::Color::kWhite) return false; objectData.setColor(gc::SameThreadMarkAndSweep::ObjectData::Color::kWhite); return true; diff --git a/kotlin-native/runtime/src/gc/stms/cpp/SameThreadMarkAndSweepTest.cpp b/kotlin-native/runtime/src/gc/stms/cpp/SameThreadMarkAndSweepTest.cpp index 9892f368df4..80f21c35f2c 100644 --- a/kotlin-native/runtime/src/gc/stms/cpp/SameThreadMarkAndSweepTest.cpp +++ b/kotlin-native/runtime/src/gc/stms/cpp/SameThreadMarkAndSweepTest.cpp @@ -190,10 +190,10 @@ test_support::Object& AllocateObjectWithFinalizer(mm::ThreadData& threa KStdVector Alive(mm::ThreadData& threadData) { KStdVector objects; for (auto node : threadData.gc().impl().objectFactoryThreadQueue()) { - objects.push_back(node.IsArray() ? node.GetArrayHeader()->obj() : node.GetObjHeader()); + objects.push_back(node.GetObjHeader()); } for (auto node : mm::GlobalData::Instance().gc().impl().objectFactory().LockForIter()) { - objects.push_back(node.IsArray() ? node.GetArrayHeader()->obj() : node.GetObjHeader()); + objects.push_back(node.GetObjHeader()); } return objects; } @@ -202,7 +202,7 @@ using Color = gc::SameThreadMarkAndSweep::ObjectData::Color; Color GetColor(ObjHeader* objHeader) { auto nodeRef = mm::ObjectFactory::NodeRef::From(objHeader); - return nodeRef.GCObjectData().color(); + return nodeRef.ObjectData().color(); } WeakCounter& InstallWeakCounter(mm::ThreadData& threadData, ObjHeader* objHeader, ObjHeader** location) { diff --git a/kotlin-native/runtime/src/main/cpp/Memory.h b/kotlin-native/runtime/src/main/cpp/Memory.h index 6401d4cce79..cac7772db33 100644 --- a/kotlin-native/runtime/src/main/cpp/Memory.h +++ b/kotlin-native/runtime/src/main/cpp/Memory.h @@ -93,6 +93,7 @@ struct ObjHeader { } // Unsafe cast to ArrayHeader. Use carefully! + // TODO: RuntimeAssert on type_info()->IsArray()? ArrayHeader* array() { return reinterpret_cast(this); } const ArrayHeader* array() const { return reinterpret_cast(this); } diff --git a/kotlin-native/runtime/src/mm/cpp/ObjectFactory.hpp b/kotlin-native/runtime/src/mm/cpp/ObjectFactory.hpp index 567964217ea..397875dc951 100644 --- a/kotlin-native/runtime/src/mm/cpp/ObjectFactory.hpp +++ b/kotlin-native/runtime/src/mm/cpp/ObjectFactory.hpp @@ -427,21 +427,20 @@ private: } // namespace internal -template +template class ObjectFactory : private Pinned { - using GCObjectData = typename GC::ObjectData; - using GCThreadData = typename GC::ThreadData; - using Allocator = typename GC::Allocator; + using ObjectData = typename Traits::ObjectData; + using Allocator = typename Traits::Allocator; struct HeapObjHeader { - GCObjectData gcData; + ObjectData gcData; alignas(kObjectAlignment) ObjHeader object; }; // Needs to be kept compatible with `HeapObjHeader` just like `ArrayHeader` is compatible // with `ObjHeader`: the former can always be casted to the other. struct HeapArrayHeader { - GCObjectData gcData; + ObjectData gcData; alignas(kObjectAlignment) ArrayHeader array; }; @@ -470,29 +469,14 @@ public: NodeRef* operator->() noexcept { return this; } - GCObjectData& GCObjectData() noexcept { + ObjectData& ObjectData() noexcept { // `HeapArrayHeader` and `HeapObjHeader` are kept compatible, so the former can // be always casted to the other. return static_cast(node_.Data())->gcData; } - bool IsArray() const noexcept { - // `HeapArrayHeader` and `HeapObjHeader` are kept compatible, so the former can - // be always casted to the other. - auto* object = &static_cast(node_.Data())->object; - return object->type_info()->IsArray(); - } - ObjHeader* GetObjHeader() noexcept { - auto* object = &static_cast(node_.Data())->object; - RuntimeAssert(!object->type_info()->IsArray(), "Must not be an array"); - return object; - } - - ArrayHeader* GetArrayHeader() noexcept { - auto* array = &static_cast(node_.Data())->array; - RuntimeAssert(array->type_info()->IsArray(), "Must be an array"); - return array; + return &static_cast(node_.Data())->object; } bool operator==(const NodeRef& rhs) const noexcept { return &node_ == &rhs.node_; } @@ -526,7 +510,7 @@ public: typename Storage::Producer::Iterator iterator_; }; - ThreadQueue(ObjectFactory& owner, GCThreadData& gc) noexcept : producer_(owner.storage_, gc.CreateAllocator()) {} + ThreadQueue(ObjectFactory& owner, Allocator allocator) noexcept : producer_(owner.storage_, std::move(allocator)) {} static size_t ObjectAllocatedSize(const TypeInfo* typeInfo) noexcept { RuntimeAssert(!typeInfo->IsArray(), "Must not be an array"); @@ -648,7 +632,7 @@ public: // TODO: Consider running it in the destructor instead. void Finalize() noexcept { for (auto node : Iterable(*this)) { - RunFinalizers(node->IsArray() ? node->GetArrayHeader()->obj() : node->GetObjHeader()); + RunFinalizers(node->GetObjHeader()); } } diff --git a/kotlin-native/runtime/src/mm/cpp/ObjectFactoryTest.cpp b/kotlin-native/runtime/src/mm/cpp/ObjectFactoryTest.cpp index 7d16fde8895..5c4dd31b76c 100644 --- a/kotlin-native/runtime/src/mm/cpp/ObjectFactoryTest.cpp +++ b/kotlin-native/runtime/src/mm/cpp/ObjectFactoryTest.cpp @@ -828,25 +828,16 @@ MockAllocator::~MockAllocator() { // static MockAllocator* GlobalMockAllocator::instance_ = nullptr; -class GC { +class ObjectFactoryTraits { public: struct ObjectData { uint32_t flags = 42; }; using Allocator = GlobalMockAllocator; - - class ThreadData { - public: - void SafePointAllocation(size_t size) noexcept {} - - void OnOOM(size_t size) noexcept {} - - Allocator CreateAllocator() noexcept { return Allocator(); } - }; }; -using ObjectFactory = mm::ObjectFactory; +using ObjectFactory = mm::ObjectFactory; struct Payload { ObjHeader* field1; @@ -864,9 +855,8 @@ TEST(ObjectFactoryTest, CreateObject) { testing::StrictMock allocator; test_support::TypeInfoHolder type{test_support::TypeInfoHolder::ObjectBuilder()}; - GC::ThreadData gc; ObjectFactory objectFactory; - ObjectFactory::ThreadQueue threadQueue(objectFactory, gc); + ObjectFactory::ThreadQueue threadQueue(objectFactory, GlobalMockAllocator()); size_t allocSize = 0; void* allocAddress = nullptr; @@ -880,13 +870,13 @@ TEST(ObjectFactoryTest, CreateObject) { EXPECT_THAT(allocSize, testing::Gt(type.typeInfo()->instanceSize_)); EXPECT_THAT(allocAddress, testing::Ne(nullptr)); EXPECT_THAT(mm::GetAllocatedHeapSize(object), allocSize); + EXPECT_THAT(object->type_info(), type.typeInfo()); threadQueue.Publish(); auto node = ObjectFactory::NodeRef::From(object); - EXPECT_FALSE(node.IsArray()); EXPECT_THAT(node.GetObjHeader(), object); - EXPECT_THAT(node.GCObjectData().flags, 42); + EXPECT_THAT(node.ObjectData().flags, 42); auto iter = objectFactory.LockForIter(); auto it = iter.begin(); @@ -900,9 +890,8 @@ TEST(ObjectFactoryTest, CreateObject) { TEST(ObjectFactoryTest, CreateObjectArray) { testing::StrictMock allocator; - GC::ThreadData gc; ObjectFactory objectFactory; - ObjectFactory::ThreadQueue threadQueue(objectFactory, gc); + ObjectFactory::ThreadQueue threadQueue(objectFactory, GlobalMockAllocator()); size_t allocSize = 0; void* allocAddress = nullptr; @@ -916,13 +905,13 @@ TEST(ObjectFactoryTest, CreateObjectArray) { EXPECT_THAT(allocSize, testing::Gt(-theArrayTypeInfo->instanceSize_ * 3)); EXPECT_THAT(allocAddress, testing::Ne(nullptr)); EXPECT_THAT(mm::GetAllocatedHeapSize(array->obj()), allocSize); + EXPECT_THAT(array->type_info(), theArrayTypeInfo); threadQueue.Publish(); auto node = ObjectFactory::NodeRef::From(array); - EXPECT_TRUE(node.IsArray()); - EXPECT_THAT(node.GetArrayHeader(), array); - EXPECT_THAT(node.GCObjectData().flags, 42); + EXPECT_THAT(node.GetObjHeader()->array(), array); + EXPECT_THAT(node.ObjectData().flags, 42); auto iter = objectFactory.LockForIter(); auto it = iter.begin(); @@ -936,9 +925,8 @@ TEST(ObjectFactoryTest, CreateObjectArray) { TEST(ObjectFactoryTest, CreateCharArray) { testing::StrictMock allocator; - GC::ThreadData gc; ObjectFactory objectFactory; - ObjectFactory::ThreadQueue threadQueue(objectFactory, gc); + ObjectFactory::ThreadQueue threadQueue(objectFactory, GlobalMockAllocator()); size_t allocSize = 0; void* allocAddress = nullptr; @@ -952,13 +940,13 @@ TEST(ObjectFactoryTest, CreateCharArray) { EXPECT_THAT(allocSize, testing::Gt(-theCharArrayTypeInfo->instanceSize_ * 3)); EXPECT_THAT(allocAddress, testing::Ne(nullptr)); EXPECT_THAT(mm::GetAllocatedHeapSize(array->obj()), allocSize); + EXPECT_THAT(array->type_info(), theCharArrayTypeInfo); threadQueue.Publish(); auto node = ObjectFactory::NodeRef::From(array); - EXPECT_TRUE(node.IsArray()); - EXPECT_THAT(node.GetArrayHeader(), array); - EXPECT_THAT(node.GCObjectData().flags, 42); + EXPECT_THAT(node.GetObjHeader()->array(), array); + EXPECT_THAT(node.ObjectData().flags, 42); auto iter = objectFactory.LockForIter(); auto it = iter.begin(); @@ -973,9 +961,8 @@ TEST(ObjectFactoryTest, Erase) { testing::StrictMock allocator; test_support::TypeInfoHolder objectType{test_support::TypeInfoHolder::ObjectBuilder()}; - GC::ThreadData gc; ObjectFactory objectFactory; - ObjectFactory::ThreadQueue threadQueue(objectFactory, gc); + ObjectFactory::ThreadQueue threadQueue(objectFactory, GlobalMockAllocator()); EXPECT_CALL(allocator, Alloc(_, _)).Times(20); for (int i = 0; i < 10; ++i) { @@ -989,7 +976,7 @@ TEST(ObjectFactoryTest, Erase) { { auto iter = objectFactory.LockForIter(); for (auto it = iter.begin(); it != iter.end();) { - if (it->IsArray()) { + if (it->GetObjHeader()->type_info()->IsArray()) { EXPECT_CALL(allocator, Free(_)); iter.EraseAndAdvance(it); testing::Mock::VerifyAndClearExpectations(&allocator); @@ -1003,7 +990,7 @@ TEST(ObjectFactoryTest, Erase) { auto iter = objectFactory.LockForIter(); int count = 0; for (auto it = iter.begin(); it != iter.end(); ++it, ++count) { - EXPECT_FALSE(it->IsArray()); + EXPECT_FALSE(it->GetObjHeader()->type_info()->IsArray()); } EXPECT_THAT(count, 10); } @@ -1014,9 +1001,8 @@ TEST(ObjectFactoryTest, Move) { testing::StrictMock allocator; test_support::TypeInfoHolder objectType{test_support::TypeInfoHolder::ObjectBuilder()}; - GC::ThreadData gc; ObjectFactory objectFactory; - ObjectFactory::ThreadQueue threadQueue(objectFactory, gc); + ObjectFactory::ThreadQueue threadQueue(objectFactory, GlobalMockAllocator()); ObjectFactory::FinalizerQueue finalizerQueue; EXPECT_CALL(allocator, Alloc(_, _)).Times(20); @@ -1031,7 +1017,7 @@ TEST(ObjectFactoryTest, Move) { { auto iter = objectFactory.LockForIter(); for (auto it = iter.begin(); it != iter.end();) { - if (it->IsArray()) { + if (it->GetObjHeader()->type_info()->IsArray()) { iter.MoveAndAdvance(finalizerQueue, it); } else { ++it; @@ -1043,7 +1029,7 @@ TEST(ObjectFactoryTest, Move) { auto iter = objectFactory.LockForIter(); int count = 0; for (auto it = iter.begin(); it != iter.end(); ++it, ++count) { - EXPECT_FALSE(it->IsArray()); + EXPECT_FALSE(it->GetObjHeader()->type_info()->IsArray()); } EXPECT_THAT(count, 10); } @@ -1052,7 +1038,7 @@ TEST(ObjectFactoryTest, Move) { int count = 0; auto iter = finalizerQueue.IterForTests(); for (auto it = iter.begin(); it != iter.end(); ++it, ++count) { - EXPECT_TRUE(it->IsArray()); + EXPECT_TRUE(it->GetObjHeader()->type_info()->IsArray()); } EXPECT_THAT(count, 10); } @@ -1066,9 +1052,8 @@ TEST(ObjectFactoryTest, RunFinalizers) { FinalizerHooksTestSupport finalizerHooks; test_support::TypeInfoHolder objectType{test_support::TypeInfoHolder::ObjectBuilder().addFlag(TF_HAS_FINALIZER)}; - GC::ThreadData gc; ObjectFactory objectFactory; - ObjectFactory::ThreadQueue threadQueue(objectFactory, gc); + ObjectFactory::ThreadQueue threadQueue(objectFactory, GlobalMockAllocator()); ObjectFactory::FinalizerQueue finalizerQueue; KStdVector objects; @@ -1111,8 +1096,7 @@ TEST(ObjectFactoryTest, ConcurrentPublish) { EXPECT_CALL(allocator, Alloc(_, _)).Times(kThreadCount); for (int i = 0; i < kThreadCount; ++i) { threads.emplace_back([&type, &objectFactory, &canStart, &readyCount, &expected, &expectedMutex]() { - GC::ThreadData gc; - ObjectFactory::ThreadQueue threadQueue(objectFactory, gc); + ObjectFactory::ThreadQueue threadQueue(objectFactory, GlobalMockAllocator()); auto* object = threadQueue.CreateObject(type.typeInfo()); { std::lock_guard guard(expectedMutex);