refactor vm

This commit is contained in:
2026-04-19 17:23:51 +08:00
parent ca7f7a5ec8
commit e527d31450
14 changed files with 1504 additions and 906 deletions
+153
View File
@@ -0,0 +1,153 @@
use fix_error::Error;
use crate::{
BytecodeReader, CallFrame, Closure, Env, StepResult, ThunkState,
};
use crate::VmContextExt;
use gc_arena::{Gc, Mutation, RefLock};
impl<'gc> crate::Vm<'gc> {
#[inline(always)]
pub(crate) fn op_call(
&mut self,
ctx: &mut impl crate::VmContext,
reader: &mut BytecodeReader<'_>,
mc: &Mutation<'gc>,
) -> StepResult<'gc> {
if let Some(step) = self.try_force_resolved(0, reader.inst_start_pc(), mc) {
return step;
}
if self.call_depth > 10000 {
return StepResult::Done(Err(Error::eval_error(
"stack overflow; max-call-depth exceeded",
)));
}
self.call_depth += 1;
let func = self.pop_stack();
let arg = reader.read_operand_data(ctx).resolve(mc, self);
if let Some(closure) = func.as_gc::<Closure>() {
let ip = closure.ip;
let n_locals = closure.n_locals;
let env = closure.env;
if let Some(ref _pattern) = closure.pattern {
todo!("pattern call")
} else {
let new_env = Gc::new(mc, RefLock::new(Env::with_arg(arg, n_locals, env)));
self.call_stack.push(CallFrame {
pc: reader.pc(),
stack_depth: 0,
thunk: None,
env: self.env,
with_env: self.with_env,
});
reader.set_pc(ip as usize);
self.env = new_env;
}
} else {
todo!("call other types: {func:?}")
}
StepResult::Continue
}
#[inline(always)]
pub(crate) fn op_return(
&mut self,
ctx: &mut impl crate::VmContext,
reader: &mut BytecodeReader<'_>,
mc: &Mutation<'gc>,
) -> StepResult<'gc> {
match self.handle_return(reader, ctx, mc) {
Some(result) => StepResult::Done(result),
None => StepResult::Continue,
}
}
pub(crate) fn handle_return<C: crate::VmContext>(
&mut self,
reader: &mut BytecodeReader<'_>,
ctx: &C,
mc: &Mutation<'gc>,
) -> Option<std::result::Result<fix_common::Value, Box<Error>>> {
let ret_inst_pc = reader.pc() - 1;
let Some(CallFrame {
pc: ret_pc,
stack_depth,
thunk,
env,
with_env,
}) = self.call_stack.pop()
else {
let val = self.pop_stack();
return Some(Ok(ctx.convert_value(val)));
};
reader.set_pc(ret_pc);
if let Some(outer_thunk) = thunk {
let val = self.pop_stack();
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)
{
self.push_stack(val.relax());
}
}
Err(inner_thunk) => {
let mut state = inner_thunk.borrow_mut(mc);
match *state {
ThunkState::Pending {
ip: inner_ip,
env: inner_env,
with_env: inner_with_env,
} => {
self.call_stack.push(CallFrame {
pc: ret_pc,
stack_depth,
thunk: Some(outer_thunk),
env,
with_env,
});
self.call_stack.push(CallFrame {
pc: ret_inst_pc,
stack_depth: 0,
thunk: Some(inner_thunk),
env: inner_env,
with_env: inner_with_env,
});
*state = ThunkState::Blackhole;
reader.set_pc(inner_ip);
self.env = inner_env;
self.with_env = inner_with_env;
return None;
}
ThunkState::Evaluated(val) => {
*outer_thunk.borrow_mut(mc) = ThunkState::Evaluated(val);
if reader
.bytecode()
.get(ret_pc)
.copied()
== Some(fix_codegen::Op::Return as u8)
{
self.push_stack(val.relax());
}
}
ThunkState::Apply { func: _, arg: _ } => todo!("force Apply thunk"),
ThunkState::Blackhole => {
return Some(Err(Error::eval_error(
"infinite recursion encountered",
)));
}
}
}
}
} else {
self.call_depth -= 1;
}
self.env = env;
self.with_env = with_env;
None
}
}