[K/N] Separate sweep pass for extra-objects
^KT-49325
This commit is contained in:
@@ -48,6 +48,20 @@ void Mark(KStdVector<ObjHeader*> graySet) noexcept {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Traits>
|
||||||
|
void SweepExtraObjects(typename Traits::ExtraObjectsFactory& objectFactory) noexcept {
|
||||||
|
objectFactory.ProcessDeletions();
|
||||||
|
auto iter = objectFactory.LockForIter();
|
||||||
|
for (auto it = iter.begin(); it != iter.end();) {
|
||||||
|
auto &extraObject = *it;
|
||||||
|
if (!Traits::IsMarkedByExtraObject(extraObject)) {
|
||||||
|
extraObject.ClearWeakReferenceCounter();
|
||||||
|
extraObject.DetachAssociatedObject();
|
||||||
|
}
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <typename Traits>
|
template <typename Traits>
|
||||||
typename Traits::ObjectFactory::FinalizerQueue Sweep(typename Traits::ObjectFactory& objectFactory) noexcept {
|
typename Traits::ObjectFactory::FinalizerQueue Sweep(typename Traits::ObjectFactory& objectFactory) noexcept {
|
||||||
typename Traits::ObjectFactory::FinalizerQueue finalizerQueue;
|
typename Traits::ObjectFactory::FinalizerQueue finalizerQueue;
|
||||||
@@ -59,10 +73,6 @@ typename Traits::ObjectFactory::FinalizerQueue Sweep(typename Traits::ObjectFact
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
auto* objHeader = it->IsArray() ? it->GetArrayHeader()->obj() : it->GetObjHeader();
|
auto* objHeader = it->IsArray() ? it->GetArrayHeader()->obj() : it->GetObjHeader();
|
||||||
if (auto* extraObject = mm::ExtraObjectData::Get(objHeader)) {
|
|
||||||
extraObject->ClearWeakReferenceCounter();
|
|
||||||
extraObject->DetachAssociatedObject();
|
|
||||||
}
|
|
||||||
if (HasFinalizers(objHeader)) {
|
if (HasFinalizers(objHeader)) {
|
||||||
iter.MoveAndAdvance(finalizerQueue, it);
|
iter.MoveAndAdvance(finalizerQueue, it);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "FinalizerHooksTestSupport.hpp"
|
#include "FinalizerHooksTestSupport.hpp"
|
||||||
#include "ObjectFactory.hpp"
|
#include "ObjectFactory.hpp"
|
||||||
#include "ObjectTestSupport.hpp"
|
#include "ObjectTestSupport.hpp"
|
||||||
|
#include "ExtraObjectDataFactory.hpp"
|
||||||
|
|
||||||
using namespace kotlin;
|
using namespace kotlin;
|
||||||
|
|
||||||
@@ -59,6 +60,7 @@ struct GC {
|
|||||||
};
|
};
|
||||||
|
|
||||||
using ObjectFactory = mm::ObjectFactory<GC>;
|
using ObjectFactory = mm::ObjectFactory<GC>;
|
||||||
|
using ExtraObjectsDataFactory = mm::ExtraObjectDataFactory;
|
||||||
|
|
||||||
class Object : public test_support::Object<Payload> {
|
class Object : public test_support::Object<Payload> {
|
||||||
public:
|
public:
|
||||||
@@ -68,7 +70,6 @@ public:
|
|||||||
|
|
||||||
static Object& FromObjHeader(ObjHeader* obj) { return static_cast<Object&>(test_support::Object<Payload>::FromObjHeader(obj)); }
|
static Object& FromObjHeader(ObjHeader* obj) { return static_cast<Object&>(test_support::Object<Payload>::FromObjHeader(obj)); }
|
||||||
|
|
||||||
void InstallExtraData() { mm::ExtraObjectData::Install(header()); }
|
|
||||||
|
|
||||||
bool HasWeakCounter() {
|
bool HasWeakCounter() {
|
||||||
if (auto* extraObjectData = mm::ExtraObjectData::Get(header())) {
|
if (auto* extraObjectData = mm::ExtraObjectData::Get(header())) {
|
||||||
@@ -95,8 +96,6 @@ public:
|
|||||||
return static_cast<ObjectArray&>(test_support::ObjectArray<3>::FromArrayHeader(array));
|
return static_cast<ObjectArray&>(test_support::ObjectArray<3>::FromArrayHeader(array));
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstallExtraData() { mm::ExtraObjectData::Install(header()); }
|
|
||||||
|
|
||||||
bool HasWeakCounter() {
|
bool HasWeakCounter() {
|
||||||
if (auto* extraObjectData = mm::ExtraObjectData::Get(header())) {
|
if (auto* extraObjectData = mm::ExtraObjectData::Get(header())) {
|
||||||
return extraObjectData->HasWeakReferenceCounter();
|
return extraObjectData->HasWeakReferenceCounter();
|
||||||
@@ -122,8 +121,6 @@ public:
|
|||||||
return static_cast<CharArray&>(test_support::CharArray<3>::FromArrayHeader(array));
|
return static_cast<CharArray&>(test_support::CharArray<3>::FromArrayHeader(array));
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstallExtraData() { mm::ExtraObjectData::Install(header()); }
|
|
||||||
|
|
||||||
bool HasWeakCounter() {
|
bool HasWeakCounter() {
|
||||||
if (auto* extraObjectData = mm::ExtraObjectData::Get(header())) {
|
if (auto* extraObjectData = mm::ExtraObjectData::Get(header())) {
|
||||||
return extraObjectData->HasWeakReferenceCounter();
|
return extraObjectData->HasWeakReferenceCounter();
|
||||||
@@ -151,6 +148,12 @@ GC::ObjectData::State GetWeakCounterState(WeakCounter& counter) {
|
|||||||
|
|
||||||
struct SweepTraits {
|
struct SweepTraits {
|
||||||
using ObjectFactory = ObjectFactory;
|
using ObjectFactory = ObjectFactory;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
static bool TryResetMark(ObjectFactory::NodeRef node) {
|
static bool TryResetMark(ObjectFactory::NodeRef node) {
|
||||||
GC::ObjectData& objectData = node.GCObjectData();
|
GC::ObjectData& objectData = node.GCObjectData();
|
||||||
@@ -169,7 +172,20 @@ struct SweepTraits {
|
|||||||
class MarkAndSweepUtilsSweepTest : public ::testing::Test {
|
class MarkAndSweepUtilsSweepTest : public ::testing::Test {
|
||||||
public:
|
public:
|
||||||
~MarkAndSweepUtilsSweepTest() override {
|
~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());
|
||||||
|
extraObjectFactory_.DestroyExtraObjectData(extraObjectFactoryThreadQueue_, *extraObject);
|
||||||
|
extraObjectFactoryThreadQueue_.Publish();
|
||||||
|
};
|
||||||
for (auto& finalizerQueue : finalizers_) {
|
for (auto& finalizerQueue : finalizers_) {
|
||||||
|
for (auto node : finalizerQueue.IterForTests()) {
|
||||||
|
auto *object = node->IsArray() ? node->GetArrayHeader()->obj() : node->GetObjHeader();
|
||||||
|
if (object->has_meta_object()) {
|
||||||
|
deallocExtraObject(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
finalizerQueue.Finalize();
|
finalizerQueue.Finalize();
|
||||||
}
|
}
|
||||||
testing::Mock::VerifyAndClear(&finalizerHook());
|
testing::Mock::VerifyAndClear(&finalizerHook());
|
||||||
@@ -179,12 +195,14 @@ public:
|
|||||||
auto* obj = node->IsArray() ? node->GetArrayHeader()->obj() : node->GetObjHeader();
|
auto* obj = node->IsArray() ? node->GetArrayHeader()->obj() : node->GetObjHeader();
|
||||||
if (auto* extraObject = mm::ExtraObjectData::Get(obj)) {
|
if (auto* extraObject = mm::ExtraObjectData::Get(obj)) {
|
||||||
extraObject->ClearWeakReferenceCounter();
|
extraObject->ClearWeakReferenceCounter();
|
||||||
|
deallocExtraObject(obj);
|
||||||
}
|
}
|
||||||
RunFinalizers(obj);
|
RunFinalizers(obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
KStdVector<ObjHeader*> Sweep() {
|
KStdVector<ObjHeader*> Sweep() {
|
||||||
|
gc::SweepExtraObjects<SweepTraits>(extraObjectFactory_);
|
||||||
auto finalizers = gc::Sweep<SweepTraits>(objectFactory_);
|
auto finalizers = gc::Sweep<SweepTraits>(objectFactory_);
|
||||||
KStdVector<ObjHeader*> objects;
|
KStdVector<ObjHeader*> objects;
|
||||||
for (auto node : finalizers.IterForTests()) {
|
for (auto node : finalizers.IterForTests()) {
|
||||||
@@ -220,11 +238,18 @@ public:
|
|||||||
return CharArray::FromArrayHeader(array);
|
return CharArray::FromArrayHeader(array);
|
||||||
}
|
}
|
||||||
|
|
||||||
WeakCounter& InstallWeakCounter(ObjHeader* objHeader) {
|
mm::ExtraObjectData& InstallExtraData(ObjHeader *objHeader) {
|
||||||
|
auto& extraObjectData = extraObjectFactory_.CreateExtraObjectDataForObject(extraObjectFactoryThreadQueue_, objHeader, objHeader->type_info());
|
||||||
|
extraObjectFactoryThreadQueue_.Publish();
|
||||||
|
objHeader->typeInfoOrMeta_ = reinterpret_cast<TypeInfo*>(&extraObjectData);
|
||||||
|
return *mm::ExtraObjectData::Get(objHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
WeakCounter& InstallWeakCounter(ObjHeader *objHeader) {
|
||||||
auto* weakCounterHeader = objectFactoryThreadQueue_.CreateObject(typeHolderWeakCounter.typeInfo());
|
auto* weakCounterHeader = objectFactoryThreadQueue_.CreateObject(typeHolderWeakCounter.typeInfo());
|
||||||
objectFactoryThreadQueue_.Publish();
|
objectFactoryThreadQueue_.Publish();
|
||||||
auto& weakCounter = WeakCounter::FromObjHeader(weakCounterHeader);
|
auto& weakCounter = WeakCounter::FromObjHeader(weakCounterHeader);
|
||||||
auto& extraObjectData = mm::ExtraObjectData::GetOrInstall(objHeader);
|
auto& extraObjectData = InstallExtraData(objHeader);
|
||||||
auto *setHeader = extraObjectData.GetOrSetWeakReferenceCounter(objHeader, weakCounter.header());
|
auto *setHeader = extraObjectData.GetOrSetWeakReferenceCounter(objHeader, weakCounter.header());
|
||||||
EXPECT_EQ(setHeader, weakCounter.header());
|
EXPECT_EQ(setHeader, weakCounter.header());
|
||||||
weakCounter->referred = objHeader;
|
weakCounter->referred = objHeader;
|
||||||
@@ -240,6 +265,8 @@ private:
|
|||||||
GC::ThreadData gcThreadData_;
|
GC::ThreadData gcThreadData_;
|
||||||
ObjectFactory objectFactory_;
|
ObjectFactory objectFactory_;
|
||||||
ObjectFactory::ThreadQueue objectFactoryThreadQueue_{objectFactory_, gcThreadData_};
|
ObjectFactory::ThreadQueue objectFactoryThreadQueue_{objectFactory_, gcThreadData_};
|
||||||
|
ExtraObjectsDataFactory extraObjectFactory_;
|
||||||
|
ExtraObjectsDataFactory::ThreadQueue extraObjectFactoryThreadQueue_{extraObjectFactory_};
|
||||||
KStdVector<ObjectFactory::FinalizerQueue> finalizers_;
|
KStdVector<ObjectFactory::FinalizerQueue> finalizers_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -322,7 +349,7 @@ TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedCharArray) {
|
|||||||
|
|
||||||
TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleObjectWithExtraData) {
|
TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleObjectWithExtraData) {
|
||||||
auto& object = AllocateObject();
|
auto& object = AllocateObject();
|
||||||
object.InstallExtraData();
|
InstallExtraData(object.header());
|
||||||
ASSERT_THAT(Alive(), testing::UnorderedElementsAre(object.header()));
|
ASSERT_THAT(Alive(), testing::UnorderedElementsAre(object.header()));
|
||||||
|
|
||||||
auto finalizers = Sweep();
|
auto finalizers = Sweep();
|
||||||
@@ -334,7 +361,7 @@ TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleObjectWithExtraData) {
|
|||||||
|
|
||||||
TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleObjectArrayWithExtraData) {
|
TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleObjectArrayWithExtraData) {
|
||||||
auto& array = AllocateObjectArray();
|
auto& array = AllocateObjectArray();
|
||||||
array.InstallExtraData();
|
InstallExtraData(array.header());
|
||||||
ASSERT_THAT(Alive(), testing::UnorderedElementsAre(array.header()));
|
ASSERT_THAT(Alive(), testing::UnorderedElementsAre(array.header()));
|
||||||
|
|
||||||
auto finalizers = Sweep();
|
auto finalizers = Sweep();
|
||||||
@@ -346,7 +373,7 @@ TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleObjectArrayWithExtraData) {
|
|||||||
|
|
||||||
TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleCharArrayWithExtraData) {
|
TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleCharArrayWithExtraData) {
|
||||||
auto& array = AllocateCharArray();
|
auto& array = AllocateCharArray();
|
||||||
array.InstallExtraData();
|
InstallExtraData(array.header());
|
||||||
ASSERT_THAT(Alive(), testing::UnorderedElementsAre(array.header()));
|
ASSERT_THAT(Alive(), testing::UnorderedElementsAre(array.header()));
|
||||||
|
|
||||||
auto finalizers = Sweep();
|
auto finalizers = Sweep();
|
||||||
@@ -358,7 +385,7 @@ TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleCharArrayWithExtraData) {
|
|||||||
|
|
||||||
TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedObjectWithExtraData) {
|
TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedObjectWithExtraData) {
|
||||||
auto& object = AllocateObject();
|
auto& object = AllocateObject();
|
||||||
object.InstallExtraData();
|
InstallExtraData(object.header());
|
||||||
object.Mark();
|
object.Mark();
|
||||||
ASSERT_THAT(Alive(), testing::UnorderedElementsAre(object.header()));
|
ASSERT_THAT(Alive(), testing::UnorderedElementsAre(object.header()));
|
||||||
|
|
||||||
@@ -371,7 +398,7 @@ TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedObjectWithExtraData) {
|
|||||||
|
|
||||||
TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedObjectArrayWithExtraData) {
|
TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedObjectArrayWithExtraData) {
|
||||||
auto& array = AllocateObjectArray();
|
auto& array = AllocateObjectArray();
|
||||||
array.InstallExtraData();
|
InstallExtraData(array.header());
|
||||||
array.Mark();
|
array.Mark();
|
||||||
ASSERT_THAT(Alive(), testing::UnorderedElementsAre(array.header()));
|
ASSERT_THAT(Alive(), testing::UnorderedElementsAre(array.header()));
|
||||||
|
|
||||||
@@ -384,7 +411,7 @@ TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedObjectArrayWithExtraData) {
|
|||||||
|
|
||||||
TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedCharArrayWithExtraData) {
|
TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedCharArrayWithExtraData) {
|
||||||
auto& array = AllocateCharArray();
|
auto& array = AllocateCharArray();
|
||||||
array.InstallExtraData();
|
InstallExtraData(array.header());
|
||||||
array.Mark();
|
array.Mark();
|
||||||
ASSERT_THAT(Alive(), testing::UnorderedElementsAre(array.header()));
|
ASSERT_THAT(Alive(), testing::UnorderedElementsAre(array.header()));
|
||||||
|
|
||||||
@@ -473,6 +500,7 @@ TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedObjectWithWeakCounter) {
|
|||||||
EXPECT_THAT(object.state(), GC::ObjectData::State::kMarkReset);
|
EXPECT_THAT(object.state(), GC::ObjectData::State::kMarkReset);
|
||||||
EXPECT_THAT(GetWeakCounterState(weakCounter), GC::ObjectData::State::kMarkReset);
|
EXPECT_THAT(GetWeakCounterState(weakCounter), GC::ObjectData::State::kMarkReset);
|
||||||
EXPECT_TRUE(object.HasWeakCounter());
|
EXPECT_TRUE(object.HasWeakCounter());
|
||||||
|
EXPECT_NE(weakCounter->referred, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedObjectArrayWithWeakCounter) {
|
TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedObjectArrayWithWeakCounter) {
|
||||||
@@ -489,6 +517,7 @@ TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedObjectArrayWithWeakCounter)
|
|||||||
EXPECT_THAT(array.state(), GC::ObjectData::State::kMarkReset);
|
EXPECT_THAT(array.state(), GC::ObjectData::State::kMarkReset);
|
||||||
EXPECT_THAT(GetWeakCounterState(weakCounter), GC::ObjectData::State::kMarkReset);
|
EXPECT_THAT(GetWeakCounterState(weakCounter), GC::ObjectData::State::kMarkReset);
|
||||||
EXPECT_TRUE(array.HasWeakCounter());
|
EXPECT_TRUE(array.HasWeakCounter());
|
||||||
|
EXPECT_NE(weakCounter->referred, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedCharArrayWithWeakCounter) {
|
TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedCharArrayWithWeakCounter) {
|
||||||
@@ -505,6 +534,7 @@ TEST_F(MarkAndSweepUtilsSweepTest, SweepSingleMarkedCharArrayWithWeakCounter) {
|
|||||||
EXPECT_THAT(array.state(), GC::ObjectData::State::kMarkReset);
|
EXPECT_THAT(array.state(), GC::ObjectData::State::kMarkReset);
|
||||||
EXPECT_THAT(GetWeakCounterState(weakCounter), GC::ObjectData::State::kMarkReset);
|
EXPECT_THAT(GetWeakCounterState(weakCounter), GC::ObjectData::State::kMarkReset);
|
||||||
EXPECT_TRUE(array.HasWeakCounter());
|
EXPECT_TRUE(array.HasWeakCounter());
|
||||||
|
EXPECT_NE(weakCounter->referred, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(MarkAndSweepUtilsSweepTest, SweepObjects) {
|
TEST_F(MarkAndSweepUtilsSweepTest, SweepObjects) {
|
||||||
|
|||||||
@@ -38,6 +38,14 @@ struct MarkTraits {
|
|||||||
|
|
||||||
struct SweepTraits {
|
struct SweepTraits {
|
||||||
using ObjectFactory = mm::ObjectFactory<gc::SameThreadMarkAndSweep>;
|
using ObjectFactory = mm::ObjectFactory<gc::SameThreadMarkAndSweep>;
|
||||||
|
using ExtraObjectsFactory = mm::ExtraObjectDataFactory;
|
||||||
|
|
||||||
|
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();
|
||||||
|
return objectData.color() == gc::SameThreadMarkAndSweep::ObjectData::Color::kBlack;
|
||||||
|
}
|
||||||
|
|
||||||
static bool TryResetMark(ObjectFactory::NodeRef node) noexcept {
|
static bool TryResetMark(ObjectFactory::NodeRef node) noexcept {
|
||||||
auto& objectData = node.GCObjectData();
|
auto& objectData = node.GCObjectData();
|
||||||
@@ -192,12 +200,16 @@ bool gc::SameThreadMarkAndSweep::PerformFullGC() noexcept {
|
|||||||
gc::Mark<MarkTraits>(std::move(graySet));
|
gc::Mark<MarkTraits>(std::move(graySet));
|
||||||
auto timeMarkUs = konan::getTimeMicros();
|
auto timeMarkUs = konan::getTimeMicros();
|
||||||
RuntimeLogDebug({kTagGC}, "Marked in %" PRIu64 " microseconds", timeMarkUs - timeRootSetUs);
|
RuntimeLogDebug({kTagGC}, "Marked in %" PRIu64 " microseconds", timeMarkUs - timeRootSetUs);
|
||||||
|
gc::SweepExtraObjects<SweepTraits>(mm::GlobalData::Instance().extraObjectDataFactory());
|
||||||
|
auto timeSweepExtraObjectsUs = konan::getTimeMicros();
|
||||||
|
RuntimeLogDebug({kTagGC}, "Sweeped extra objects in %" PRIu64 " microseconds", timeSweepExtraObjectsUs - timeMarkUs);
|
||||||
finalizerQueue = gc::Sweep<SweepTraits>(mm::GlobalData::Instance().objectFactory());
|
finalizerQueue = gc::Sweep<SweepTraits>(mm::GlobalData::Instance().objectFactory());
|
||||||
auto timeSweepUs = konan::getTimeMicros();
|
auto timeSweepUs = konan::getTimeMicros();
|
||||||
RuntimeLogDebug({kTagGC}, "Sweeped in %" PRIu64 " microseconds", timeSweepUs - timeMarkUs);
|
RuntimeLogDebug({kTagGC}, "Sweeped in %" PRIu64 " microseconds", timeSweepUs - timeSweepExtraObjectsUs);
|
||||||
|
|
||||||
// Can be unsafe, because we've stopped the world.
|
// Can be unsafe, because we've stopped the world.
|
||||||
auto objectsCountAfter = mm::GlobalData::Instance().objectFactory().GetSizeUnsafe();
|
auto objectsCountAfter = mm::GlobalData::Instance().objectFactory().GetSizeUnsafe();
|
||||||
|
auto extraObjectsCountAfter = mm::GlobalData::Instance().extraObjectDataFactory().GetSizeUnsafe();
|
||||||
|
|
||||||
gSafepointFlag = SafepointFlag::kNone;
|
gSafepointFlag = SafepointFlag::kNone;
|
||||||
mm::ResumeThreads();
|
mm::ResumeThreads();
|
||||||
@@ -210,9 +222,9 @@ bool gc::SameThreadMarkAndSweep::PerformFullGC() noexcept {
|
|||||||
|
|
||||||
RuntimeLogInfo(
|
RuntimeLogInfo(
|
||||||
{kTagGC},
|
{kTagGC},
|
||||||
"Finished GC epoch %zu. Collected %zu objects, to be finalized %zu objects, %zu objects remain. Total pause time %" PRIu64
|
"Finished GC epoch %zu. Collected %zu objects, to be finalized %zu objects, %zu objects and %zd extra data objects remain. Total pause time %" PRIu64
|
||||||
" microseconds",
|
" microseconds",
|
||||||
epoch_, collectedCount, finalizersCount, objectsCountAfter, timeResumeUs - timeStartUs);
|
epoch_, collectedCount, finalizersCount, objectsCountAfter, extraObjectsCountAfter, timeResumeUs - timeStartUs);
|
||||||
++epoch_;
|
++epoch_;
|
||||||
lastGCTimestampUs_ = timeResumeUs;
|
lastGCTimestampUs_ = timeResumeUs;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -165,6 +165,10 @@ public:
|
|||||||
deletionQueue_.clear();
|
deletionQueue_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t GetSizeUnsafe() noexcept {
|
||||||
|
return queue_.size();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Using `KStdList` as it allows to implement `Collect` without memory allocations,
|
// Using `KStdList` as it allows to implement `Collect` without memory allocations,
|
||||||
// which is important for GC mark phase.
|
// which is important for GC mark phase.
|
||||||
|
|||||||
@@ -51,6 +51,8 @@ public:
|
|||||||
|
|
||||||
void ClearForTests() noexcept { extraObjects_.ClearForTests(); }
|
void ClearForTests() noexcept { extraObjects_.ClearForTests(); }
|
||||||
|
|
||||||
|
size_t GetSizeUnsafe() noexcept { return extraObjects_.GetSizeUnsafe(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Queue extraObjects_;
|
Queue extraObjects_;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user