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