Fixed arena allocator aligned allocation functions
Some checks failed
CMake on multiple platforms / build (Release, cl, cl, windows-latest) (push) Has been cancelled
CMake on multiple platforms / build (Release, clang, clang++, macos-latest) (push) Has been cancelled
CMake on multiple platforms / build (Release, clang, clang++, ubuntu-latest) (push) Has been cancelled
CMake on multiple platforms / build (Release, gcc, g++, ubuntu-latest) (push) Has been cancelled

Moved arena allocator initialization to an explicit init() function to avoid performing this test on each allocation.
This commit is contained in:
2026-08-15 15:10:48 -07:00
parent edc7669a5c
commit 3e2b84411c
2 changed files with 41 additions and 36 deletions

View File

@@ -31,19 +31,26 @@
#pragma once
#include <string>
#include <cstddef>
namespace mimir {
class Arena
{
public:
Arena(size_t minSize = 1ULL << 24, size_t maxSize = 1ULL << 32);
Arena();
~Arena();
bool init(size_t minSize = 1ULL << 24, size_t maxSize = 1ULL << 32);
// Allocate `size` bytes
std::byte* alloc(size_t size);
// Allocate `size` bytes, aligned to 16 bytes and padded to next 16-byte offset.
std::byte* allocA16(size_t size);
// Allocate `size` bytes, aligned to 64 bytes and padded to next 64-byte offset.
std::byte* allocA64(size_t size);
// Reset the arena, potentially also releasing committed pages
void reset();
private:
std::byte* m_data;

View File

@@ -51,24 +51,13 @@
namespace mimir {
struct ArenaControlBlock
{
size_t allocated;
size_t comitted;
size_t next;
};
static_assert(sizeof(ArenaControlBlock) < 4096);
Arena::Arena(size_t minSize, size_t maxSize)
: m_minSize(minSize)
, m_maxSize(maxSize)
Arena::Arena()
: m_minSize(0)
, m_maxSize(0)
, m_data(nullptr)
, m_usedSize(0)
, m_committedSize(0)
{
assert(maxSize >= minSize);
for (size_t i = 0; i < kWatermarkLen; i++) {
m_watermark[i] = 0;
}
@@ -89,27 +78,36 @@ Arena::~Arena()
}
}
std::byte* Arena::alloc(size_t size)
bool Arena::init(size_t minSize, size_t maxSize)
{
size_t neededSize = m_usedSize + size;
assert(maxSize >= minSize);
assert(m_data == nullptr);
assert(m_usedSize == 0);
assert(m_committedSize == 0);
m_minSize = KRAKEN_MEM_ROUND_UP_PAGE(minSize);
m_maxSize = KRAKEN_MEM_ROUND_UP_PAGE(maxSize);
if (m_data == nullptr) {
#if defined(_WIN32) || defined(_WIN64)
m_data = (std::byte*)VirtualAlloc(NULL, KRAKEN_MEM_ROUND_UP_PAGE(m_maxSize), MEM_RESERVE, PAGE_NOACCESS);
if (m_data == nullptr) {
ReportWindowsLastError("VirtualAlloc");
return nullptr;
return false;
}
#elif defined(__unix__) || defined(__APPLE__) || defined(ANDROID)
m_data = (std::byte*)mmap(NULL, KRAKEN_MEM_ROUND_UP_PAGE(m_maxSize), PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (m_data == MAP_FAILED) {
return nullptr;
return false;
}
#else
static_assert(false, "Not Implemented");
#endif
}
return true;
}
std::byte* Arena::alloc(size_t size)
{
size_t neededSize = m_usedSize + size;
if (neededSize > m_committedSize)
{
size_t newSize = std::bit_ceil(neededSize) << 1;
@@ -142,7 +140,7 @@ std::byte* Arena::allocA16(size_t size)
{
uint32_t nextByte = (m_usedSize + 15) & ~15;
uint32_t roundedSize = (size + 15) & ~15;
if (alloc(size) == nullptr) {
if (alloc(roundedSize + nextByte - m_usedSize) == nullptr) {
return nullptr;
}
@@ -153,7 +151,7 @@ std::byte* Arena::allocA64(size_t size)
{
uint32_t nextByte = (m_usedSize + 63) & ~63;
uint32_t roundedSize = (size + 63) & ~63;
if (alloc(size) == nullptr) {
if (alloc(roundedSize + nextByte - m_usedSize) == nullptr) {
return nullptr;
}