#ifndef MRT_ALLOC_BUFFER_H
#define MRT_ALLOC_BUFFER_H
#include <functional>
#include "Common/MarkWorkStack.h"
#include "RegionList.h"
namespace MapleRuntime {
class AllocBuffer {
public:
AllocBuffer() : tlRawPointerRegions("thread-local raw-pointer regions"),
tlLargeRawPointerRegions("thread-local large raw-pointer regions") {}
~AllocBuffer();
void Init();
void Fini();
static AllocBuffer* GetOrCreateAllocBuffer();
static AllocBuffer* GetAllocBuffer();
MAddress Allocate(size_t size, AllocType allocType);
RegionInfo* GetRegion() { return tlRegion; }
RegionInfo* GetPreparedRegion() { return preparedRegion.load(std::memory_order_relaxed); }
void SetRegion(RegionInfo* newRegion) { tlRegion = newRegion; }
inline void ClearRegion()
{
if (tlRegion == RegionInfo::NullRegion()) {
return;
}
DLOG(REGION, "alloc buffer clear tlRegion %p@[0x%zx, 0x%zx)", tlRegion, tlRegion->GetRegionStart(),
tlRegion->GetRegionEnd());
tlRegion = RegionInfo::NullRegion();
}
bool SetPreparedRegion(RegionInfo* newPreparedRegion)
{
RegionInfo* expect = nullptr;
return preparedRegion.compare_exchange_strong(expect, newPreparedRegion, std::memory_order_release);
}
void CommitRawPointerRegions();
void PushRoot(BaseObject* root) { stackRoots.emplace_back(root); }
template<class WorkStack>
inline void MergeRoots(WorkStack& workStack)
{
if (stackRoots.empty()) {
return;
}
for (BaseObject* obj : stackRoots) {
workStack.push_back(obj);
}
stackRoots.clear();
}
void FlushRegion();
private:
MAddress TryAllocateOnce(size_t totalSize, AllocType allocType);
MAddress AllocateImpl(size_t totalSize, AllocType allocType);
MAddress AllocateRawPointerObject(size_t totalSize);
RegionInfo* tlRegion = RegionInfo::NullRegion();
std::atomic<RegionInfo*> preparedRegion = { nullptr };
RegionList tlRawPointerRegions;
RegionList tlLargeRawPointerRegions;
std::list<BaseObject*> stackRoots;
};
}
#endif