[K/N] Simplify ObjectFactory ^KT-51436

Merge-request: KT-MR-5958
Merged-by: Alexander Shabalin <Alexander.Shabalin@jetbrains.com>
This commit is contained in:
Alexander Shabalin
2022-03-31 09:43:47 +00:00
committed by Space
parent 4873f18067
commit 421ad77740
12 changed files with 85 additions and 123 deletions
@@ -42,7 +42,7 @@ struct MarkTraits {
}
static void enqueue(MarkQueue& queue, ObjHeader* object) noexcept {
auto& objectData = mm::ObjectFactory<gc::ConcurrentMarkAndSweep>::NodeRef::From(object).GCObjectData();
auto& objectData = mm::ObjectFactory<gc::ConcurrentMarkAndSweep>::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<gc::ConcurrentMarkAndSweep>::NodeRef::From(baseObject).GCObjectData();
auto& objectData = mm::ObjectFactory<gc::ConcurrentMarkAndSweep>::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;
@@ -190,10 +190,10 @@ test_support::Object<Payload>& AllocateObjectWithFinalizer(mm::ThreadData& threa
KStdVector<ObjHeader*> Alive(mm::ThreadData& threadData) {
KStdVector<ObjHeader*> 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<gc::ConcurrentMarkAndSweep>::NodeRef::From(objHeader);
return nodeRef.GCObjectData().color();
return nodeRef.ObjectData().color();
}
WeakCounter& InstallWeakCounter(mm::ThreadData& threadData, ObjHeader* objHeader, ObjHeader** location) {
@@ -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_; }
@@ -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 {
@@ -44,7 +44,7 @@ test_support::TypeInfoHolder typeHolder{test_support::TypeInfoHolder::ObjectBuil
test_support::TypeInfoHolder typeHolderWithFinalizer{test_support::TypeInfoHolder::ObjectBuilder<Payload>().addFlag(TF_HAS_FINALIZER)};
test_support::TypeInfoHolder typeHolderWeakCounter{test_support::TypeInfoHolder::ObjectBuilder<WeakCounterPayload>()};
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<GC>;
using ObjectFactory = mm::ObjectFactory<ObjectFactoryTraits>;
using ExtraObjectsDataFactory = mm::ExtraObjectDataFactory;
class Object : public test_support::Object<Payload> {
@@ -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<WeakCounterPayload>;
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<SweepTraits>(objectFactory_);
KStdVector<ObjHeader*> 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<ObjHeader*> Alive() {
KStdVector<ObjHeader*> 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<ObjectFactory::FinalizerQueue> 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);
}
@@ -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_; }
@@ -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_; }
@@ -40,7 +40,7 @@ struct MarkTraits {
}
static void enqueue(MarkQueue& queue, ObjHeader* object) noexcept {
auto& objectData = mm::ObjectFactory<gc::SameThreadMarkAndSweep>::NodeRef::From(object).GCObjectData();
auto& objectData = mm::ObjectFactory<gc::SameThreadMarkAndSweep>::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<gc::SameThreadMarkAndSweep>::NodeRef::From(baseObject).GCObjectData();
auto& objectData = mm::ObjectFactory<gc::SameThreadMarkAndSweep>::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;
@@ -190,10 +190,10 @@ test_support::Object<Payload>& AllocateObjectWithFinalizer(mm::ThreadData& threa
KStdVector<ObjHeader*> Alive(mm::ThreadData& threadData) {
KStdVector<ObjHeader*> 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<gc::SameThreadMarkAndSweep>::NodeRef::From(objHeader);
return nodeRef.GCObjectData().color();
return nodeRef.ObjectData().color();
}
WeakCounter& InstallWeakCounter(mm::ThreadData& threadData, ObjHeader* objHeader, ObjHeader** location) {
@@ -93,6 +93,7 @@ struct ObjHeader {
}
// Unsafe cast to ArrayHeader. Use carefully!
// TODO: RuntimeAssert on type_info()->IsArray()?
ArrayHeader* array() { return reinterpret_cast<ArrayHeader*>(this); }
const ArrayHeader* array() const { return reinterpret_cast<const ArrayHeader*>(this); }
@@ -427,21 +427,20 @@ private:
} // namespace internal
template <typename GC>
template <typename Traits>
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<HeapObjHeader*>(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<HeapObjHeader*>(node_.Data())->object;
return object->type_info()->IsArray();
}
ObjHeader* GetObjHeader() noexcept {
auto* object = &static_cast<HeapObjHeader*>(node_.Data())->object;
RuntimeAssert(!object->type_info()->IsArray(), "Must not be an array");
return object;
}
ArrayHeader* GetArrayHeader() noexcept {
auto* array = &static_cast<HeapArrayHeader*>(node_.Data())->array;
RuntimeAssert(array->type_info()->IsArray(), "Must be an array");
return array;
return &static_cast<HeapObjHeader*>(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());
}
}
@@ -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<GC>;
using ObjectFactory = mm::ObjectFactory<ObjectFactoryTraits>;
struct Payload {
ObjHeader* field1;
@@ -864,9 +855,8 @@ TEST(ObjectFactoryTest, CreateObject) {
testing::StrictMock<MockAllocator> allocator;
test_support::TypeInfoHolder type{test_support::TypeInfoHolder::ObjectBuilder<Payload>()};
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<size_t>(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<MockAllocator> 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<size_t>(-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<MockAllocator> 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<size_t>(-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<MockAllocator> allocator;
test_support::TypeInfoHolder objectType{test_support::TypeInfoHolder::ObjectBuilder<Payload>()};
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<MockAllocator> allocator;
test_support::TypeInfoHolder objectType{test_support::TypeInfoHolder::ObjectBuilder<Payload>()};
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<Payload>().addFlag(TF_HAS_FINALIZER)};
GC::ThreadData gc;
ObjectFactory objectFactory;
ObjectFactory::ThreadQueue threadQueue(objectFactory, gc);
ObjectFactory::ThreadQueue threadQueue(objectFactory, GlobalMockAllocator());
ObjectFactory::FinalizerQueue finalizerQueue;
KStdVector<ObjHeader*> 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<std::mutex> guard(expectedMutex);