feat: add experimental tailcall vm backend

This commit is contained in:
2026-04-19 22:13:54 +08:00
parent 800249cb1e
commit 98b07f00e4
16 changed files with 501 additions and 111 deletions
+8 -21
View File
@@ -1,11 +1,8 @@
use fix_error::Error;
use crate::{
BytecodeReader, CallFrame, Closure, Env, StepResult, ThunkState,
};
use crate::VmContextExt;
use gc_arena::{Gc, Mutation, RefLock};
use crate::{BytecodeReader, CallFrame, Closure, Env, StepResult, ThunkState, VmContextExt};
impl<'gc> crate::Vm<'gc> {
#[inline(always)]
pub(crate) fn op_call(
@@ -18,9 +15,7 @@ impl<'gc> crate::Vm<'gc> {
return step;
}
if self.call_depth > 10000 {
return self.finish_err(Error::eval_error(
"stack overflow; max-call-depth exceeded",
));
return self.finish_err(Error::eval_error("stack overflow; max-call-depth exceeded"));
}
self.call_depth += 1;
let func = self.pop_stack();
@@ -83,11 +78,7 @@ impl<'gc> crate::Vm<'gc> {
match val.restrict() {
Ok(val) => {
*outer_thunk.borrow_mut(mc) = ThunkState::Evaluated(val);
if reader
.bytecode()
.get(ret_pc)
.copied()
== Some(fix_codegen::Op::Return as u8)
if reader.bytecode().get(ret_pc).copied() == Some(fix_codegen::Op::Return as u8)
{
self.push_stack(val.relax());
}
@@ -122,10 +113,7 @@ impl<'gc> crate::Vm<'gc> {
}
ThunkState::Evaluated(val) => {
*outer_thunk.borrow_mut(mc) = ThunkState::Evaluated(val);
if reader
.bytecode()
.get(ret_pc)
.copied()
if reader.bytecode().get(ret_pc).copied()
== Some(fix_codegen::Op::Return as u8)
{
self.push_stack(val.relax());
@@ -133,9 +121,8 @@ impl<'gc> crate::Vm<'gc> {
}
ThunkState::Apply { func: _, arg: _ } => todo!("force Apply thunk"),
ThunkState::Blackhole => {
return self.finish_err(Error::eval_error(
"infinite recursion encountered",
));
return self
.finish_err(Error::eval_error("infinite recursion encountered"));
}
}
}
@@ -147,4 +134,4 @@ impl<'gc> crate::Vm<'gc> {
self.with_env = with_env;
StepResult::Continue
}
}
}