refactor: split VmContext

This commit is contained in:
2026-04-25 17:54:59 +08:00
parent 468269c20d
commit 4f3cd0ef4c
9 changed files with 243 additions and 215 deletions
+3 -6
View File
@@ -3,7 +3,7 @@ use fix_common::StringId;
use num_enum::TryFromPrimitive;
use string_interner::Symbol as _;
use crate::OperandData;
use crate::{OperandData, VmRuntimeCtx};
pub(crate) struct BytecodeReader<'a> {
bytecode: &'a [u8],
@@ -94,7 +94,7 @@ impl<'a> BytecodeReader<'a> {
}
#[inline(always)]
pub(crate) fn read_operand_data<C: crate::VmContext>(&mut self, ctx: &C) -> OperandData {
pub(crate) fn read_operand_data<C: VmRuntimeCtx>(&mut self, ctx: &C) -> OperandData {
let tag = self.read_u8();
let Ok(ty) = OperandType::try_from_primitive(tag)
.map_err(|err| panic!("unknown operand tag: {:#04x}", err.number));
@@ -117,10 +117,7 @@ impl<'a> BytecodeReader<'a> {
}
#[inline(always)]
pub(crate) fn read_attr_key_data<C: crate::VmContext>(
&mut self,
ctx: &C,
) -> crate::AttrKeyData {
pub(crate) fn read_attr_key_data<C: VmRuntimeCtx>(&mut self, ctx: &C) -> crate::AttrKeyData {
use fix_codegen::AttrKeyType;
let tag = self.read_u8();
let ty = AttrKeyType::try_from_primitive(tag)
+10 -10
View File
@@ -2,7 +2,7 @@
use gc_arena::Mutation;
use crate::{Break, BytecodeReader, Step, Vm, VmContext};
use crate::{Break, BytecodeReader, Step, Vm, VmRuntimeCtx};
pub(crate) enum TailResult {
YieldFuel(u32),
@@ -19,9 +19,9 @@ pub(crate) type OpFn<'gc, C> = extern "rust-preserve-none" fn(
u32,
) -> TailResult;
pub(crate) struct DispatchTable<'gc, C: VmContext>(pub(crate) [OpFn<'gc, C>; 256]);
pub(crate) struct DispatchTable<'gc, C: VmRuntimeCtx>(pub(crate) [OpFn<'gc, C>; 256]);
extern "rust-preserve-none" fn op_illegal<'gc, C: VmContext>(
extern "rust-preserve-none" fn op_illegal<'gc, C: VmRuntimeCtx>(
_vm: &mut Vm<'gc>,
_mc: &Mutation<'gc>,
_ctx: &mut C,
@@ -50,7 +50,7 @@ macro_rules! tail_dispatch_after {
macro_rules! tail_fn {
($name:ident, ()) => {
extern "rust-preserve-none" fn $name<'gc, C: VmContext>(
extern "rust-preserve-none" fn $name<'gc, C: VmRuntimeCtx>(
vm: &mut Vm<'gc>,
mc: &Mutation<'gc>,
ctx: &mut C,
@@ -64,7 +64,7 @@ macro_rules! tail_fn {
}
};
($name:ident, (reader)) => {
extern "rust-preserve-none" fn $name<'gc, C: VmContext>(
extern "rust-preserve-none" fn $name<'gc, C: VmRuntimeCtx>(
vm: &mut Vm<'gc>,
mc: &Mutation<'gc>,
ctx: &mut C,
@@ -79,7 +79,7 @@ macro_rules! tail_fn {
}
};
($name:ident, (reader, mc)) => {
extern "rust-preserve-none" fn $name<'gc, C: VmContext>(
extern "rust-preserve-none" fn $name<'gc, C: VmRuntimeCtx>(
vm: &mut Vm<'gc>,
mc: &Mutation<'gc>,
ctx: &mut C,
@@ -94,7 +94,7 @@ macro_rules! tail_fn {
}
};
($name:ident, (ctx, reader, mc)) => {
extern "rust-preserve-none" fn $name<'gc, C: VmContext>(
extern "rust-preserve-none" fn $name<'gc, C: VmRuntimeCtx>(
vm: &mut Vm<'gc>,
mc: &Mutation<'gc>,
ctx: &mut C,
@@ -109,7 +109,7 @@ macro_rules! tail_fn {
}
};
($name:ident, (ctx)) => {
extern "rust-preserve-none" fn $name<'gc, C: VmContext>(
extern "rust-preserve-none" fn $name<'gc, C: VmRuntimeCtx>(
vm: &mut Vm<'gc>,
mc: &Mutation<'gc>,
ctx: &mut C,
@@ -198,7 +198,7 @@ tail_fn!(op_load_scoped_binding, (reader));
macro_rules! table {
($($variant:ident => $fn:ident),* $(,)?) => {
impl<'gc, C: VmContext> DispatchTable<'gc, C> {
impl<'gc, C: VmRuntimeCtx> DispatchTable<'gc, C> {
pub(crate) const NEW: Self = {
let mut arr: [OpFn<'gc, C>; 256] = [op_illegal; 256];
$( arr[fix_codegen::Op::$variant as usize] = $fn; )*
@@ -291,7 +291,7 @@ table! {
Illegal => op_illegal,
}
pub(crate) fn run_tailcall<'gc, C: VmContext>(
pub(crate) fn run_tailcall<'gc, C: VmRuntimeCtx>(
vm: &mut Vm<'gc>,
mc: &Mutation<'gc>,
ctx: &mut C,
+12 -15
View File
@@ -3,13 +3,13 @@ use std::cmp::Ordering;
use gc_arena::{Gc, Mutation};
use crate::value::*;
use crate::{BytecodeReader, NixNum, Step, VmContextExt, VmError};
use crate::{BytecodeReader, NixNum, Step, VmError, VmRuntimeCtx, VmRuntimeCtxExt as _};
impl<'gc> crate::Vm<'gc> {
#[inline(always)]
pub(crate) fn op_add(
&mut self,
ctx: &mut impl crate::VmContext,
ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>,
mc: &Mutation<'gc>,
) -> Step {
@@ -82,7 +82,7 @@ impl<'gc> crate::Vm<'gc> {
#[inline(always)]
pub(crate) fn op_eq(
&mut self,
ctx: &mut impl crate::VmContext,
ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>,
mc: &Mutation<'gc>,
) -> Step {
@@ -98,7 +98,7 @@ impl<'gc> crate::Vm<'gc> {
#[inline(always)]
pub(crate) fn op_neq(
&mut self,
ctx: &mut impl crate::VmContext,
ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>,
mc: &Mutation<'gc>,
) -> Step {
@@ -114,7 +114,7 @@ impl<'gc> crate::Vm<'gc> {
#[inline(always)]
pub(crate) fn op_lt(
&mut self,
ctx: &mut impl crate::VmContext,
ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>,
mc: &Mutation<'gc>,
) -> Step {
@@ -124,7 +124,7 @@ impl<'gc> crate::Vm<'gc> {
#[inline(always)]
pub(crate) fn op_gt(
&mut self,
ctx: &mut impl crate::VmContext,
ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>,
mc: &Mutation<'gc>,
) -> Step {
@@ -134,7 +134,7 @@ impl<'gc> crate::Vm<'gc> {
#[inline(always)]
pub(crate) fn op_leq(
&mut self,
ctx: &mut impl crate::VmContext,
ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>,
mc: &Mutation<'gc>,
) -> Step {
@@ -144,7 +144,7 @@ impl<'gc> crate::Vm<'gc> {
#[inline(always)]
pub(crate) fn op_geq(
&mut self,
ctx: &mut impl crate::VmContext,
ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>,
mc: &Mutation<'gc>,
) -> Step {
@@ -153,7 +153,7 @@ impl<'gc> crate::Vm<'gc> {
fn compare_values(
&mut self,
ctx: &impl crate::VmContext,
ctx: &impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>,
mc: &Mutation<'gc>,
pred: fn(Ordering) -> bool,
@@ -202,7 +202,7 @@ impl<'gc> crate::Vm<'gc> {
pub(crate) fn values_equal(
&mut self,
ctx: &impl crate::VmContext,
ctx: &impl VmRuntimeCtx,
lhs: StrictValue<'gc>,
rhs: StrictValue<'gc>,
) -> crate::VmResult<bool> {
@@ -257,7 +257,7 @@ impl<'gc> crate::Vm<'gc> {
fn compare_values_inner(
&mut self,
ctx: &impl crate::VmContext,
ctx: &impl VmRuntimeCtx,
pred: fn(Ordering) -> bool,
lhs: StrictValue<'gc>,
rhs: StrictValue<'gc>,
@@ -276,10 +276,7 @@ impl<'gc> crate::Vm<'gc> {
self.push(Value::new_inline(pred(ord)));
return Ok(());
}
if let (Some(a), Some(b)) = (
VmContextExt::get_string(ctx, lhs),
VmContextExt::get_string(ctx, rhs),
) {
if let (Some(a), Some(b)) = (ctx.get_string(lhs), ctx.get_string(rhs)) {
self.push(Value::new_inline(pred(a.cmp(b))));
return Ok(());
}
+3 -3
View File
@@ -1,7 +1,7 @@
use fix_builtins::BuiltinId;
use num_enum::TryFromPrimitive;
use crate::{BytecodeReader, PrimOp, Step, Value};
use crate::{BytecodeReader, PrimOp, Step, Value, VmRuntimeCtx};
impl<'gc> crate::Vm<'gc> {
#[inline(always)]
@@ -42,7 +42,7 @@ impl<'gc> crate::Vm<'gc> {
#[inline(always)]
pub(crate) fn op_concat_strings(
&mut self,
ctx: &mut impl crate::VmContext,
ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>,
_mc: &gc_arena::Mutation<'gc>,
) -> Step {
@@ -57,7 +57,7 @@ impl<'gc> crate::Vm<'gc> {
}
#[inline(always)]
pub(crate) fn op_resolve_path(&mut self, _ctx: &mut impl crate::VmContext) -> Step {
pub(crate) fn op_resolve_path(&mut self, _ctx: &mut impl VmRuntimeCtx) -> Step {
todo!("implement ResolvePath");
}
}
+6 -4
View File
@@ -2,13 +2,15 @@ use fix_error::Error;
use gc_arena::{Gc, Mutation, RefLock};
use crate::value::*;
use crate::{BytecodeReader, CallFrame, Closure, Env, Step, ThunkState, VmContextExt};
use crate::{
BytecodeReader, CallFrame, Closure, Env, Step, ThunkState, VmRuntimeCtx, VmRuntimeCtxExt,
};
impl<'gc> crate::Vm<'gc> {
#[inline(always)]
pub(crate) fn op_call(
&mut self,
ctx: &mut impl crate::VmContext,
ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>,
mc: &Mutation<'gc>,
) -> Step {
@@ -45,14 +47,14 @@ impl<'gc> crate::Vm<'gc> {
#[inline(always)]
pub(crate) fn op_return(
&mut self,
ctx: &mut impl crate::VmContext,
ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>,
mc: &Mutation<'gc>,
) -> Step {
self.handle_return(reader, ctx, mc)
}
pub(crate) fn handle_return<C: crate::VmContext>(
pub(crate) fn handle_return<C: VmRuntimeCtx>(
&mut self,
reader: &mut BytecodeReader<'_>,
ctx: &C,
+10 -9
View File
@@ -5,14 +5,15 @@ use smallvec::SmallVec;
use crate::value::NixType;
use crate::{
AttrKeyData, AttrSet, BytecodeReader, List, OperandData, Step, StrictValue, Value, VmContextExt,
AttrKeyData, AttrSet, BytecodeReader, List, OperandData, Step, StrictValue, Value,
VmRuntimeCtx, VmRuntimeCtxExt,
};
impl<'gc> crate::Vm<'gc> {
#[inline(always)]
pub(crate) fn op_make_attrs(
&mut self,
ctx: &mut impl crate::VmContext,
ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>,
mc: &gc_arena::Mutation<'gc>,
) -> Step {
@@ -52,7 +53,7 @@ impl<'gc> crate::Vm<'gc> {
#[inline(always)]
pub(crate) fn op_select_static(
&mut self,
ctx: &mut impl crate::VmContext,
ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>,
mc: &gc_arena::Mutation<'gc>,
) -> Step {
@@ -73,7 +74,7 @@ impl<'gc> crate::Vm<'gc> {
#[inline(always)]
pub(crate) fn op_select_dynamic(
&mut self,
ctx: &mut impl crate::VmContext,
ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>,
mc: &gc_arena::Mutation<'gc>,
) -> Step {
@@ -102,7 +103,7 @@ impl<'gc> crate::Vm<'gc> {
fn select_skip(
&mut self,
key: StringId,
ctx: &mut impl crate::VmContext,
ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>,
) -> Step {
use fix_codegen::Op::*;
@@ -168,7 +169,7 @@ impl<'gc> crate::Vm<'gc> {
#[inline(always)]
pub(crate) fn op_has_attr_path_static(
&mut self,
_ctx: &mut impl crate::VmContext,
_ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>,
mc: &gc_arena::Mutation<'gc>,
) -> Step {
@@ -192,7 +193,7 @@ impl<'gc> crate::Vm<'gc> {
#[inline(always)]
pub(crate) fn op_has_attr_path_dynamic(
&mut self,
ctx: &mut impl crate::VmContext,
ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>,
mc: &gc_arena::Mutation<'gc>,
) -> Step {
@@ -255,7 +256,7 @@ impl<'gc> crate::Vm<'gc> {
#[inline(always)]
pub(crate) fn op_has_attr_dynamic(
&mut self,
ctx: &mut impl crate::VmContext,
ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>,
mc: &gc_arena::Mutation<'gc>,
) -> Step {
@@ -288,7 +289,7 @@ impl<'gc> crate::Vm<'gc> {
#[inline(always)]
pub(crate) fn op_make_list(
&mut self,
ctx: &mut impl crate::VmContext,
ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>,
mc: &gc_arena::Mutation<'gc>,
) -> Step {
+3 -3
View File
@@ -3,13 +3,13 @@ use fix_error::Error;
use gc_arena::Gc;
use crate::value::*;
use crate::{BytecodeReader, CallFrame, Step, WithEnv};
use crate::{BytecodeReader, CallFrame, Step, VmRuntimeCtx, WithEnv};
impl<'gc> crate::Vm<'gc> {
#[inline(always)]
pub(crate) fn op_push_with(
&mut self,
ctx: &mut impl crate::VmContext,
ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>,
mc: &gc_arena::Mutation<'gc>,
) -> Step {
@@ -49,7 +49,7 @@ impl<'gc> crate::Vm<'gc> {
#[inline(always)]
pub(crate) fn op_lookup_with(
&mut self,
ctx: &mut impl crate::VmContext,
ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>,
mc: &gc_arena::Mutation<'gc>,
) -> Step {
+27 -16
View File
@@ -64,15 +64,26 @@ pub enum ForceMode {
}
pub trait VmContext {
fn intern_string(&mut self, s: impl AsRef<str>) -> StringId;
fn resolve_string(&self, id: StringId) -> &str;
fn bytecode(&self) -> &[u8];
fn get_const(&self, id: u32) -> StaticValue;
fn compile(&mut self, source: Source);
fn split(&mut self) -> (&mut impl VmCode, &mut impl VmRuntimeCtx);
}
pub(crate) trait VmContextExt: VmContext {
pub trait VmRuntimeCtx {
fn intern_string(&mut self, s: impl AsRef<str>) -> StringId;
fn resolve_string(&self, id: StringId) -> &str;
fn get_const(&self, id: u32) -> StaticValue;
fn add_const(&mut self, val: StaticValue) -> u32;
}
pub trait VmCode {
fn bytecode(&self) -> &[u8];
fn compile(
&mut self,
source: Source,
ctx: &mut impl VmRuntimeCtx,
) -> fix_error::Result<InstructionPtr>;
}
pub(crate) trait VmRuntimeCtxExt: VmRuntimeCtx {
fn get_string<'a, 'gc: 'a>(&'a self, val: StrictValue<'gc>) -> Option<&'a str>;
fn get_string_id<'a, 'gc: 'a>(
&'a mut self,
@@ -81,7 +92,7 @@ pub(crate) trait VmContextExt: VmContext {
fn convert_value(&self, val: Value) -> fix_common::Value;
}
impl<T: VmContext> VmContextExt for T {
impl<T: VmRuntimeCtx> VmRuntimeCtxExt for T {
fn get_string<'a, 'gc: 'a>(&'a self, val: StrictValue<'gc>) -> Option<&'a str> {
if let Some(sid) = val.as_inline::<StringId>() {
Some(self.resolve_string(sid))
@@ -213,7 +224,7 @@ pub(crate) enum AttrKeyData {
Dynamic(OperandData),
}
fn init_builtins<'gc>(mc: &Mutation<'gc>, ctx: &mut impl VmContext) -> Value<'gc> {
fn init_builtins<'gc>(mc: &Mutation<'gc>, ctx: &mut impl VmRuntimeCtx) -> Value<'gc> {
let mut entries = SmallVec::with_capacity(BUILTINS.len());
for (idx, &(name, arity)) in BUILTINS.iter().enumerate() {
@@ -268,7 +279,7 @@ fn init_builtins<'gc>(mc: &Mutation<'gc>, ctx: &mut impl VmContext) -> Value<'gc
}
impl<'gc> Vm<'gc> {
fn new(force_mode: ForceMode, mc: &Mutation<'gc>, ctx: &mut impl VmContext) -> Self {
fn new(force_mode: ForceMode, mc: &Mutation<'gc>, ctx: &mut impl VmRuntimeCtx) -> Self {
let builtins = init_builtins(mc, ctx);
Vm {
stack: Vec::with_capacity(8192),
@@ -448,15 +459,15 @@ impl Vm<'_> {
ip: InstructionPtr,
force_mode: ForceMode,
) -> Result<fix_common::Value> {
let mut arena: Arena<Rootable![Vm<'_>]> =
Arena::new(|mc| Vm::new(force_mode, mc, ctx));
let (code, runtime) = ctx.split();
let mut arena: Arena<Rootable![Vm<'_>]> = Arena::new(|mc| Vm::new(force_mode, mc, runtime));
const COLLECTOR_GRANULARITY: f64 = 1024.0;
let mut pc = ip.0;
let bytecode: Vec<u8> = ctx.bytecode().to_vec();
loop {
match arena.mutate_root(|mc, root| root.dispatch_batch(&bytecode, ctx, pc, mc)) {
let bytecode = code.bytecode();
match arena.mutate_root(|mc, root| root.dispatch_batch(bytecode, runtime, pc, mc)) {
Action::Continue { pc: new_pc } => {
pc = new_pc;
if arena.metrics().allocation_debt() > COLLECTOR_GRANULARITY {
@@ -477,7 +488,7 @@ impl<'gc> Vm<'gc> {
const DEFAULT_FUEL_AMOUNT: u32 = 1024;
#[inline(always)]
fn dispatch_batch<C: VmContext>(
fn dispatch_batch<C: VmRuntimeCtx>(
&mut self,
bytecode: &[u8],
ctx: &mut C,
@@ -507,7 +518,7 @@ impl<'gc> Vm<'gc> {
fn execute_batch(
&mut self,
bytecode: &[u8],
ctx: &mut impl VmContext,
ctx: &mut impl VmRuntimeCtx,
pc: usize,
mc: &Mutation<'gc>,
) -> Action {