0f635ccf2b
- 更新了类型系统,新增了类型并优化了结构。 - 引入了基类型和派生类,用于函数、结构体和接口类型。 - 实现了类型上下文,用于管理内置类型和类型解析。 - 添加了诊断类,用于收集和报告警告和错误。 - 通过改进错误处理增强了虚拟机执行,以应对递归限制问题。 - 实现了反汇编器,将字节码转换为代码,以改善调试和分析。 - 添加了新的抽象语法树节点,用于成员表达式、对象初始化、接口和结构体定义。 - 引入了语义错误测试,包括重定义、未声明的变量和无效的结构字段。
116 lines
3.5 KiB
C++
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
|