#ifndef MRT_WCOLLECTOR_H
#define MRT_WCOLLECTOR_H
#include <unordered_map>
#include "Allocator/RegionSpace.h"
#include "Collector/CopyCollector.h"
namespace MapleRuntime {
class ForwardTable {
public:
explicit ForwardTable(RegionSpace& space) : theSpace(space) {}
BaseObject* RouteObject(BaseObject* old)
{
BaseObject* toAddress = theSpace.RouteObject(old);
return toAddress;
}
bool RouteRegion(RegionInfo* region) { return theSpace.GetRegionManager().RouteRegion(region); }
void PrepareForwardTable()
{
DLOG(FORWARD, "reset fwd table");
theSpace.PrepareFromSpace();
ForwardDataManager::GetForwardDataManager().ClearPreviousForwardData();
}
RegionSpace& theSpace;
};
using CrossRefHandler = void(*)(BaseObject*, BaseObject*);
class WCollector : public CopyCollector {
public:
explicit WCollector(Allocator& allocator, CollectorResources& resources)
: CopyCollector(allocator, resources), fwdTable(reinterpret_cast<RegionSpace&>(allocator))
{
collectorType = CollectorType::SMOOTH_COLLECTOR;
}
~WCollector() override = default;
void Init() override { ForwardDataManager::GetForwardDataManager().InitializeForwardData(); }
void MarkNewObject(BaseObject* obj) override;
bool ShouldIgnoreRequest(GCRequest& request) override;
bool MarkObject(BaseObject* obj) const override;
bool ResurrectObject(BaseObject* obj, size_t offset, RegionInfo* regionInfo) override;
void EnumRefFieldRoot(RefField<>& ref, RootSet& rootSet) const override;
void TraceRefField(BaseObject* obj, RefField<>& ref, WorkStack& workStack) const;
void TraceObjectRefFields(BaseObject* obj, WorkStack& workStack) override;
BaseObject* GetAndTryTagObj(BaseObject* obj, RefField<>& field) override;
BaseObject* ForwardObject(BaseObject* fromVersion) override;
void PostResolveCycleTask();
void PrepareCycleRef()
{
std::lock_guard<std::mutex> lg(cycleWorkStackMtx);
cycleRefWorkStack.insert(discoveredExternObjects.begin(), discoveredExternObjects.end());
discoveredExternObjects.clear();
}
void MergeResurrectExportObjects()
{
std::lock_guard<std::mutex> lg(resurrectExportMtx);
resurrectedExportObjectes.insert(resurrectedExportObjectesForwardPhase.begin(),
resurrectedExportObjectesForwardPhase.end());
resurrectedExportObjectesForwardPhase.clear();
}
void FlipTagID() { currentTagID ^= 1; }
uint16_t GetCurrentTagID() override { return currentTagID; }
uint16_t GetPreviousTagID() const { return currentTagID ^ 1; }
bool IsOldPointer(RefField<>& ref) const override { return ref.IsTagged() && ref.GetTagID() == GetPreviousTagID(); }
bool IsCurrentPointer(RefField<>& ref) const override { return ref.IsTagged() && ref.GetTagID() == currentTagID; }
void AddRawPointerObject(BaseObject* obj) override
{
RegionSpace& space = reinterpret_cast<RegionSpace&>(theAllocator);
space.AddRawPointerObject(obj);
}
void RemoveRawPointerObject(BaseObject* obj) override
{
RegionSpace& space = reinterpret_cast<RegionSpace&>(theAllocator);
space.RemoveRawPointerObject(obj);
}
void ResolveCycleRef() override;
BaseObject* ForwardUpdateRawRef(ObjectRef& ref);
bool IsFromObject(BaseObject* obj) const override
{
if (Heap::IsHeapAddress(obj)) {
auto regionInfo = RegionInfo::GetRegionInfoAt(reinterpret_cast<uintptr_t>(obj));
return regionInfo->IsFromRegion();
}
return false;
}
bool IsGhostFromObject(BaseObject* obj) const override
{
if (Heap::IsHeapAddress(obj)) {
return RegionInfo::InGhostFromRegion(obj);
}
return false;
}
bool IsUnmovableFromObject(BaseObject* obj) const override;
BaseObject* GetForwardPointer(BaseObject* fromObj, RegionInfo* region)
{
RegionSpace& space = reinterpret_cast<RegionSpace&>(theAllocator);
return space.GetRegionManager().RouteObject(fromObj, region);
}
BaseObject* FindToVersion(BaseObject* obj) const override
{
RegionInfo* fromRegionInfo = RegionInfo::GetGhostFromRegionAt(reinterpret_cast<MAddress>(obj));
if (fromRegionInfo == nullptr) {
return nullptr;
}
RegionSpace& space = reinterpret_cast<RegionSpace&>(theAllocator);
return space.GetRegionManager().RouteObject(obj);
}
protected:
BaseObject* ForwardObjectImpl(BaseObject* obj, RegionInfo* ghostFromRegion);
BaseObject* ForwardObjectExclusive(BaseObject* obj) override;
bool TryUntagRefField(BaseObject* obj, RefField<>& field, BaseObject*& target) const override;
BaseObject* TryForwardObject(BaseObject* fromVersion);
bool TryUpdateRefField(BaseObject* obj, RefField<>& field, BaseObject*& newRef) const override;
bool TryForwardRefField(BaseObject* obj, RefField<>& field, BaseObject*& newRef) const override;
RefField<> GetAndTryTagRefField(BaseObject* target) const override
{
if (IsFromObject(target)) {
return RefField<>(target, 1, currentTagID);
} else {
return RefField<>(target);
}
}
void CollectLargeGarbage()
{
MRT_PHASE_TIMER("Collect large garbage");
RegionSpace& space = reinterpret_cast<RegionSpace&>(theAllocator);
GCStats& stats = GetGCStats();
stats.largeSpaceSize = space.LargeObjectBytes();
stats.largeGarbageSize = space.CollectLargeGarbage();
stats.collectedBytes += stats.largeGarbageSize;
}
void CollectPinnedGarbage()
{
RegionSpace& space = reinterpret_cast<RegionSpace&>(theAllocator);
GCStats& stats = GetGCStats();
stats.pinnedSpaceSize = space.PinnedSpaceSize();
stats.pinnedGarbageSize = space.CollectPinnedGarbage();
stats.collectedBytes += stats.pinnedGarbageSize;
}
void CollectSmallSpace();
void DoGarbageCollection() override;
void ProcessFinalizers() override;
void EnumAndTagRawRoot(ObjectRef& ref, RootSet& rootSet) const override;
private:
template<bool forward>
bool TryUpdateRefFieldImpl(BaseObject* obj, RefField<>& ref, BaseObject*& oldRef, BaseObject*& newRef) const;
void TraceHeap();
void PreforwardConcurrencyModelRoots();
void PostTrace();
void Preforward();
void PreforwardAllExportFromRoots();
void PreforwardFinalizerProcessorRoots();
void PreforwardDiscoveredExternObjects();
void PreforwardAllResurrectExportFromObjects();
CrossRefHandler GetCrossRefHandler(BaseObject* foreignProxy);
ForwardTable fwdTable;
uint16_t currentTagID = 0;
};
}
#endif