#include "CopyCollector.h"
#include "Allocator/RegionSpace.h"
#include "Common/Runtime.h"
#include "Mutator/MutatorManager.h"
#include "Mutator/SatbBuffer.h"
#include "ObjectModel/RefField.inline.h"
#include "schedule.h"
#if defined(CANGJIE_TSAN_SUPPORT)
#include "Sanitizer/SanitizerInterface.h"
#endif
namespace MapleRuntime {
void CopyCollector::PostGarbageCollection(uint64_t gcIndex)
{
reinterpret_cast<RegionSpace&>(theAllocator).DumpRegionStats("region statistics when gc ends");
TracingCollector::PostGarbageCollection(gcIndex);
MutatorManager::Instance().DestroyExpiredMutators();
}
void CopyCollector::CopyObject(const BaseObject& fromObj, BaseObject& toObj, size_t size) const
{
uintptr_t from = reinterpret_cast<uintptr_t>(&fromObj);
uintptr_t to = reinterpret_cast<uintptr_t>(&toObj);
CHECK_E(memmove_s(reinterpret_cast<void*>(to), size, reinterpret_cast<void*>(from), size) != EOK, "memmove_s fail");
#if defined(CANGJIE_TSAN_SUPPORT)
Sanitizer::TsanFixShadow(reinterpret_cast<void*>(from), reinterpret_cast<void*>(to), size);
#endif
}
void CopyCollector::RunGarbageCollection(uint64_t gcIndex, GCReason reason)
{
ScopedEntryTrace trace("CJRT_GC_START");
ScopedSTWLock stwLock;
gcReason = reason;
PreGarbageCollection(true);
ScheduleTraceEvent(TRACE_EV_GC_START, -1, nullptr, 0);
VLOG(REPORT, "[GC] Start %s %s gcIndex= %lu", GetCollectorName(), g_gcRequests[gcReason].name, gcIndex);
GCStats& gcStats = GetGCStats();
gcStats.collectedBytes = 0;
gcStats.gcStartTime = TimeUtil::NanoSeconds();
DoGarbageCollection();
if (reason == GC_REASON_OOM) {
Heap::GetHeap().GetAllocator().ReclaimGarbageMemory(true);
}
PostGarbageCollection(gcIndex);
gcStats.gcEndTime = TimeUtil::NanoSeconds();
UpdateGCStats();
uint64_t gcTimeNs = gcStats.gcEndTime - gcStats.gcStartTime;
ScheduleTraceEvent(TRACE_EV_GC_DONE, -1, nullptr, 0);
double rate = (static_cast<double>(gcStats.collectedBytes) / gcTimeNs) * (static_cast<double>(NS_PER_S) / MB);
VLOG(REPORT, "total gc time: %s us, collection rate %.3lf MB/s\n", Pretty(gcTimeNs / NS_PER_US).Str(), rate);
g_gcCount++;
g_gcTotalTimeUs += (gcTimeNs / NS_PER_US);
g_gcCollectedTotalBytes += gcStats.collectedBytes;
gcStats.collectionRate = rate;
}
void CopyCollector::ForwardFromSpace()
{
ScopedEntryTrace trace("CJRT_GC_FORWARD");
TransitionToGCPhase(GCPhase::GC_PHASE_FORWARD, true);
RegionSpace& space = reinterpret_cast<RegionSpace&>(theAllocator);
GCStats& stats = GetGCStats();
stats.liveBytesBeforeGC = space.AllocatedBytes();
stats.fromSpaceSize = space.FromSpaceSize();
space.ForwardFromSpace(GetThreadPool());
}
void CopyCollector::RefineFromSpace()
{
GCStats& stats = GetGCStats();
RegionSpace& space = reinterpret_cast<RegionSpace&>(theAllocator);
stats.smallGarbageSize = space.RefineFromSpace();
}
}