ladybird/Libraries/LibGC/WeakBlock.cpp

78 lines
1.9 KiB
C++
Raw Normal View History

/*
* Copyright (c) 2025, Andreas Kling <andreas@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibGC/Cell.h>
#include <LibGC/WeakBlock.h>
#include <sys/mman.h>
#if defined(AK_OS_WINDOWS)
# include <AK/Windows.h>
# include <memoryapi.h>
#endif
namespace GC {
WeakImpl WeakImpl::the_null_weak_impl;
WeakBlock* WeakBlock::create()
{
#if !defined(AK_OS_WINDOWS)
auto* block = (HeapBlock*)mmap(nullptr, WeakBlock::BLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
VERIFY(block != MAP_FAILED);
#else
auto* block = (HeapBlock*)VirtualAlloc(NULL, WeakBlock::BLOCK_SIZE, MEM_COMMIT, PAGE_READWRITE);
VERIFY(block);
#endif
return new (block) WeakBlock;
}
WeakBlock::WeakBlock()
{
for (size_t i = 0; i < IMPL_COUNT; ++i) {
m_impls[i].set_ptr({}, i + 1 < IMPL_COUNT ? &m_impls[i + 1] : nullptr);
m_impls[i].set_state(WeakImpl::State::Freelist);
}
m_freelist = &m_impls[0];
}
WeakBlock::~WeakBlock() = default;
WeakImpl* WeakBlock::allocate(Cell* cell)
{
auto* impl = m_freelist;
if (!impl)
return nullptr;
VERIFY(impl->ref_count() == 0);
m_freelist = impl->ptr() ? static_cast<WeakImpl*>(impl->ptr()) : nullptr;
impl->set_ptr({}, cell);
impl->set_state(WeakImpl::State::Allocated);
return impl;
}
void WeakBlock::deallocate(WeakImpl* impl)
{
VERIFY(impl->ref_count() == 0);
impl->set_ptr({}, m_freelist);
impl->set_state(WeakImpl::State::Freelist);
m_freelist = impl;
}
void WeakBlock::sweep()
{
for (size_t i = 0; i < IMPL_COUNT; ++i) {
auto& impl = m_impls[i];
if (impl.state() == WeakImpl::State::Freelist)
continue;
auto* cell = static_cast<Cell*>(impl.ptr());
if (!cell || !cell->is_marked())
impl.set_ptr({}, nullptr);
if (impl.ref_count() == 0)
deallocate(&impl);
}
}
}