Files
Fig/src/Utils/Arena.hpp
T
PuqiAR 0f635ccf2b 重构类型系统并改进诊断功能
- 更新了类型系统,新增了类型并优化了结构。
- 引入了基类型和派生类,用于函数、结构体和接口类型。
- 实现了类型上下文,用于管理内置类型和类型解析。
- 添加了诊断类,用于收集和报告警告和错误。
- 通过改进错误处理增强了虚拟机执行,以应对递归限制问题。
- 实现了反汇编器,将字节码转换为代码,以改善调试和分析。
- 添加了新的抽象语法树节点,用于成员表达式、对象初始化、接口和结构体定义。
- 引入了语义错误测试,包括重定义、未声明的变量和无效的结构字段。
2026-03-10 12:33:17 +08:00

116 lines
3.5 KiB
C++

/*!
@file src/Utils/Arena.hpp
@brief 线性分配内存池,支持非平凡析构对象的自动清理
@author PuqiAR (im@puqiar.top)
@date 2026-03-08
*/
#pragma once
#include <cstddef>
#include <vector>
#include <memory>
#include <type_traits>
namespace Fig
{
class Arena
{
private:
struct DestructorNode
{
void (*destructor)(void *);
void *object;
DestructorNode *next;
};
static constexpr std::size_t CHUNK_SIZE = 64 * 1024; // 64KB 块大小
std::vector<char *> chunks;
char *currentPtr = nullptr;
std::size_t remaining = 0;
DestructorNode *destructorHead = nullptr;
public:
Arena() = default;
~Arena()
{
// 逆序调用析构函数
DestructorNode *node = destructorHead;
while (node)
{
node->destructor(node->object);
node = node->next;
}
// 释放所有分配的内存块
for (char *chunk : chunks)
{
delete[] chunk;
}
}
// 禁止拷贝和移动,防止内存所有权混乱
Arena(const Arena &) = delete;
Arena &operator=(const Arena &) = delete;
template <typename T, typename... Args>
T *Allocate(Args &&...args)
{
std::size_t size = sizeof(T);
std::size_t alignment = alignof(T);
// 在当前块中尝试对齐并分配
void *ptr = allocateRaw(size, alignment);
// 在分配的内存上构造对象
T *obj = new (ptr) T(std::forward<Args>(args)...);
// 如果 T 需要析构(如包含 String),注册到销毁链表
if constexpr (!std::is_trivially_destructible_v<T>)
{
// 注意: DestructorNode 本身是 POD,直接在 Arena 里分配,不需要注册析构
void *nodeRaw = allocateRaw(sizeof(DestructorNode), alignof(DestructorNode));
DestructorNode *node = new (nodeRaw) DestructorNode();
node->object = obj;
node->destructor = [](void *p) { static_cast<T *>(p)->~T(); };
node->next = destructorHead;
destructorHead = node;
}
return obj;
}
private:
void *allocateRaw(std::size_t size, std::size_t alignment)
{
// 对齐计算
std::size_t adjustment = 0;
std::size_t currentAddr = reinterpret_cast<std::size_t>(currentPtr);
if (alignment > 0 && (currentAddr % alignment) != 0)
{
adjustment = alignment - (currentAddr % alignment);
}
if (remaining < (size + adjustment))
{
// 当前块空间不足,分配新块
std::size_t nextChunkSize = (size > CHUNK_SIZE) ? size : CHUNK_SIZE;
currentPtr = new char[nextChunkSize];
chunks.push_back(currentPtr);
remaining = nextChunkSize;
adjustment = 0; // 新分配的块通常是最大对齐的
}
currentPtr += adjustment;
void *res = currentPtr;
currentPtr += size;
remaining -= (size + adjustment);
return res;
}
};
} // namespace Fig