[K/N] Rework allocating of ExtraObjectData objects.

^KT-49325
This commit is contained in:
Pavel Kunyavskiy
2021-10-15 16:07:38 +03:00
committed by Space
parent 495a10dd7f
commit da3e31cd3a
10 changed files with 179 additions and 9 deletions
@@ -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<EmptyPayload>().addFlag(TF_HAS_FINALIZER)};
test_support::Object<EmptyPayload> 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<EmptyPayload>()};
test_support::Object<EmptyPayload> object(type.typeInfo());
ObjHeader* obj = object.header();
@@ -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 <typename... Args, typename = std::enable_if_t<std::is_constructible_v<T, Args...>>>
explicit Node(Producer* owner, Args&& ...args) noexcept : value_(std::forward<Args>(args)...), owner_(owner) {}
T& operator*() noexcept { return value_; }
static Node& fromValue(T& t) noexcept {
static_assert(std::is_base_of_v<Pinned, T>, "fromValue function only makes sense for non-movable object");
return *reinterpret_cast<Node*>(reinterpret_cast<uintptr_t>(&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 <typename... Args, typename = std::enable_if_t<std::is_constructible_v<T, Args...>>>
Node* Emplace(Args&& ...value) noexcept {
queue_.emplace_back(this, std::forward<Args>(value)...);
auto& node = queue_.back();
node.position_ = std::prev(queue_.end());
return &node;
@@ -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<TypeInfo*>(data));
TypeInfo* old = __sync_val_compare_and_swap(&object->typeInfoOrMeta_, typeInfo, reinterpret_cast<TypeInfo*>(&data));
if (old != typeInfo) {
// Somebody else created `mm::ExtraObjectData` for this object
delete data;
mm::ExtraObjectDataFactory::Instance().DestroyExtraObjectData(threadData, data);
return *reinterpret_cast<mm::ExtraObjectData*>(old);
}
return *data;
return data;
}
// static
@@ -62,7 +64,12 @@ void mm::ExtraObjectData::Uninstall(ObjHeader* object) noexcept {
*const_cast<const TypeInfo**>(&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
}
@@ -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_;
@@ -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;
@@ -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<MutexThreadStateHandling::kIgnore>;
using Queue = MultiSourceQueue<mm::ExtraObjectData, Mutex>;
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
@@ -26,6 +26,7 @@ struct EmptyPayload {
} // namespace
TEST(ExtraObjectDataTest, Install) {
ScopedMemoryInit init;
test_support::TypeInfoHolder type{test_support::TypeInfoHolder::ObjectBuilder<EmptyPayload>()};
test_support::Object<EmptyPayload> 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<EmptyPayload>()};
test_support::Object<EmptyPayload> 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) {
}
@@ -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;
@@ -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<gc::GC>& 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<gc::GC> objectFactory_;
gc::GCScheduler gcScheduler_;
gc::GC gc_;
@@ -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_;