对编译器和虚拟机进行重构,以支持闭包和垃圾回收功能

- 去除了不再使用的结构,并更新了编译器以处理新的闭包语义。
- 改进了 Compiler,使其能够生成带有源位置跟踪的指令。
- 在 FunctionObject 和 VM 中引入了作用域变量管理,以支持动态闭包。
- 实现了使用标记-扫描(Mark-And-Sweep) (Tri-Color tracing) 算法的垃圾回收机制,包括对作用域变量的处理。
- 在 VM 中增加了函数加载和作用域变量检索的支持。
- 更新了对象模型,包括引入 InstanceObject 并改进内存管理。
- 添加了用于调试的全局变量打印功能。
This commit is contained in:
2026-03-11 16:53:10 +08:00
parent 0f635ccf2b
commit 51a939ac45
20 changed files with 712 additions and 126 deletions

View File

@@ -150,7 +150,8 @@ namespace Fig
CoreIO::GetStdErr() << std::format(
"Oops! max recursion depth limit {} exceeded in Fn `{}` , exiting...\n",
MAX_RECURSION_DEPTH,
(currentFrame - 1)->proto->name); // pushFrame失败了但currentFrame仍然移动所以 (currentFrame - 1)是 lastFrame
(currentFrame - 1)->proto->name); // pushFrame失败了但currentFrame仍然移动所以
// (currentFrame - 1)是 lastFrame
std::exit(static_cast<int>(MAX_RECURSION_DEPTH));
}
@@ -191,6 +192,40 @@ namespace Fig
do_Call: {
// TODO: FunctionObject 动态解包
std::uint8_t a = decodeA(inst);
std::uint8_t baseReg = decodeB(inst);
Value callee = currentFrame->registerBase[a];
FunctionObject *closure = nullptr;
if (!callee.IsObject())
{
size_t ipIdx = currentFrame->ip - currentFrame->proto->code.data();
return std::unexpected(Error(ErrorType::TypeError,
std::format("Object `{}` is not callable", callee.ToString()),
"none",
*currentFrame->proto->locations[ipIdx]));
}
else
{
Object *obj = callee.AsObject();
if (!obj->isFunction())
{
size_t ipIdx = currentFrame->ip - currentFrame->proto->code.data();
return std::unexpected(Error(ErrorType::TypeError,
std::format("Object `{}` is not callable", callee.ToString()),
"none",
*currentFrame->proto->locations[ipIdx]));
}
closure = static_cast<FunctionObject *>(obj);
}
currentFrame->ip = pushFrame(closure, currentFrame->registerBase + baseReg);
DISPATCH();
}
@@ -198,8 +233,9 @@ namespace Fig
std::uint8_t a = decodeA(inst);
Value retVal = currentFrame->registerBase[a];
// 此时 registerBase[0] 指向的是 Caller 的 baseReg 槽位
closeUpvalues(currentFrame->registerBase);
// 此时 registerBase[0] 指向的是 Caller 的 baseReg 槽位
currentFrame->registerBase[0] = retVal;
popFrame();
@@ -207,6 +243,67 @@ namespace Fig
}
do_LoadFn: {
std::uint8_t a = decodeA(inst);
std::uint16_t bx = decodeBx(inst);
Proto *p = compiledModule->protos[bx];
size_t upValSize = p->upvalues.size();
size_t extraSize = upValSize * sizeof(Upvalue *);
FunctionObject *closure =
(FunctionObject *) allocateObject<FunctionObject>(ObjectType::Function, extraSize);
// CoreIO::GetStdErr() << "DEBUG: p->name = " << p->name << '\n';
new (&closure->name) String(p->name); // String非平凡类型有自己的构造函数
closure->proto = p;
closure->paraCount = p->numParams;
closure->upvalueCount = static_cast<std::uint32_t>(upValSize);
for (size_t i = 0; i < closure->upvalueCount; ++i)
{
auto &info = p->upvalues[i];
if (info.isLocal)
{
Value *targetSlot = &currentFrame->registerBase[info.index];
Upvalue *prev = nullptr;
Upvalue *curr = openUpvalues;
while (curr != nullptr && curr->location > targetSlot)
{
prev = curr;
curr = curr->next;
}
if (curr != nullptr && curr->location == targetSlot)
{
// 如果别的闭包已经捕获了这个槽位,共享物理指针
closure->upvalues[i] = curr;
++curr->refCount;
}
else
{
// 首次捕获
Upvalue *uv = new Upvalue;
uv->location = targetSlot;
uv->next = curr;
++uv->refCount;
if (prev == nullptr)
openUpvalues = uv;
else
prev->next = uv;
closure->upvalues[i] = uv;
}
}
else
{
closure->upvalues[i] = currentFrame->closure->upvalues[info.index];
}
}
currentFrame->registerBase[a] = Value::FromObject(closure);
DISPATCH();
}
@@ -315,12 +412,17 @@ namespace Fig
}
do_GetUpval: {
assert(false && "VM: GetUpval requires FunctionObject (Closure) implementation");
std::uint8_t a = decodeA(inst);
std::uint8_t b = decodeB(inst);
currentFrame->registerBase[a] = *(currentFrame->closure->upvalues[b]->location);
DISPATCH();
}
do_SetUpval: {
assert(false && "VM: SetUpval requires FunctionObject (Closure) implementation");
std::uint8_t a = decodeA(inst);
std::uint8_t b = decodeB(inst);
*(currentFrame->closure->upvalues[b]->location) = currentFrame->registerBase[a]; // copy
DISPATCH();
}