[K/N] Optimize finalizing of simple extra objects

There is no need to delay ExtraObject deletion when it doesn't have
associated object. We can just remove it while iterating on them.
This commit is contained in:
Pavel Kunyavskiy
2021-11-02 12:01:10 +03:00
committed by Space
parent ff3abf9fc0
commit b22dec062c
9 changed files with 72 additions and 39 deletions
@@ -71,9 +71,16 @@ void SweepExtraObjects(typename Traits::ExtraObjectsFactory& objectFactory) noex
auto &extraObject = *it;
if (!Traits::IsMarkedByExtraObject(extraObject)) {
extraObject.ClearWeakReferenceCounter();
extraObject.DetachAssociatedObject();
if (extraObject.HasAssociatedObject()) {
extraObject.DetachAssociatedObject();
++it;
} else {
extraObject.Uninstall();
objectFactory.EraseAndAdvance(it);
}
} else {
++it;
}
++it;
}
}
@@ -50,6 +50,7 @@ public:
auto& extraObjectData = mm::ExtraObjectData::GetOrInstall(GetObjHeader());
auto *setCounter = extraObjectData.GetOrSetWeakReferenceCounter(GetObjHeader(), counter.GetObjHeader());
EXPECT_EQ(setCounter, counter.GetObjHeader());
EXPECT_EQ(extraObjectData.GetBaseObject(), GetObjHeader());
}
protected:
@@ -340,6 +341,7 @@ TEST_F(MarkAndSweepUtilsMarkTest, MarkSingleCharArrayWithExtraData) {
TEST_F(MarkAndSweepUtilsMarkTest, MarkSingleObjectWithWeakCounter) {
Object weakCounter;
Object object;
weakCounter->field1 = object.header();
object.InstallWeakCounter(weakCounter);
auto stats = Mark({object});
@@ -352,6 +354,7 @@ TEST_F(MarkAndSweepUtilsMarkTest, MarkSingleObjectWithWeakCounter) {
TEST_F(MarkAndSweepUtilsMarkTest, MarkSingleObjectArrayWithWeakCounter) {
Object weakCounter;
ObjectArray array;
weakCounter->field1 = array.header();
array.InstallWeakCounter(weakCounter);
auto stats = Mark({array});
@@ -364,6 +367,7 @@ TEST_F(MarkAndSweepUtilsMarkTest, MarkSingleObjectArrayWithWeakCounter) {
TEST_F(MarkAndSweepUtilsMarkTest, MarkSingleCharArrayWithWeakCounter) {
Object weakCounter;
CharArray array;
weakCounter->field1 = array.header();
array.InstallWeakCounter(weakCounter);
auto stats = Mark({array});
@@ -377,6 +381,7 @@ TEST_F(MarkAndSweepUtilsMarkTest, MarkSingleObjectWithInvalidFieldsWithWeakCount
Object weakCounter;
Object object;
object->field1 = kInitializingSingleton;
weakCounter->field1 = object.header();
object.InstallWeakCounter(weakCounter);
auto stats = Mark({object});
@@ -390,6 +395,7 @@ TEST_F(MarkAndSweepUtilsMarkTest, MarkSingleObjectArrayWithInvalidFieldsWithWeak
Object weakCounter;
ObjectArray array;
array.elements()[0] = kInitializingSingleton;
weakCounter->field1 = array.header();
array.InstallWeakCounter(weakCounter);
auto stats = Mark({array});
@@ -405,6 +411,7 @@ TEST_F(MarkAndSweepUtilsMarkTest, MarkSingleCharArrayWithSomeDataWithWeakCounter
array.elements()[0] = 'a';
array.elements()[1] = 'b';
array.elements()[2] = 'c';
weakCounter->field1 = array.header();
array.InstallWeakCounter(weakCounter);
auto stats = Mark({array});
@@ -177,8 +177,7 @@ public:
~MarkAndSweepUtilsSweepTest() override {
auto deallocExtraObject = [this](ObjHeader* obj) {
auto *extraObject = mm::ExtraObjectData::Get(obj);
EXPECT_NE(extraObject, nullptr);
obj->typeInfoOrMeta_ = const_cast<TypeInfo*>(obj->type_info());
extraObject->Uninstall();
extraObjectFactory_.DestroyExtraObjectData(extraObjectFactoryThreadQueue_, *extraObject);
extraObjectFactoryThreadQueue_.Publish();
};
@@ -223,6 +222,14 @@ public:
return objects;
}
KStdVector<mm::ExtraObjectData*> AliveExtraObjects() {
KStdVector<mm::ExtraObjectData*> objects;
for (auto &node : extraObjectFactory_.LockForIter()) {
objects.push_back(&node);
}
return objects;
}
Object& AllocateObject(const TypeInfo* typeInfo = typeHolder.typeInfo()) {
auto* object = objectFactoryThreadQueue_.CreateObject(typeInfo);
objectFactoryThreadQueue_.Publish();
@@ -357,9 +364,9 @@ TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleObjectWithExtraData) {
auto finalizers = Sweep();
EXPECT_THAT(finalizers, testing::UnorderedElementsAre(object.header()));
EXPECT_THAT(finalizers, testing::UnorderedElementsAre());
EXPECT_THAT(Alive(), testing::UnorderedElementsAre());
EXPECT_THAT(object.state(), GC::ObjectData::State::kUnmarked);
EXPECT_THAT(AliveExtraObjects(), testing::UnorderedElementsAre());
}
TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleObjectArrayWithExtraData) {
@@ -369,9 +376,9 @@ TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleObjectArrayWithExtraData) {
auto finalizers = Sweep();
EXPECT_THAT(finalizers, testing::UnorderedElementsAre(array.header()));
EXPECT_THAT(finalizers, testing::UnorderedElementsAre());
EXPECT_THAT(Alive(), testing::UnorderedElementsAre());
EXPECT_THAT(array.state(), GC::ObjectData::State::kUnmarked);
EXPECT_THAT(AliveExtraObjects(), testing::UnorderedElementsAre());
}
TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleCharArrayWithExtraData) {
@@ -381,14 +388,14 @@ TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleCharArrayWithExtraData) {
auto finalizers = Sweep();
EXPECT_THAT(finalizers, testing::UnorderedElementsAre(array.header()));
EXPECT_THAT(finalizers, testing::UnorderedElementsAre());
EXPECT_THAT(Alive(), testing::UnorderedElementsAre());
EXPECT_THAT(array.state(), GC::ObjectData::State::kUnmarked);
EXPECT_THAT(AliveExtraObjects(), testing::UnorderedElementsAre());
}
TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedObjectWithExtraData) {
auto& object = AllocateObject();
InstallExtraData(object.header());
auto& extra = InstallExtraData(object.header());
object.Mark();
ASSERT_THAT(Alive(), testing::UnorderedElementsAre(object.header()));
@@ -396,12 +403,12 @@ TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedObjectWithExtraData) {
EXPECT_THAT(finalizers, testing::UnorderedElementsAre());
EXPECT_THAT(Alive(), testing::UnorderedElementsAre(object.header()));
EXPECT_THAT(object.state(), GC::ObjectData::State::kMarkReset);
EXPECT_THAT(AliveExtraObjects(), testing::UnorderedElementsAre(&extra));
}
TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedObjectArrayWithExtraData) {
auto& array = AllocateObjectArray();
InstallExtraData(array.header());
auto& extra = InstallExtraData(array.header());
array.Mark();
ASSERT_THAT(Alive(), testing::UnorderedElementsAre(array.header()));
@@ -409,12 +416,12 @@ TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedObjectArrayWithExtraData) {
EXPECT_THAT(finalizers, testing::UnorderedElementsAre());
EXPECT_THAT(Alive(), testing::UnorderedElementsAre(array.header()));
EXPECT_THAT(array.state(), GC::ObjectData::State::kMarkReset);
EXPECT_THAT(AliveExtraObjects(), testing::UnorderedElementsAre(&extra));
}
TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedCharArrayWithExtraData) {
auto& array = AllocateCharArray();
InstallExtraData(array.header());
auto& extra = InstallExtraData(array.header());
array.Mark();
ASSERT_THAT(Alive(), testing::UnorderedElementsAre(array.header()));
@@ -422,7 +429,7 @@ TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedCharArrayWithExtraData) {
EXPECT_THAT(finalizers, testing::UnorderedElementsAre());
EXPECT_THAT(Alive(), testing::UnorderedElementsAre(array.header()));
EXPECT_THAT(array.state(), GC::ObjectData::State::kMarkReset);
EXPECT_THAT(AliveExtraObjects(), testing::UnorderedElementsAre(&extra));
}
TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleObjectWithFinalizerHook) {
@@ -457,10 +464,8 @@ TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleObjectWithWeakCounter) {
auto finalizers = Sweep();
EXPECT_THAT(finalizers, testing::UnorderedElementsAre(object.header()));
EXPECT_THAT(finalizers, testing::UnorderedElementsAre());
EXPECT_THAT(Alive(), testing::UnorderedElementsAre());
EXPECT_THAT(object.state(), GC::ObjectData::State::kUnmarked);
EXPECT_FALSE(object.HasWeakCounter());
}
TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleObjectArrayWithWeakCounter) {
@@ -470,10 +475,8 @@ TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleObjectArrayWithWeakCounter) {
auto finalizers = Sweep();
EXPECT_THAT(finalizers, testing::UnorderedElementsAre(array.header()));
EXPECT_THAT(finalizers, testing::UnorderedElementsAre());
EXPECT_THAT(Alive(), testing::UnorderedElementsAre());
EXPECT_THAT(array.state(), GC::ObjectData::State::kUnmarked);
EXPECT_FALSE(array.HasWeakCounter());
}
TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleCharArrayWithWeakCounter) {
@@ -483,10 +486,8 @@ TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleCharArrayWithWeakCounter) {
auto finalizers = Sweep();
EXPECT_THAT(finalizers, testing::UnorderedElementsAre(array.header()));
EXPECT_THAT(finalizers, testing::UnorderedElementsAre());
EXPECT_THAT(Alive(), testing::UnorderedElementsAre());
EXPECT_THAT(array.state(), GC::ObjectData::State::kUnmarked);
EXPECT_FALSE(array.HasWeakCounter());
}
TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedObjectWithWeakCounter) {
@@ -160,6 +160,11 @@ public:
deletionQueue_ = std::move(remainingDeletions);
}
// requires LockForIter
void EraseAndAdvance(Iterator &it) {
it.position_ = queue_.erase(it.position_);
}
void ClearForTests() noexcept {
queue_.clear();
deletionQueue_.clear();
@@ -56,20 +56,15 @@ mm::ExtraObjectData& mm::ExtraObjectData::Install(ObjHeader* object) noexcept {
return data;
}
// static
void mm::ExtraObjectData::Uninstall(ObjHeader* object) noexcept {
RuntimeAssert(object->has_meta_object(), "Object must have a meta object set");
void mm::ExtraObjectData::Uninstall() noexcept {
auto *object = GetBaseObject();
*const_cast<const TypeInfo**>(&object->typeInfoOrMeta_) = typeInfo_;
RuntimeAssert(!object->has_meta_object(), "Object has metaobject after removing metaobject");
auto& data = ExtraObjectData::FromMetaObjHeader(object->meta_object());
*const_cast<const TypeInfo**>(&object->typeInfoOrMeta_) = data.typeInfo_;
auto *threadData = mm::ThreadRegistry::Instance().CurrentThreadData();
#ifdef KONAN_OBJC_INTEROP
Kotlin_ObjCExport_releaseAssociatedObject(data.associatedObject_);
data.associatedObject_ = nullptr;
Kotlin_ObjCExport_releaseAssociatedObject(associatedObject_);
associatedObject_ = nullptr;
#endif
mm::ExtraObjectDataFactory::Instance().DestroyExtraObjectData(threadData, data);
}
void mm::ExtraObjectData::DetachAssociatedObject() noexcept {
@@ -78,6 +73,15 @@ void mm::ExtraObjectData::DetachAssociatedObject() noexcept {
#endif
}
bool mm::ExtraObjectData::HasAssociatedObject() noexcept {
#ifdef KONAN_OBJC_INTEROP
return associatedObject_ != nullptr;
#else
return false;
#endif
}
void mm::ExtraObjectData::ClearWeakReferenceCounter() noexcept {
if (!HasWeakReferenceCounter()) return;
@@ -41,11 +41,12 @@ public:
static ExtraObjectData& GetOrInstall(ObjHeader* object) noexcept { return FromMetaObjHeader(object->meta_object()); }
static ExtraObjectData& Install(ObjHeader* object) noexcept;
static void Uninstall(ObjHeader* object) noexcept;
void Uninstall() noexcept;
#ifdef KONAN_OBJC_INTEROP
void** GetAssociatedObjectLocation() noexcept { return &associatedObject_; }
#endif
bool HasAssociatedObject() noexcept;
void DetachAssociatedObject() noexcept;
std::atomic<Flags>& flags() noexcept { return flags_; }
@@ -53,6 +53,9 @@ public:
size_t GetSizeUnsafe() noexcept { return extraObjects_.GetSizeUnsafe(); }
// requires LockForIter
void EraseAndAdvance(Iterator &it) { extraObjects_.EraseAndAdvance(it); }
private:
Queue extraObjects_;
};
@@ -52,7 +52,8 @@ TEST_F(ExtraObjectDataTest, Install) {
EXPECT_FALSE(extraData.HasWeakReferenceCounter());
EXPECT_THAT(extraData.GetBaseObject(), object.header());
mm::ExtraObjectData::Uninstall(object.header());
extraData.Uninstall();
mm::GlobalData::Instance().threadRegistry().CurrentThreadData()->ClearForTests();
EXPECT_FALSE(object.header()->has_meta_object());
EXPECT_THAT(object.header()->type_info(), typeInfo);
+5 -1
View File
@@ -82,7 +82,11 @@ MetaObjHeader* ObjHeader::createMetaObject(ObjHeader* object) {
// static
void ObjHeader::destroyMetaObject(ObjHeader* object) {
mm::ExtraObjectData::Uninstall(object);
RuntimeAssert(object->has_meta_object(), "Object must have a meta object set");
auto &extraObject = *mm::ExtraObjectData::Get(object);
extraObject.Uninstall();
auto *threadData = mm::ThreadRegistry::Instance().CurrentThreadData();
mm::ExtraObjectDataFactory::Instance().DestroyExtraObjectData(threadData, extraObject);
}
ALWAYS_INLINE bool isPermanentOrFrozen(const ObjHeader* obj) {