[K/N] Make GCStatistics handles movable

This commit is contained in:
Aleksei.Glushko
2023-08-28 18:27:44 +02:00
committed by Space Team
parent e48ab4deb4
commit 1437a9bb69
2 changed files with 152 additions and 126 deletions
@@ -410,11 +410,17 @@ void GCHandle::sweptExtraObjects(gc::SweepStats stats) noexcept {
}
}
GCHandle::GCSweepScope GCHandle::sweep() { return GCSweepScope(*this); }
GCHandle::GCSweepExtraObjectsScope GCHandle::sweepExtraObjects() { return GCSweepExtraObjectsScope(*this); }
GCHandle::GCGlobalRootSetScope GCHandle::collectGlobalRoots() { return GCGlobalRootSetScope(*this); }
GCHandle::GCThreadRootSetScope GCHandle::collectThreadRoots(mm::ThreadData& threadData) { return GCThreadRootSetScope(*this, threadData); }
GCHandle::GCMarkScope GCHandle::mark() { return GCMarkScope(*this); }
GCHandle::GCProcessWeaksScope GCHandle::processWeaks() noexcept { return GCProcessWeaksScope(*this); }
GCHandle::GCSweepScope::GCSweepScope(kotlin::gc::GCHandle& handle) : handle_(handle) {}
GCHandle::GCSweepScope::GCSweepScope(kotlin::gc::GCHandle handle) : GCStageScopeBase(handle) {}
GCHandle::GCSweepScope::~GCSweepScope() {
if (!handle_.isValid()) return;
handle_.swept(stats_, markedCount_);
GCLogDebug(
handle_.getEpoch(),
@@ -423,9 +429,10 @@ GCHandle::GCSweepScope::~GCSweepScope() {
stats_.sweptCount, getStageTime(), stats_.keptCount);
}
GCHandle::GCSweepExtraObjectsScope::GCSweepExtraObjectsScope(kotlin::gc::GCHandle& handle) : handle_(handle) {}
GCHandle::GCSweepExtraObjectsScope::GCSweepExtraObjectsScope(kotlin::gc::GCHandle handle) : GCStageScopeBase(handle) {}
GCHandle::GCSweepExtraObjectsScope::~GCSweepExtraObjectsScope() {
if (!handle_.isValid()) return;
handle_.sweptExtraObjects(stats_);
GCLogDebug(
handle_.getEpoch(),
@@ -434,49 +441,39 @@ GCHandle::GCSweepExtraObjectsScope::~GCSweepExtraObjectsScope() {
stats_.sweptCount, getStageTime(), stats_.keptCount);
}
GCHandle::GCGlobalRootSetScope::GCGlobalRootSetScope(kotlin::gc::GCHandle& handle) : handle_(handle) {}
GCHandle::GCGlobalRootSetScope::GCGlobalRootSetScope(kotlin::gc::GCHandle handle) : GCStageScopeBase(handle) {}
GCHandle::GCGlobalRootSetScope::~GCGlobalRootSetScope(){
if (!handle_.isValid()) return;
handle_.globalRootSetCollected(globalRoots_, stableRoots_);
GCLogDebug(handle_.getEpoch(), "Collected global root set global=%" PRIu64 " stableRef=%" PRIu64 " in %" PRIu64" microseconds.",
globalRoots_, stableRoots_, getStageTime());
GCLogDebug(
handle_.getEpoch(), "Collected global root set global=%" PRIu64 " stableRef=%" PRIu64 " in %" PRIu64 " microseconds.",
globalRoots_, stableRoots_, getStageTime());
}
GCHandle::GCThreadRootSetScope::GCThreadRootSetScope(kotlin::gc::GCHandle& handle, mm::ThreadData& threadData) :
handle_(handle), threadData_(threadData) {}
GCHandle::GCThreadRootSetScope::GCThreadRootSetScope(kotlin::gc::GCHandle handle, mm::ThreadData& threadData) :
GCStageScopeBase(handle), threadData_(threadData) {}
GCHandle::GCThreadRootSetScope::~GCThreadRootSetScope(){
if (!handle_.isValid()) return;
handle_.threadRootSetCollected(threadData_, threadLocalRoots_, stackRoots_);
GCLogDebug(handle_.getEpoch(), "Collected root set for thread #%d: stack=%" PRIu64 " tls=%" PRIu64 " in %" PRIu64" microseconds.",
threadData_.threadId(), stackRoots_, threadLocalRoots_, getStageTime());
GCLogDebug(
handle_.getEpoch(), "Collected root set for thread #%d: stack=%" PRIu64 " tls=%" PRIu64 " in %" PRIu64 " microseconds.",
threadData_.threadId(), stackRoots_, threadLocalRoots_, getStageTime());
}
void GCHandle::GCMarkScope::swap(GCHandle::GCMarkScope& other) noexcept {
std::swap(handle_, other.handle_);
std::swap(startTime_, other.startTime_);
}
GCHandle::GCMarkScope::GCMarkScope(kotlin::gc::GCHandle& handle) : handle_(handle) {}
GCHandle::GCMarkScope::GCMarkScope(GCHandle::GCMarkScope&& that) noexcept {
swap(that);
}
GCHandle::GCMarkScope& GCHandle::GCMarkScope::operator=(GCHandle::GCMarkScope that) noexcept {
swap(that);
return *this;
}
GCHandle::GCMarkScope::GCMarkScope(kotlin::gc::GCHandle handle) : GCStageScopeBase(handle) {}
GCHandle::GCMarkScope::~GCMarkScope() {
if (handle_.isValid()) {
handle_.marked(stats_);
GCLogDebug(handle_.getEpoch(), "Marked %" PRIu64 " objects in %" PRIu64 " microseconds.", stats_.markedCount, getStageTime());
}
if (!handle_.isValid()) return;
handle_.marked(stats_);
GCLogDebug(handle_.getEpoch(), "Marked %" PRIu64 " objects in %" PRIu64 " microseconds.", stats_.markedCount, getStageTime());
}
gc::GCHandle::GCProcessWeaksScope::GCProcessWeaksScope(gc::GCHandle& handle) noexcept : handle_(handle) {}
GCHandle::GCProcessWeaksScope::GCProcessWeaksScope(gc::GCHandle handle) noexcept : GCStageScopeBase(handle) {}
gc::GCHandle::GCProcessWeaksScope::~GCProcessWeaksScope() {
GCHandle::GCProcessWeaksScope::~GCProcessWeaksScope() {
if (!handle_.isValid()) return;
GCLogDebug(
handle_.getEpoch(),
"Processed special refs in %" PRIu64 " microseconds. %" PRIu64 " are undisposed, %" PRIu64 " are alive, %" PRIu64
@@ -37,92 +37,15 @@ struct MarkStats {
class GCHandle {
public:
class GCStageScopeUsTimer {
protected:
uint64_t startTime_ = konan::getTimeMicros();
uint64_t getStageTime() const { return (konan::getTimeMicros() - startTime_); }
};
class GCSweepScope : GCStageScopeUsTimer, Pinned {
GCHandle& handle_;
SweepStats stats_;
uint64_t markedCount_ = 0;
public:
explicit GCSweepScope(GCHandle& handle);
~GCSweepScope();
void addSweptObject() noexcept { stats_.sweptCount += 1; }
void addKeptObject() noexcept { stats_.keptCount += 1; }
// Custom allocator only. To be finalized objects are kept alive.
void addMarkedObject() noexcept { markedCount_ += 1; }
};
class GCSweepExtraObjectsScope : GCStageScopeUsTimer, Pinned {
GCHandle& handle_;
SweepStats stats_;
public:
explicit GCSweepExtraObjectsScope(GCHandle& handle);
~GCSweepExtraObjectsScope();
void addSweptObject() noexcept { stats_.sweptCount += 1; }
void addKeptObject() noexcept { stats_.keptCount += 1; }
};
class GCGlobalRootSetScope : GCStageScopeUsTimer, Pinned {
GCHandle& handle_;
uint64_t globalRoots_ = 0;
uint64_t stableRoots_ = 0;
public:
explicit GCGlobalRootSetScope(GCHandle& handle);
~GCGlobalRootSetScope();
void addGlobalRoot() { globalRoots_++; }
void addStableRoot() { stableRoots_++; }
};
class GCThreadRootSetScope : GCStageScopeUsTimer, Pinned {
GCHandle& handle_;
mm::ThreadData& threadData_;
uint64_t stackRoots_ = 0;
uint64_t threadLocalRoots_ = 0;
public:
explicit GCThreadRootSetScope(GCHandle& handle, mm::ThreadData& threadData);
~GCThreadRootSetScope();
void addStackRoot() { stackRoots_++; }
void addThreadLocalRoot() { threadLocalRoots_++; }
};
class GCStageScopeBase;
class GCSweepScope;
class GCSweepExtraObjectsScope;
class GCGlobalRootSetScope;
class GCThreadRootSetScope;
class GCMarkScope;
class GCProcessWeaksScope;
class GCProcessWeaksScope : GCStageScopeUsTimer, Pinned {
GCHandle& handle_;
uint64_t undisposedCount_ = 0;
uint64_t aliveCount_ = 0;
uint64_t nulledCount_ = 0;
public:
explicit GCProcessWeaksScope(GCHandle& handle) noexcept;
~GCProcessWeaksScope();
void addUndisposed() noexcept { ++undisposedCount_; }
void addAlive() noexcept { ++aliveCount_; }
void addNulled() noexcept { ++nulledCount_; }
};
private:
uint64_t epoch_;
explicit GCHandle(uint64_t epoch) : epoch_(epoch) {}
void threadRootSetCollected(mm::ThreadData& threadData, uint64_t threadLocalReferences, uint64_t stackReferences);
void globalRootSetCollected(uint64_t globalReferences, uint64_t stableReferences);
void swept(SweepStats stats, uint64_t markedCount) noexcept;
void sweptExtraObjects(SweepStats stats) noexcept;
void marked(MarkStats stats);
public:
static GCHandle create(uint64_t epoch);
static GCHandle createFakeForTests();
static GCHandle getByEpoch(uint64_t epoch);
@@ -138,28 +61,134 @@ public:
void suspensionRequested();
void threadsAreSuspended();
void threadsAreResumed();
GCSweepScope sweep() { return GCSweepScope(*this); }
GCSweepExtraObjectsScope sweepExtraObjects() { return GCSweepExtraObjectsScope(*this); }
GCGlobalRootSetScope collectGlobalRoots() { return GCGlobalRootSetScope(*this); }
GCThreadRootSetScope collectThreadRoots(mm::ThreadData& threadData) { return GCThreadRootSetScope(*this, threadData); }
GCMarkScope mark();
GCProcessWeaksScope processWeaks() noexcept { return GCProcessWeaksScope(*this); }
[[nodiscard]] GCSweepScope sweep();
[[nodiscard]] GCSweepExtraObjectsScope sweepExtraObjects();
[[nodiscard]] GCGlobalRootSetScope collectGlobalRoots();
[[nodiscard]] GCThreadRootSetScope collectThreadRoots(mm::ThreadData& threadData);
[[nodiscard]] GCMarkScope mark();
[[nodiscard]] GCProcessWeaksScope processWeaks() noexcept;
MarkStats getMarked();
private:
uint64_t epoch_;
explicit GCHandle(uint64_t epoch) : epoch_(epoch) {}
void threadRootSetCollected(mm::ThreadData& threadData, uint64_t threadLocalReferences, uint64_t stackReferences);
void globalRootSetCollected(uint64_t globalReferences, uint64_t stableReferences);
void swept(SweepStats stats, uint64_t markedCount) noexcept;
void sweptExtraObjects(SweepStats stats) noexcept;
void marked(MarkStats stats);
};
class GCHandle::GCMarkScope : GCStageScopeUsTimer {
GCHandle handle_ = GCHandle::invalid();
MarkStats stats_;
class GCHandle::GCStageScopeBase : private MoveOnly {
public:
explicit GCStageScopeBase(GCHandle gcHandle) : handle_(gcHandle) {}
void swap(GCMarkScope& other) noexcept;
friend void swap(GCStageScopeBase& first, GCStageScopeBase& second) noexcept {
using std::swap;
swap(first.handle_, second.handle_);
swap(first.startTime_, second.startTime_);
}
GCStageScopeBase(GCStageScopeBase&& that) noexcept : GCStageScopeBase(GCHandle::invalid()) {
swap(*this, that);
}
GCStageScopeBase& operator=(GCStageScopeBase&& that) noexcept {
auto tmp = std::move(that);
swap(*this, tmp);
return *this;
}
protected:
uint64_t getStageTime() const { return (konan::getTimeMicros() - startTime_); }
GCHandle handle_;
uint64_t startTime_ = konan::getTimeMicros();
};
class GCHandle::GCSweepScope : GCStageScopeBase {
SweepStats stats_;
uint64_t markedCount_ = 0;
public:
explicit GCMarkScope(GCHandle& handle);
GCMarkScope(GCMarkScope&& that) noexcept;
GCMarkScope& operator=(GCMarkScope that) noexcept;
explicit GCSweepScope(GCHandle handle);
GCSweepScope(GCSweepScope&& that) = default;
GCSweepScope& operator=(GCSweepScope&& that) = default;
~GCSweepScope();
void addSweptObject() noexcept { stats_.sweptCount += 1; }
void addKeptObject() noexcept { stats_.keptCount += 1; }
// Custom allocator only. To be finalized objects are kept alive.
void addMarkedObject() noexcept { markedCount_ += 1; }
};
class GCHandle::GCSweepExtraObjectsScope : private GCStageScopeBase {
SweepStats stats_;
public:
explicit GCSweepExtraObjectsScope(GCHandle handle);
GCSweepExtraObjectsScope(GCSweepExtraObjectsScope&& that) = default;
GCSweepExtraObjectsScope& operator=(GCSweepExtraObjectsScope&& that) = default;
~GCSweepExtraObjectsScope();
void addSweptObject() noexcept { stats_.sweptCount += 1; }
void addKeptObject() noexcept { stats_.keptCount += 1; }
};
class GCHandle::GCGlobalRootSetScope : private GCStageScopeBase {
uint64_t globalRoots_ = 0;
uint64_t stableRoots_ = 0;
public:
explicit GCGlobalRootSetScope(GCHandle handle);
GCGlobalRootSetScope(GCGlobalRootSetScope&& that) = default;
GCGlobalRootSetScope& operator=(GCGlobalRootSetScope&& that) = default;
~GCGlobalRootSetScope();
void addGlobalRoot() { globalRoots_++; }
void addStableRoot() { stableRoots_++; }
};
class GCHandle::GCThreadRootSetScope : private GCStageScopeBase {
mm::ThreadData& threadData_;
uint64_t stackRoots_ = 0;
uint64_t threadLocalRoots_ = 0;
public:
explicit GCThreadRootSetScope(GCHandle handle, mm::ThreadData& threadData);
GCThreadRootSetScope(GCThreadRootSetScope&& that) = default;
GCThreadRootSetScope& operator=(GCThreadRootSetScope&& that) = delete;
~GCThreadRootSetScope();
void addStackRoot() { stackRoots_++; }
void addThreadLocalRoot() { threadLocalRoots_++; }
};
class GCHandle::GCMarkScope : private GCStageScopeBase {
MarkStats stats_;
public:
explicit GCMarkScope(GCHandle handle);
GCMarkScope(GCMarkScope&& that) = default;
GCMarkScope& operator=(GCMarkScope&& that) = default;
~GCMarkScope();
void addObject() noexcept { ++stats_.markedCount; }
};
class GCHandle::GCProcessWeaksScope : private GCStageScopeBase {
uint64_t undisposedCount_ = 0;
uint64_t aliveCount_ = 0;
uint64_t nulledCount_ = 0;
public:
explicit GCProcessWeaksScope(GCHandle handle) noexcept;
GCProcessWeaksScope(GCProcessWeaksScope&& that) = default;
GCProcessWeaksScope& operator=(GCProcessWeaksScope&& that) = default;
~GCProcessWeaksScope();
void addUndisposed() noexcept { ++undisposedCount_; }
void addAlive() noexcept { ++aliveCount_; }
void addNulled() noexcept { ++nulledCount_; }
};
}