diff --git a/kotlin-native/runtime/src/main/cpp/FinalizerHooksTest.cpp b/kotlin-native/runtime/src/main/cpp/FinalizerHooksTest.cpp index 459326ec9e0..c2fdcc6fbff 100644 --- a/kotlin-native/runtime/src/main/cpp/FinalizerHooksTest.cpp +++ b/kotlin-native/runtime/src/main/cpp/FinalizerHooksTest.cpp @@ -11,6 +11,7 @@ #include "FinalizerHooksTestSupport.hpp" #include "Memory.h" #include "ObjectTestSupport.hpp" +#include "TestSupport.hpp" using namespace kotlin; @@ -46,6 +47,7 @@ TEST_F(FinalizerHooksTest, TypeWithFinalizerHookWithoutExtra) { } TEST_F(FinalizerHooksTest, TypeWithFinalizerHookWithExtra) { + ScopedMemoryInit init; test_support::TypeInfoHolder type{test_support::TypeInfoHolder::ObjectBuilder().addFlag(TF_HAS_FINALIZER)}; test_support::Object object(type.typeInfo()); ObjHeader* obj = object.header(); @@ -71,6 +73,7 @@ TEST_F(FinalizerHooksTest, TypeWithoutFinalizerHookWithoutExtra) { } TEST_F(FinalizerHooksTest, TypeWithoutFinalizerHookWithExtra) { + ScopedMemoryInit init; test_support::TypeInfoHolder type{test_support::TypeInfoHolder::ObjectBuilder()}; test_support::Object object(type.typeInfo()); ObjHeader* obj = object.header(); diff --git a/kotlin-native/runtime/src/main/cpp/MultiSourceQueue.hpp b/kotlin-native/runtime/src/main/cpp/MultiSourceQueue.hpp index f6bd8f0b4a0..af2d47d2a67 100644 --- a/kotlin-native/runtime/src/main/cpp/MultiSourceQueue.hpp +++ b/kotlin-native/runtime/src/main/cpp/MultiSourceQueue.hpp @@ -25,10 +25,18 @@ public: // and to not store the iterator. class Node : private Pinned, public KonanAllocatorAware { public: - Node(const T& value, Producer* owner) noexcept : value_(value), owner_(owner) {} + Node(Producer* owner, const T& value) noexcept : value_(value), owner_(owner) {} + + template >> + explicit Node(Producer* owner, Args&& ...args) noexcept : value_(std::forward(args)...), owner_(owner) {} 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"); + return *reinterpret_cast(reinterpret_cast(&t) - offsetof(Node, value_)); + } + private: friend class MultiSourceQueue; @@ -44,7 +52,15 @@ public: ~Producer() { Publish(); } Node* Insert(const T& value) noexcept { - queue_.emplace_back(value, this); + queue_.emplace_back(this, value); + auto& node = queue_.back(); + node.position_ = std::prev(queue_.end()); + return &node; + } + + template >> + Node* Emplace(Args&& ...value) noexcept { + queue_.emplace_back(this, std::forward(value)...); auto& node = queue_.back(); node.position_ = std::prev(queue_.end()); return &node; diff --git a/kotlin-native/runtime/src/mm/cpp/ExtraObjectData.cpp b/kotlin-native/runtime/src/mm/cpp/ExtraObjectData.cpp index 06789e5cb8e..9f6bde81dae 100644 --- a/kotlin-native/runtime/src/mm/cpp/ExtraObjectData.cpp +++ b/kotlin-native/runtime/src/mm/cpp/ExtraObjectData.cpp @@ -8,6 +8,7 @@ #include "ObjectOps.hpp" #include "PointerBits.h" #include "Weak.h" +#include "ExtraObjectDataFactory.hpp" #ifdef KONAN_OBJC_INTEROP #include "ObjCMMAPI.h" @@ -42,16 +43,17 @@ mm::ExtraObjectData& mm::ExtraObjectData::Install(ObjHeader* object) noexcept { RuntimeCheck(!hasPointerBits(typeInfo, OBJECT_TAG_MASK), "Object must not be tagged"); - auto* data = new ExtraObjectData(typeInfo); + auto *threadData = mm::ThreadRegistry::Instance().CurrentThreadData(); + auto& data = mm::ExtraObjectDataFactory::Instance().CreateExtraObjectDataForObject(threadData, typeInfo); - TypeInfo* old = __sync_val_compare_and_swap(&object->typeInfoOrMeta_, typeInfo, reinterpret_cast(data)); + TypeInfo* old = __sync_val_compare_and_swap(&object->typeInfoOrMeta_, typeInfo, reinterpret_cast(&data)); if (old != typeInfo) { // Somebody else created `mm::ExtraObjectData` for this object - delete data; + mm::ExtraObjectDataFactory::Instance().DestroyExtraObjectData(threadData, data); return *reinterpret_cast(old); } - return *data; + return data; } // static @@ -62,7 +64,12 @@ void mm::ExtraObjectData::Uninstall(ObjHeader* object) noexcept { *const_cast(&object->typeInfoOrMeta_) = data.typeInfo_; - delete &data; + auto *threadData = mm::ThreadRegistry::Instance().CurrentThreadData(); +#ifdef KONAN_OBJC_INTEROP + Kotlin_ObjCExport_releaseAssociatedObject(data.associatedObject_); + data.associatedObject_ = nullptr; +#endif + mm::ExtraObjectDataFactory::Instance().DestroyExtraObjectData(threadData, data); } void mm::ExtraObjectData::DetachAssociatedObject() noexcept { @@ -89,6 +96,6 @@ mm::ExtraObjectData::~ExtraObjectData() { RuntimeAssert(!HasWeakReferenceCounter(), "Object must have cleared weak references"); #ifdef KONAN_OBJC_INTEROP - Kotlin_ObjCExport_releaseAssociatedObject(associatedObject_); + RuntimeAssert(associatedObject_ == nullptr, "Object must have cleared associated object"); #endif } diff --git a/kotlin-native/runtime/src/mm/cpp/ExtraObjectData.hpp b/kotlin-native/runtime/src/mm/cpp/ExtraObjectData.hpp index c17dfafc56f..0dbf35f5a05 100644 --- a/kotlin-native/runtime/src/mm/cpp/ExtraObjectData.hpp +++ b/kotlin-native/runtime/src/mm/cpp/ExtraObjectData.hpp @@ -14,6 +14,7 @@ #include "Memory.h" #include "TypeInfo.h" #include "Utils.hpp" +#include "MultiSourceQueue.hpp" namespace kotlin { namespace mm { @@ -51,9 +52,9 @@ public: bool HasWeakReferenceCounter() noexcept; void ClearWeakReferenceCounter() noexcept; -private: explicit ExtraObjectData(const TypeInfo* typeInfo) noexcept : typeInfo_(typeInfo) {} ~ExtraObjectData(); +private: // Must be first to match `TypeInfo` layout. const TypeInfo* typeInfo_; diff --git a/kotlin-native/runtime/src/mm/cpp/ExtraObjectDataFactory.cpp b/kotlin-native/runtime/src/mm/cpp/ExtraObjectDataFactory.cpp new file mode 100644 index 00000000000..41ebb744111 --- /dev/null +++ b/kotlin-native/runtime/src/mm/cpp/ExtraObjectDataFactory.cpp @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#include "ExtraObjectDataFactory.hpp" + +#include "GlobalData.hpp" +#include "ThreadData.hpp" + +using namespace kotlin; + +// static +mm::ExtraObjectDataFactory& mm::ExtraObjectDataFactory::Instance() noexcept { + return GlobalData::Instance().extraObjectDataFactory(); +} + +mm::ExtraObjectData& mm::ExtraObjectDataFactory::CreateExtraObjectDataForObject(mm::ThreadData* threadData, TypeInfo* info) noexcept { + return **threadData->extraObjectDataThreadQueue().Emplace(info); +} + +void mm::ExtraObjectDataFactory::DestroyExtraObjectData(mm::ThreadData* threadData, ExtraObjectData& data) noexcept { + threadData->extraObjectDataThreadQueue().Erase(&Queue::Node::fromValue(data)); +} + +void mm::ExtraObjectDataFactory::ProcessThread(mm::ThreadData* threadData) noexcept { + threadData->extraObjectDataThreadQueue().Publish(); +} + +void mm::ExtraObjectDataFactory::ProcessDeletions() noexcept { + extraObjects_.ApplyDeletions(); +} + +mm::ExtraObjectDataFactory::ExtraObjectDataFactory() = default; +mm::ExtraObjectDataFactory::~ExtraObjectDataFactory() = default; diff --git a/kotlin-native/runtime/src/mm/cpp/ExtraObjectDataFactory.hpp b/kotlin-native/runtime/src/mm/cpp/ExtraObjectDataFactory.hpp new file mode 100644 index 00000000000..8d651aa6040 --- /dev/null +++ b/kotlin-native/runtime/src/mm/cpp/ExtraObjectDataFactory.hpp @@ -0,0 +1,59 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ + +#ifndef RUNTIME_MM_EXTRA_OBJECT_DATA_REGISTRY_H +#define RUNTIME_MM_EXTRA_OBJECT_DATA_REGISTRY_H + +#include "Memory.h" +#include "MultiSourceQueue.hpp" +#include "ThreadRegistry.hpp" +#include "ExtraObjectData.hpp" + +namespace kotlin { +namespace mm { + +// Registry for extra data, attached to some kotlin objects: weak refs, associated objects, ... +class ExtraObjectDataFactory : Pinned { + using Mutex = SpinLock; + using Queue = MultiSourceQueue; +public: + class ThreadQueue : public Queue::Producer { + public: + explicit ThreadQueue(ExtraObjectDataFactory& registry) : Producer(registry.extraObjects_) {} + // Do not add fields as this is just a wrapper and Producer does not have virtual destructor. + }; + + using Iterable = Queue::Iterable; + using Iterator = Queue::Iterator; + + ExtraObjectDataFactory(); + ~ExtraObjectDataFactory(); + + static ExtraObjectDataFactory& Instance() noexcept; + + ExtraObjectData& CreateExtraObjectDataForObject(mm::ThreadData* threadData, TypeInfo* info) noexcept; + + void DestroyExtraObjectData(mm::ThreadData* threadData, ExtraObjectData& data) noexcept; + + // Collect extra data objects from thread corresponding to `threadData`. Must be called by the thread + // when it's asked by GC to stop. + void ProcessThread(mm::ThreadData* threadData) noexcept; + + // Lock registry and apply deletions. Should be called on GC thread after all threads have published, and before `LockForIter`. + void ProcessDeletions() noexcept; + + // Lock registry for safe iteration. + Iterable LockForIter() noexcept { return extraObjects_.LockForIter(); } + + void ClearForTests() noexcept { extraObjects_.ClearForTests(); } + +private: + Queue extraObjects_; +}; + +} // namespace mm +} // namespace kotlin + +#endif // RUNTIME_MM_EXTRA_OBJECT_DATA_REGISTRY_H diff --git a/kotlin-native/runtime/src/mm/cpp/ExtraObjectDataTest.cpp b/kotlin-native/runtime/src/mm/cpp/ExtraObjectDataTest.cpp index e17344a2f18..fc126c88d93 100644 --- a/kotlin-native/runtime/src/mm/cpp/ExtraObjectDataTest.cpp +++ b/kotlin-native/runtime/src/mm/cpp/ExtraObjectDataTest.cpp @@ -26,6 +26,7 @@ struct EmptyPayload { } // namespace TEST(ExtraObjectDataTest, Install) { + ScopedMemoryInit init; test_support::TypeInfoHolder type{test_support::TypeInfoHolder::ObjectBuilder()}; test_support::Object object(type.typeInfo()); auto* typeInfo = object.header()->type_info(); @@ -45,6 +46,7 @@ TEST(ExtraObjectDataTest, Install) { } TEST(ExtraObjectDataTest, ConcurrentInstall) { + ScopedMemoryInit init; test_support::TypeInfoHolder type{test_support::TypeInfoHolder::ObjectBuilder()}; test_support::Object object(type.typeInfo()); @@ -57,6 +59,7 @@ TEST(ExtraObjectDataTest, ConcurrentInstall) { for (int i = 0; i < kThreadCount; ++i) { threads.emplace_back([i, &actual, &object, &canStart, &readyCount]() { + ScopedMemoryInit init; ++readyCount; while (!canStart) { } diff --git a/kotlin-native/runtime/src/mm/cpp/FreezingTest.cpp b/kotlin-native/runtime/src/mm/cpp/FreezingTest.cpp index fd2019d39c0..9bb776222bc 100644 --- a/kotlin-native/runtime/src/mm/cpp/FreezingTest.cpp +++ b/kotlin-native/runtime/src/mm/cpp/FreezingTest.cpp @@ -12,6 +12,7 @@ #include "Memory.h" #include "ObjectTestSupport.hpp" #include "Utils.hpp" +#include "TestSupport.hpp" using namespace kotlin; @@ -153,6 +154,7 @@ TYPED_TEST(FreezingEmptyNoHookTest, PermanentIsFrozen) { } TYPED_TEST(FreezingEmptyNoHookTest, FailToEnsureNeverFrozen) { + ScopedMemoryInit init; TypeParam object; ASSERT_THAT(mm::FreezeSubgraph(object.header()), nullptr); ASSERT_TRUE(mm::IsFrozen(object.header())); @@ -167,12 +169,14 @@ TYPED_TEST(FreezingEmptyNoHookTest, FailToEnsureNeverFrozenPermanent) { } TYPED_TEST(FreezingEmptyNoHookTest, Freeze) { + ScopedMemoryInit init; TypeParam object; EXPECT_THAT(mm::FreezeSubgraph(object.header()), nullptr); EXPECT_TRUE(mm::IsFrozen(object.header())); } TYPED_TEST(FreezingEmptyNoHookTest, FreezePermanent) { + ScopedMemoryInit init; TypeParam object; object.MakePermanent(); EXPECT_THAT(mm::FreezeSubgraph(object.header()), nullptr); @@ -180,6 +184,7 @@ TYPED_TEST(FreezingEmptyNoHookTest, FreezePermanent) { } TYPED_TEST(FreezingEmptyNoHookTest, FreezeTwice) { + ScopedMemoryInit init; TypeParam object; EXPECT_THAT(mm::FreezeSubgraph(object.header()), nullptr); EXPECT_THAT(mm::FreezeSubgraph(object.header()), nullptr); @@ -187,6 +192,7 @@ TYPED_TEST(FreezingEmptyNoHookTest, FreezeTwice) { } TYPED_TEST(FreezingEmptyNoHookTest, FreezeForbidden) { + ScopedMemoryInit init; TypeParam object; ASSERT_TRUE(mm::EnsureNeverFrozen(object.header())); EXPECT_THAT(mm::FreezeSubgraph(object.header()), object.header()); @@ -194,6 +200,7 @@ TYPED_TEST(FreezingEmptyNoHookTest, FreezeForbidden) { } TYPED_TEST(FreezingEmptyWithHookTest, Freeze) { + ScopedMemoryInit init; TypeParam object; EXPECT_CALL(this->freezeHook(), Call(object.header())); EXPECT_THAT(mm::FreezeSubgraph(object.header()), nullptr); @@ -201,6 +208,7 @@ TYPED_TEST(FreezingEmptyWithHookTest, Freeze) { } TYPED_TEST(FreezingEmptyWithHookTest, FreezePermanent) { + ScopedMemoryInit init; TypeParam object; object.MakePermanent(); EXPECT_CALL(this->freezeHook(), Call(_)).Times(0); @@ -209,6 +217,7 @@ TYPED_TEST(FreezingEmptyWithHookTest, FreezePermanent) { } TYPED_TEST(FreezingEmptyWithHookTest, FreezeTwice) { + ScopedMemoryInit init; TypeParam object; // Only called for the first freeze. EXPECT_CALL(this->freezeHook(), Call(object.header())); @@ -219,6 +228,7 @@ TYPED_TEST(FreezingEmptyWithHookTest, FreezeTwice) { } TYPED_TEST(FreezingEmptyWithHookTest, FreezeForbidden) { + ScopedMemoryInit init; TypeParam object; ASSERT_TRUE(mm::EnsureNeverFrozen(object.header())); EXPECT_CALL(this->freezeHook(), Call(object.header())); @@ -227,12 +237,14 @@ TYPED_TEST(FreezingEmptyWithHookTest, FreezeForbidden) { } TYPED_TEST(FreezingNoHookTest, Freeze) { + ScopedMemoryInit init; TypeParam object; EXPECT_THAT(mm::FreezeSubgraph(object.header()), nullptr); EXPECT_TRUE(mm::IsFrozen(object.header())); } TYPED_TEST(FreezingNoHookTest, FreezePermanent) { + ScopedMemoryInit init; TypeParam object; object.MakePermanent(); EXPECT_THAT(mm::FreezeSubgraph(object.header()), nullptr); @@ -240,6 +252,7 @@ TYPED_TEST(FreezingNoHookTest, FreezePermanent) { } TYPED_TEST(FreezingNoHookTest, FreezeTwice) { + ScopedMemoryInit init; TypeParam object; EXPECT_THAT(mm::FreezeSubgraph(object.header()), nullptr); EXPECT_THAT(mm::FreezeSubgraph(object.header()), nullptr); @@ -247,6 +260,7 @@ TYPED_TEST(FreezingNoHookTest, FreezeTwice) { } TYPED_TEST(FreezingNoHookTest, FreezeForbidden) { + ScopedMemoryInit init; TypeParam object; ASSERT_TRUE(mm::EnsureNeverFrozen(object.header())); EXPECT_THAT(mm::FreezeSubgraph(object.header()), object.header()); @@ -254,6 +268,7 @@ TYPED_TEST(FreezingNoHookTest, FreezeForbidden) { } TYPED_TEST(FreezingNoHookTest, FreezeTree) { + ScopedMemoryInit init; TypeParam object; TypeParam field1; TypeParam field2; @@ -269,6 +284,7 @@ TYPED_TEST(FreezingNoHookTest, FreezeTree) { } TYPED_TEST(FreezingNoHookTest, FreezeTreePermanent) { + ScopedMemoryInit init; TypeParam object; object.MakePermanent(); TypeParam field1; @@ -288,6 +304,7 @@ TYPED_TEST(FreezingNoHookTest, FreezeTreePermanent) { } TYPED_TEST(FreezingNoHookTest, FreezeTreePermanentLeaf) { + ScopedMemoryInit init; TypeParam object; TypeParam field1; field1.MakePermanent(); @@ -304,6 +321,7 @@ TYPED_TEST(FreezingNoHookTest, FreezeTreePermanentLeaf) { } TYPED_TEST(FreezingNoHookTest, FreezeTreeTwice) { + ScopedMemoryInit init; TypeParam object; TypeParam field1; TypeParam field2; @@ -320,6 +338,7 @@ TYPED_TEST(FreezingNoHookTest, FreezeTreeTwice) { } TYPED_TEST(FreezingNoHookTest, FreezeTreeForbidden) { + ScopedMemoryInit init; TypeParam object; TypeParam field1; TypeParam field2; @@ -336,6 +355,7 @@ TYPED_TEST(FreezingNoHookTest, FreezeTreeForbidden) { } TYPED_TEST(FreezingNoHookTest, FreezeTreeForbiddenByField) { + ScopedMemoryInit init; TypeParam object; TypeParam field1; TypeParam field2; @@ -352,6 +372,7 @@ TYPED_TEST(FreezingNoHookTest, FreezeTreeForbiddenByField) { } TYPED_TEST(FreezingNoHookTest, FreezeTreeRecursive) { + ScopedMemoryInit init; TypeParam object; TypeParam inner1; TypeParam inner2; @@ -365,6 +386,7 @@ TYPED_TEST(FreezingNoHookTest, FreezeTreeRecursive) { } TYPED_TEST(FreezingNoHookTest, FreezeTreeRecursivePermanent) { + ScopedMemoryInit init; TypeParam object; object.MakePermanent(); TypeParam inner1; @@ -381,6 +403,7 @@ TYPED_TEST(FreezingNoHookTest, FreezeTreeRecursivePermanent) { } TYPED_TEST(FreezingWithHookTest, Freeze) { + ScopedMemoryInit init; TypeParam object; EXPECT_CALL(this->freezeHook(), Call(object.header())); EXPECT_THAT(mm::FreezeSubgraph(object.header()), nullptr); @@ -388,6 +411,7 @@ TYPED_TEST(FreezingWithHookTest, Freeze) { } TYPED_TEST(FreezingWithHookTest, FreezePermanent) { + ScopedMemoryInit init; TypeParam object; object.MakePermanent(); EXPECT_CALL(this->freezeHook(), Call(_)).Times(0); @@ -396,6 +420,7 @@ TYPED_TEST(FreezingWithHookTest, FreezePermanent) { } TYPED_TEST(FreezingWithHookTest, FreezeTwice) { + ScopedMemoryInit init; TypeParam object; // Only called for the first freeze. EXPECT_CALL(this->freezeHook(), Call(object.header())); @@ -406,6 +431,7 @@ TYPED_TEST(FreezingWithHookTest, FreezeTwice) { } TYPED_TEST(FreezingWithHookTest, FreezeForbidden) { + ScopedMemoryInit init; TypeParam object; ASSERT_TRUE(mm::EnsureNeverFrozen(object.header())); EXPECT_CALL(this->freezeHook(), Call(object.header())); @@ -414,6 +440,7 @@ TYPED_TEST(FreezingWithHookTest, FreezeForbidden) { } TYPED_TEST(FreezingWithHookTest, FreezeTree) { + ScopedMemoryInit init; TypeParam object; TypeParam field1; TypeParam field2; @@ -433,6 +460,7 @@ TYPED_TEST(FreezingWithHookTest, FreezeTree) { } TYPED_TEST(FreezingWithHookTest, FreezeTreePermanent) { + ScopedMemoryInit init; TypeParam object; object.MakePermanent(); TypeParam field1; @@ -453,6 +481,7 @@ TYPED_TEST(FreezingWithHookTest, FreezeTreePermanent) { } TYPED_TEST(FreezingWithHookTest, FreezeTreePermanentLeaf) { + ScopedMemoryInit init; TypeParam object; TypeParam field1; field1.MakePermanent(); @@ -473,6 +502,7 @@ TYPED_TEST(FreezingWithHookTest, FreezeTreePermanentLeaf) { } TYPED_TEST(FreezingWithHookTest, FreezeTreeTwice) { + ScopedMemoryInit init; TypeParam object; TypeParam field1; TypeParam field2; @@ -495,6 +525,7 @@ TYPED_TEST(FreezingWithHookTest, FreezeTreeTwice) { } TYPED_TEST(FreezingWithHookTest, FreezeTreeForbidden) { + ScopedMemoryInit init; TypeParam object; TypeParam field1; TypeParam field2; @@ -515,6 +546,7 @@ TYPED_TEST(FreezingWithHookTest, FreezeTreeForbidden) { } TYPED_TEST(FreezingWithHookTest, FreezeTreeForbiddenByField) { + ScopedMemoryInit init; TypeParam object; TypeParam field1; TypeParam field2; @@ -535,6 +567,7 @@ TYPED_TEST(FreezingWithHookTest, FreezeTreeForbiddenByField) { } TYPED_TEST(FreezingWithHookTest, FreezeTreeRecursive) { + ScopedMemoryInit init; TypeParam object; TypeParam inner1; TypeParam inner2; @@ -551,6 +584,7 @@ TYPED_TEST(FreezingWithHookTest, FreezeTreeRecursive) { } TYPED_TEST(FreezingWithHookTest, FreezeTreeRecursivePermanent) { + ScopedMemoryInit init; TypeParam object; object.MakePermanent(); TypeParam inner1; @@ -568,6 +602,7 @@ TYPED_TEST(FreezingWithHookTest, FreezeTreeRecursivePermanent) { } TYPED_TEST(FreezingWithHookTest, FreezeTreeWithHookRewrite) { + ScopedMemoryInit init; TypeParam object; TypeParam field1; TypeParam field2; @@ -597,6 +632,7 @@ TYPED_TEST(FreezingWithHookTest, FreezeTreeWithHookRewrite) { } TYPED_TEST(FreezingWithHookTest, FreezeTreeForbiddenByHook) { + ScopedMemoryInit init; TypeParam object; TypeParam field1; TypeParam field2; diff --git a/kotlin-native/runtime/src/mm/cpp/GlobalData.hpp b/kotlin-native/runtime/src/mm/cpp/GlobalData.hpp index c6c096febbb..a0d652e11b0 100644 --- a/kotlin-native/runtime/src/mm/cpp/GlobalData.hpp +++ b/kotlin-native/runtime/src/mm/cpp/GlobalData.hpp @@ -13,6 +13,7 @@ #include "StableRefRegistry.hpp" #include "ThreadRegistry.hpp" #include "Utils.hpp" +#include "ExtraObjectDataFactory.hpp" namespace kotlin { namespace mm { @@ -25,6 +26,7 @@ public: ThreadRegistry& threadRegistry() noexcept { return threadRegistry_; } GlobalsRegistry& globalsRegistry() noexcept { return globalsRegistry_; } StableRefRegistry& stableRefRegistry() noexcept { return stableRefRegistry_; } + ExtraObjectDataFactory& extraObjectDataFactory() noexcept { return extraObjectDataFactory_; } ObjectFactory& objectFactory() noexcept { return objectFactory_; } gc::GCScheduler& gcScheduler() noexcept { return gcScheduler_; } gc::GC& gc() noexcept { return gc_; } @@ -39,6 +41,7 @@ private: ThreadRegistry threadRegistry_; GlobalsRegistry globalsRegistry_; StableRefRegistry stableRefRegistry_; + ExtraObjectDataFactory extraObjectDataFactory_; ObjectFactory objectFactory_; gc::GCScheduler gcScheduler_; gc::GC gc_; diff --git a/kotlin-native/runtime/src/mm/cpp/ThreadData.hpp b/kotlin-native/runtime/src/mm/cpp/ThreadData.hpp index c81c19343a4..f6b20598dcb 100644 --- a/kotlin-native/runtime/src/mm/cpp/ThreadData.hpp +++ b/kotlin-native/runtime/src/mm/cpp/ThreadData.hpp @@ -13,6 +13,7 @@ #include "GC.hpp" #include "GCScheduler.hpp" #include "ObjectFactory.hpp" +#include "ExtraObjectDataFactory.hpp" #include "ShadowStack.hpp" #include "StableRefRegistry.hpp" #include "ThreadLocalStorage.hpp" @@ -33,6 +34,7 @@ public: threadId_(threadId), globalsThreadQueue_(GlobalsRegistry::Instance()), stableRefThreadQueue_(StableRefRegistry::Instance()), + extraObjectDataThreadQueue_(ExtraObjectDataFactory::Instance()), gcScheduler_(GlobalData::Instance().gcScheduler().NewThreadData()), gc_(GlobalData::Instance().gc(), *this), objectFactoryThreadQueue_(GlobalData::Instance().objectFactory(), gc_), @@ -48,6 +50,8 @@ public: StableRefRegistry::ThreadQueue& stableRefThreadQueue() noexcept { return stableRefThreadQueue_; } + ExtraObjectDataFactory::ThreadQueue& extraObjectDataThreadQueue() noexcept { return extraObjectDataThreadQueue_; } + ThreadState state() noexcept { return suspensionData_.state(); } ThreadState setState(ThreadState state) noexcept { return suspensionData_.setState(state); } @@ -69,12 +73,14 @@ public: globalsThreadQueue_.Publish(); stableRefThreadQueue_.Publish(); objectFactoryThreadQueue_.Publish(); + extraObjectDataThreadQueue_.Publish(); } void ClearForTests() noexcept { globalsThreadQueue_.ClearForTests(); stableRefThreadQueue_.ClearForTests(); objectFactoryThreadQueue_.ClearForTests(); + extraObjectDataThreadQueue_.ClearForTests(); } private: @@ -82,6 +88,7 @@ private: GlobalsRegistry::ThreadQueue globalsThreadQueue_; ThreadLocalStorage tls_; StableRefRegistry::ThreadQueue stableRefThreadQueue_; + ExtraObjectDataFactory::ThreadQueue extraObjectDataThreadQueue_; ShadowStack shadowStack_; gc::GCSchedulerThreadData gcScheduler_; gc::GC::ThreadData gc_;