* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ECMASCRIPT_MEM_CMS_MEM_SLOT_GC_ALLOCATOR_INL_H
#define ECMASCRIPT_MEM_CMS_MEM_SLOT_GC_ALLOCATOR_INL_H
#include "ecmascript/mem/cms_mem/slot_gc_allocator.h"
#include "ecmascript/mem/cms_mem/slot_allocator-inl.h"
#include "ecmascript/mem/cms_mem/slot_space-inl.h"
namespace panda::ecmascript {
SlotGCAllocator::SlotGCAllocator()
{
InitializeAllocators();
}
SlotGCAllocator::~SlotGCAllocator()
{
for (SlotBumpPointerAllocator *tlab : tlabAllocatorInstances_) {
delete tlab;
}
tlabAllocatorInstances_.clear();
tlabAllocators_.fill(nullptr);
}
void SlotGCAllocator::InitializeAllocators()
{
size_t preSize = 0;
for (size_t i = 0; i < SlotSpaceConfig::NUM_SLOTS; ++i) {
size_t slotSize = SlotSpace::GetSlotSizeByIdx(i);
if (slotSize > preSize) {
SlotBumpPointerAllocator *tlab = new SlotBumpPointerAllocator(slotSize);
tlabAllocatorInstances_.emplace_back(tlab);
}
tlabAllocators_[i] = tlabAllocatorInstances_.back();
ASSERT(tlabAllocators_[i]->GetSlotSize() >= i * SlotSpaceConfig::SLOT_STEP_SIZE);
preSize = slotSize;
}
}
void SlotGCAllocator::Setup(SlotSpace *slotSpace)
{
ASSERT(slotSpace_ == nullptr && slotSpace != nullptr);
slotSpace_ = slotSpace;
}
void SlotGCAllocator::Initialize()
{
for ([[maybe_unused]] SlotBumpPointerAllocator *bpAllocator : tlabAllocatorInstances_) {
ASSERT(bpAllocator->IsEmpty());
}
}
uintptr_t SlotGCAllocator::Allocate(size_t size)
{
size_t idx = SlotSpace::GetSlotIdxBySize(size);
SlotBumpPointerAllocator *tlab = tlabAllocators_[idx];
{
uintptr_t result = tlab->Allocate();
if (LIKELY(result > 0)) {
return result;
}
}
auto [bufferBegin, bufferSize] = slotSpace_->AllocateBufferSyncByIdx(idx);
tlab->Reset(bufferBegin, bufferBegin + bufferSize);
uintptr_t result = tlab->Allocate();
ASSERT(result > 0);
return result;
}
void SlotGCAllocator::Finalize()
{
for (SlotBumpPointerAllocator *tlab : tlabAllocatorInstances_) {
tlab->Finalize();
ASSERT(tlab->IsEmpty());
}
}
SlotGCAllocator::SlotBumpPointerAllocator::SlotBumpPointerAllocator(size_t slotSize) : slotSize_(slotSize)
{
ASSERT(slotSize_ % SlotSpaceConfig::SLOT_STEP_SIZE == 0);
}
void SlotGCAllocator::SlotBumpPointerAllocator::Reset(uintptr_t top, uintptr_t end)
{
ASSERT(IsEmpty());
ASSERT(end - top > 0 && (end - top) % slotSize_ == 0);
top_ = top;
end_ = end;
}
void SlotGCAllocator::SlotBumpPointerAllocator::Finalize()
{
if (top_ < end_) {
size_t left = end_ - top_;
SlotFreeSegment::FillFreeSegment(top_, left);
}
top_ = 0;
end_ = 0;
}
uintptr_t SlotGCAllocator::SlotBumpPointerAllocator::Allocate()
{
if (LIKELY(top_ < end_)) {
uintptr_t result = top_;
top_ += slotSize_;
return result;
}
return 0;
}
bool SlotGCAllocator::SlotBumpPointerAllocator::IsEmpty() const
{
ASSERT(top_ <= end_);
return top_ == end_;
}
size_t SlotGCAllocator::SlotBumpPointerAllocator::GetSlotSize() const
{
return slotSize_;
}
}
#endif