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 num_enum::TryFromPrimitive;
use string_interner::Symbol as _; use string_interner::Symbol as _;
use crate::OperandData; use crate::{OperandData, VmRuntimeCtx};
pub(crate) struct BytecodeReader<'a> { pub(crate) struct BytecodeReader<'a> {
bytecode: &'a [u8], bytecode: &'a [u8],
@@ -94,7 +94,7 @@ impl<'a> BytecodeReader<'a> {
} }
#[inline(always)] #[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 tag = self.read_u8();
let Ok(ty) = OperandType::try_from_primitive(tag) let Ok(ty) = OperandType::try_from_primitive(tag)
.map_err(|err| panic!("unknown operand tag: {:#04x}", err.number)); .map_err(|err| panic!("unknown operand tag: {:#04x}", err.number));
@@ -117,10 +117,7 @@ impl<'a> BytecodeReader<'a> {
} }
#[inline(always)] #[inline(always)]
pub(crate) fn read_attr_key_data<C: crate::VmContext>( pub(crate) fn read_attr_key_data<C: VmRuntimeCtx>(&mut self, ctx: &C) -> crate::AttrKeyData {
&mut self,
ctx: &C,
) -> crate::AttrKeyData {
use fix_codegen::AttrKeyType; use fix_codegen::AttrKeyType;
let tag = self.read_u8(); let tag = self.read_u8();
let ty = AttrKeyType::try_from_primitive(tag) let ty = AttrKeyType::try_from_primitive(tag)
+10 -10
View File
@@ -2,7 +2,7 @@
use gc_arena::Mutation; use gc_arena::Mutation;
use crate::{Break, BytecodeReader, Step, Vm, VmContext}; use crate::{Break, BytecodeReader, Step, Vm, VmRuntimeCtx};
pub(crate) enum TailResult { pub(crate) enum TailResult {
YieldFuel(u32), YieldFuel(u32),
@@ -19,9 +19,9 @@ pub(crate) type OpFn<'gc, C> = extern "rust-preserve-none" fn(
u32, u32,
) -> TailResult; ) -> 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>, _vm: &mut Vm<'gc>,
_mc: &Mutation<'gc>, _mc: &Mutation<'gc>,
_ctx: &mut C, _ctx: &mut C,
@@ -50,7 +50,7 @@ macro_rules! tail_dispatch_after {
macro_rules! tail_fn { macro_rules! tail_fn {
($name:ident, ()) => { ($name:ident, ()) => {
extern "rust-preserve-none" fn $name<'gc, C: VmContext>( extern "rust-preserve-none" fn $name<'gc, C: VmRuntimeCtx>(
vm: &mut Vm<'gc>, vm: &mut Vm<'gc>,
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
ctx: &mut C, ctx: &mut C,
@@ -64,7 +64,7 @@ macro_rules! tail_fn {
} }
}; };
($name:ident, (reader)) => { ($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>, vm: &mut Vm<'gc>,
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
ctx: &mut C, ctx: &mut C,
@@ -79,7 +79,7 @@ macro_rules! tail_fn {
} }
}; };
($name:ident, (reader, mc)) => { ($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>, vm: &mut Vm<'gc>,
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
ctx: &mut C, ctx: &mut C,
@@ -94,7 +94,7 @@ macro_rules! tail_fn {
} }
}; };
($name:ident, (ctx, reader, mc)) => { ($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>, vm: &mut Vm<'gc>,
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
ctx: &mut C, ctx: &mut C,
@@ -109,7 +109,7 @@ macro_rules! tail_fn {
} }
}; };
($name:ident, (ctx)) => { ($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>, vm: &mut Vm<'gc>,
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
ctx: &mut C, ctx: &mut C,
@@ -198,7 +198,7 @@ tail_fn!(op_load_scoped_binding, (reader));
macro_rules! table { macro_rules! table {
($($variant:ident => $fn:ident),* $(,)?) => { ($($variant:ident => $fn:ident),* $(,)?) => {
impl<'gc, C: VmContext> DispatchTable<'gc, C> { impl<'gc, C: VmRuntimeCtx> DispatchTable<'gc, C> {
pub(crate) const NEW: Self = { pub(crate) const NEW: Self = {
let mut arr: [OpFn<'gc, C>; 256] = [op_illegal; 256]; let mut arr: [OpFn<'gc, C>; 256] = [op_illegal; 256];
$( arr[fix_codegen::Op::$variant as usize] = $fn; )* $( arr[fix_codegen::Op::$variant as usize] = $fn; )*
@@ -291,7 +291,7 @@ table! {
Illegal => op_illegal, Illegal => op_illegal,
} }
pub(crate) fn run_tailcall<'gc, C: VmContext>( pub(crate) fn run_tailcall<'gc, C: VmRuntimeCtx>(
vm: &mut Vm<'gc>, vm: &mut Vm<'gc>,
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
ctx: &mut C, ctx: &mut C,
+12 -15
View File
@@ -3,13 +3,13 @@ use std::cmp::Ordering;
use gc_arena::{Gc, Mutation}; use gc_arena::{Gc, Mutation};
use crate::value::*; use crate::value::*;
use crate::{BytecodeReader, NixNum, Step, VmContextExt, VmError}; use crate::{BytecodeReader, NixNum, Step, VmError, VmRuntimeCtx, VmRuntimeCtxExt as _};
impl<'gc> crate::Vm<'gc> { impl<'gc> crate::Vm<'gc> {
#[inline(always)] #[inline(always)]
pub(crate) fn op_add( pub(crate) fn op_add(
&mut self, &mut self,
ctx: &mut impl crate::VmContext, ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>, reader: &mut BytecodeReader<'_>,
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
) -> Step { ) -> Step {
@@ -82,7 +82,7 @@ impl<'gc> crate::Vm<'gc> {
#[inline(always)] #[inline(always)]
pub(crate) fn op_eq( pub(crate) fn op_eq(
&mut self, &mut self,
ctx: &mut impl crate::VmContext, ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>, reader: &mut BytecodeReader<'_>,
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
) -> Step { ) -> Step {
@@ -98,7 +98,7 @@ impl<'gc> crate::Vm<'gc> {
#[inline(always)] #[inline(always)]
pub(crate) fn op_neq( pub(crate) fn op_neq(
&mut self, &mut self,
ctx: &mut impl crate::VmContext, ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>, reader: &mut BytecodeReader<'_>,
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
) -> Step { ) -> Step {
@@ -114,7 +114,7 @@ impl<'gc> crate::Vm<'gc> {
#[inline(always)] #[inline(always)]
pub(crate) fn op_lt( pub(crate) fn op_lt(
&mut self, &mut self,
ctx: &mut impl crate::VmContext, ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>, reader: &mut BytecodeReader<'_>,
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
) -> Step { ) -> Step {
@@ -124,7 +124,7 @@ impl<'gc> crate::Vm<'gc> {
#[inline(always)] #[inline(always)]
pub(crate) fn op_gt( pub(crate) fn op_gt(
&mut self, &mut self,
ctx: &mut impl crate::VmContext, ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>, reader: &mut BytecodeReader<'_>,
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
) -> Step { ) -> Step {
@@ -134,7 +134,7 @@ impl<'gc> crate::Vm<'gc> {
#[inline(always)] #[inline(always)]
pub(crate) fn op_leq( pub(crate) fn op_leq(
&mut self, &mut self,
ctx: &mut impl crate::VmContext, ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>, reader: &mut BytecodeReader<'_>,
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
) -> Step { ) -> Step {
@@ -144,7 +144,7 @@ impl<'gc> crate::Vm<'gc> {
#[inline(always)] #[inline(always)]
pub(crate) fn op_geq( pub(crate) fn op_geq(
&mut self, &mut self,
ctx: &mut impl crate::VmContext, ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>, reader: &mut BytecodeReader<'_>,
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
) -> Step { ) -> Step {
@@ -153,7 +153,7 @@ impl<'gc> crate::Vm<'gc> {
fn compare_values( fn compare_values(
&mut self, &mut self,
ctx: &impl crate::VmContext, ctx: &impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>, reader: &mut BytecodeReader<'_>,
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
pred: fn(Ordering) -> bool, pred: fn(Ordering) -> bool,
@@ -202,7 +202,7 @@ impl<'gc> crate::Vm<'gc> {
pub(crate) fn values_equal( pub(crate) fn values_equal(
&mut self, &mut self,
ctx: &impl crate::VmContext, ctx: &impl VmRuntimeCtx,
lhs: StrictValue<'gc>, lhs: StrictValue<'gc>,
rhs: StrictValue<'gc>, rhs: StrictValue<'gc>,
) -> crate::VmResult<bool> { ) -> crate::VmResult<bool> {
@@ -257,7 +257,7 @@ impl<'gc> crate::Vm<'gc> {
fn compare_values_inner( fn compare_values_inner(
&mut self, &mut self,
ctx: &impl crate::VmContext, ctx: &impl VmRuntimeCtx,
pred: fn(Ordering) -> bool, pred: fn(Ordering) -> bool,
lhs: StrictValue<'gc>, lhs: StrictValue<'gc>,
rhs: StrictValue<'gc>, rhs: StrictValue<'gc>,
@@ -276,10 +276,7 @@ impl<'gc> crate::Vm<'gc> {
self.push(Value::new_inline(pred(ord))); self.push(Value::new_inline(pred(ord)));
return Ok(()); return Ok(());
} }
if let (Some(a), Some(b)) = ( if let (Some(a), Some(b)) = (ctx.get_string(lhs), ctx.get_string(rhs)) {
VmContextExt::get_string(ctx, lhs),
VmContextExt::get_string(ctx, rhs),
) {
self.push(Value::new_inline(pred(a.cmp(b)))); self.push(Value::new_inline(pred(a.cmp(b))));
return Ok(()); return Ok(());
} }
+3 -3
View File
@@ -1,7 +1,7 @@
use fix_builtins::BuiltinId; use fix_builtins::BuiltinId;
use num_enum::TryFromPrimitive; use num_enum::TryFromPrimitive;
use crate::{BytecodeReader, PrimOp, Step, Value}; use crate::{BytecodeReader, PrimOp, Step, Value, VmRuntimeCtx};
impl<'gc> crate::Vm<'gc> { impl<'gc> crate::Vm<'gc> {
#[inline(always)] #[inline(always)]
@@ -42,7 +42,7 @@ impl<'gc> crate::Vm<'gc> {
#[inline(always)] #[inline(always)]
pub(crate) fn op_concat_strings( pub(crate) fn op_concat_strings(
&mut self, &mut self,
ctx: &mut impl crate::VmContext, ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>, reader: &mut BytecodeReader<'_>,
_mc: &gc_arena::Mutation<'gc>, _mc: &gc_arena::Mutation<'gc>,
) -> Step { ) -> Step {
@@ -57,7 +57,7 @@ impl<'gc> crate::Vm<'gc> {
} }
#[inline(always)] #[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"); todo!("implement ResolvePath");
} }
} }
+6 -4
View File
@@ -2,13 +2,15 @@ use fix_error::Error;
use gc_arena::{Gc, Mutation, RefLock}; use gc_arena::{Gc, Mutation, RefLock};
use crate::value::*; 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> { impl<'gc> crate::Vm<'gc> {
#[inline(always)] #[inline(always)]
pub(crate) fn op_call( pub(crate) fn op_call(
&mut self, &mut self,
ctx: &mut impl crate::VmContext, ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>, reader: &mut BytecodeReader<'_>,
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
) -> Step { ) -> Step {
@@ -45,14 +47,14 @@ impl<'gc> crate::Vm<'gc> {
#[inline(always)] #[inline(always)]
pub(crate) fn op_return( pub(crate) fn op_return(
&mut self, &mut self,
ctx: &mut impl crate::VmContext, ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>, reader: &mut BytecodeReader<'_>,
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
) -> Step { ) -> Step {
self.handle_return(reader, ctx, mc) self.handle_return(reader, ctx, mc)
} }
pub(crate) fn handle_return<C: crate::VmContext>( pub(crate) fn handle_return<C: VmRuntimeCtx>(
&mut self, &mut self,
reader: &mut BytecodeReader<'_>, reader: &mut BytecodeReader<'_>,
ctx: &C, ctx: &C,
+10 -9
View File
@@ -5,14 +5,15 @@ use smallvec::SmallVec;
use crate::value::NixType; use crate::value::NixType;
use crate::{ 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> { impl<'gc> crate::Vm<'gc> {
#[inline(always)] #[inline(always)]
pub(crate) fn op_make_attrs( pub(crate) fn op_make_attrs(
&mut self, &mut self,
ctx: &mut impl crate::VmContext, ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>, reader: &mut BytecodeReader<'_>,
mc: &gc_arena::Mutation<'gc>, mc: &gc_arena::Mutation<'gc>,
) -> Step { ) -> Step {
@@ -52,7 +53,7 @@ impl<'gc> crate::Vm<'gc> {
#[inline(always)] #[inline(always)]
pub(crate) fn op_select_static( pub(crate) fn op_select_static(
&mut self, &mut self,
ctx: &mut impl crate::VmContext, ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>, reader: &mut BytecodeReader<'_>,
mc: &gc_arena::Mutation<'gc>, mc: &gc_arena::Mutation<'gc>,
) -> Step { ) -> Step {
@@ -73,7 +74,7 @@ impl<'gc> crate::Vm<'gc> {
#[inline(always)] #[inline(always)]
pub(crate) fn op_select_dynamic( pub(crate) fn op_select_dynamic(
&mut self, &mut self,
ctx: &mut impl crate::VmContext, ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>, reader: &mut BytecodeReader<'_>,
mc: &gc_arena::Mutation<'gc>, mc: &gc_arena::Mutation<'gc>,
) -> Step { ) -> Step {
@@ -102,7 +103,7 @@ impl<'gc> crate::Vm<'gc> {
fn select_skip( fn select_skip(
&mut self, &mut self,
key: StringId, key: StringId,
ctx: &mut impl crate::VmContext, ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>, reader: &mut BytecodeReader<'_>,
) -> Step { ) -> Step {
use fix_codegen::Op::*; use fix_codegen::Op::*;
@@ -168,7 +169,7 @@ impl<'gc> crate::Vm<'gc> {
#[inline(always)] #[inline(always)]
pub(crate) fn op_has_attr_path_static( pub(crate) fn op_has_attr_path_static(
&mut self, &mut self,
_ctx: &mut impl crate::VmContext, _ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>, reader: &mut BytecodeReader<'_>,
mc: &gc_arena::Mutation<'gc>, mc: &gc_arena::Mutation<'gc>,
) -> Step { ) -> Step {
@@ -192,7 +193,7 @@ impl<'gc> crate::Vm<'gc> {
#[inline(always)] #[inline(always)]
pub(crate) fn op_has_attr_path_dynamic( pub(crate) fn op_has_attr_path_dynamic(
&mut self, &mut self,
ctx: &mut impl crate::VmContext, ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>, reader: &mut BytecodeReader<'_>,
mc: &gc_arena::Mutation<'gc>, mc: &gc_arena::Mutation<'gc>,
) -> Step { ) -> Step {
@@ -255,7 +256,7 @@ impl<'gc> crate::Vm<'gc> {
#[inline(always)] #[inline(always)]
pub(crate) fn op_has_attr_dynamic( pub(crate) fn op_has_attr_dynamic(
&mut self, &mut self,
ctx: &mut impl crate::VmContext, ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>, reader: &mut BytecodeReader<'_>,
mc: &gc_arena::Mutation<'gc>, mc: &gc_arena::Mutation<'gc>,
) -> Step { ) -> Step {
@@ -288,7 +289,7 @@ impl<'gc> crate::Vm<'gc> {
#[inline(always)] #[inline(always)]
pub(crate) fn op_make_list( pub(crate) fn op_make_list(
&mut self, &mut self,
ctx: &mut impl crate::VmContext, ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>, reader: &mut BytecodeReader<'_>,
mc: &gc_arena::Mutation<'gc>, mc: &gc_arena::Mutation<'gc>,
) -> Step { ) -> Step {
+3 -3
View File
@@ -3,13 +3,13 @@ use fix_error::Error;
use gc_arena::Gc; use gc_arena::Gc;
use crate::value::*; use crate::value::*;
use crate::{BytecodeReader, CallFrame, Step, WithEnv}; use crate::{BytecodeReader, CallFrame, Step, VmRuntimeCtx, WithEnv};
impl<'gc> crate::Vm<'gc> { impl<'gc> crate::Vm<'gc> {
#[inline(always)] #[inline(always)]
pub(crate) fn op_push_with( pub(crate) fn op_push_with(
&mut self, &mut self,
ctx: &mut impl crate::VmContext, ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>, reader: &mut BytecodeReader<'_>,
mc: &gc_arena::Mutation<'gc>, mc: &gc_arena::Mutation<'gc>,
) -> Step { ) -> Step {
@@ -49,7 +49,7 @@ impl<'gc> crate::Vm<'gc> {
#[inline(always)] #[inline(always)]
pub(crate) fn op_lookup_with( pub(crate) fn op_lookup_with(
&mut self, &mut self,
ctx: &mut impl crate::VmContext, ctx: &mut impl VmRuntimeCtx,
reader: &mut BytecodeReader<'_>, reader: &mut BytecodeReader<'_>,
mc: &gc_arena::Mutation<'gc>, mc: &gc_arena::Mutation<'gc>,
) -> Step { ) -> Step {
+27 -16
View File
@@ -64,15 +64,26 @@ pub enum ForceMode {
} }
pub trait VmContext { pub trait VmContext {
fn intern_string(&mut self, s: impl AsRef<str>) -> StringId; fn split(&mut self) -> (&mut impl VmCode, &mut impl VmRuntimeCtx);
fn resolve_string(&self, id: StringId) -> &str;
fn bytecode(&self) -> &[u8];
fn get_const(&self, id: u32) -> StaticValue;
fn compile(&mut self, source: Source);
} }
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<'a, 'gc: 'a>(&'a self, val: StrictValue<'gc>) -> Option<&'a str>;
fn get_string_id<'a, 'gc: 'a>( fn get_string_id<'a, 'gc: 'a>(
&'a mut self, &'a mut self,
@@ -81,7 +92,7 @@ pub(crate) trait VmContextExt: VmContext {
fn convert_value(&self, val: Value) -> fix_common::Value; 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> { fn get_string<'a, 'gc: 'a>(&'a self, val: StrictValue<'gc>) -> Option<&'a str> {
if let Some(sid) = val.as_inline::<StringId>() { if let Some(sid) = val.as_inline::<StringId>() {
Some(self.resolve_string(sid)) Some(self.resolve_string(sid))
@@ -213,7 +224,7 @@ pub(crate) enum AttrKeyData {
Dynamic(OperandData), 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()); let mut entries = SmallVec::with_capacity(BUILTINS.len());
for (idx, &(name, arity)) in BUILTINS.iter().enumerate() { 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> { 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); let builtins = init_builtins(mc, ctx);
Vm { Vm {
stack: Vec::with_capacity(8192), stack: Vec::with_capacity(8192),
@@ -448,15 +459,15 @@ impl Vm<'_> {
ip: InstructionPtr, ip: InstructionPtr,
force_mode: ForceMode, force_mode: ForceMode,
) -> Result<fix_common::Value> { ) -> Result<fix_common::Value> {
let mut arena: Arena<Rootable![Vm<'_>]> = let (code, runtime) = ctx.split();
Arena::new(|mc| Vm::new(force_mode, mc, ctx)); let mut arena: Arena<Rootable![Vm<'_>]> = Arena::new(|mc| Vm::new(force_mode, mc, runtime));
const COLLECTOR_GRANULARITY: f64 = 1024.0; const COLLECTOR_GRANULARITY: f64 = 1024.0;
let mut pc = ip.0; let mut pc = ip.0;
let bytecode: Vec<u8> = ctx.bytecode().to_vec();
loop { 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 } => { Action::Continue { pc: new_pc } => {
pc = new_pc; pc = new_pc;
if arena.metrics().allocation_debt() > COLLECTOR_GRANULARITY { if arena.metrics().allocation_debt() > COLLECTOR_GRANULARITY {
@@ -477,7 +488,7 @@ impl<'gc> Vm<'gc> {
const DEFAULT_FUEL_AMOUNT: u32 = 1024; const DEFAULT_FUEL_AMOUNT: u32 = 1024;
#[inline(always)] #[inline(always)]
fn dispatch_batch<C: VmContext>( fn dispatch_batch<C: VmRuntimeCtx>(
&mut self, &mut self,
bytecode: &[u8], bytecode: &[u8],
ctx: &mut C, ctx: &mut C,
@@ -507,7 +518,7 @@ impl<'gc> Vm<'gc> {
fn execute_batch( fn execute_batch(
&mut self, &mut self,
bytecode: &[u8], bytecode: &[u8],
ctx: &mut impl VmContext, ctx: &mut impl VmRuntimeCtx,
pc: usize, pc: usize,
mc: &Mutation<'gc>, mc: &Mutation<'gc>,
) -> Action { ) -> Action {
+162 -142
View File
@@ -8,33 +8,33 @@ use fix_common::{StringId, Symbol};
use fix_error::{Error, Result, Source}; use fix_error::{Error, Result, Source};
use fix_ir::downgrade::{Downgrade as _, DowngradeContext}; use fix_ir::downgrade::{Downgrade as _, DowngradeContext};
use fix_ir::{Ir, IrRef, MaybeThunk, RawIrRef, ThunkId}; use fix_ir::{Ir, IrRef, MaybeThunk, RawIrRef, ThunkId};
use fix_vm::{ForceMode, StaticValue, Vm, VmContext}; use fix_vm::{ForceMode, StaticValue, Vm, VmCode, VmContext, VmRuntimeCtx};
use ghost_cell::{GhostCell, GhostToken}; use ghost_cell::{GhostCell, GhostToken};
use hashbrown::{HashMap, HashSet}; use hashbrown::{HashMap, HashSet};
use string_interner::{DefaultStringInterner, Symbol as _}; use string_interner::{DefaultStringInterner, Symbol as _};
// mod fetcher;
// mod nar;
// mod nix_utils;
// mod store;
// mod string_context;
mod derivation; mod derivation;
pub mod logging; pub mod logging;
#[global_allocator] #[global_allocator]
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc;
pub struct RuntimeState {
pub strings: DefaultStringInterner,
pub constants: Constants,
}
pub struct CodeState {
pub bytecode: Vec<u8>,
pub sources: Vec<Source>,
pub spans: Vec<(usize, rnix::TextRange)>,
pub thunk_count: usize,
pub global_env: HashMap<StringId, Ir<'static, RawIrRef<'static>>>,
}
pub struct Evaluator { pub struct Evaluator {
bytecode: Vec<u8>, pub runtime: RuntimeState,
constants: Constants, pub code: CodeState,
strings: DefaultStringInterner,
sources: Vec<Source>,
spans: Vec<(usize, rnix::TextRange)>,
// FIXME: remove?
thunk_count: usize,
global_env: HashMap<StringId, Ir<'static, RawIrRef<'static>>>,
} }
impl Default for Evaluator { impl Default for Evaluator {
@@ -48,14 +48,17 @@ impl Evaluator {
let mut strings = DefaultStringInterner::new(); let mut strings = DefaultStringInterner::new();
let global_env = fix_ir::new_global_env(&mut strings); let global_env = fix_ir::new_global_env(&mut strings);
Self { Self {
runtime: RuntimeState {
strings,
constants: Constants::default(),
},
code: CodeState {
sources: Vec::new(), sources: Vec::new(),
spans: Vec::new(), spans: Vec::new(),
strings,
thunk_count: 0, thunk_count: 0,
bytecode: Vec::new(), bytecode: Vec::new(),
constants: Constants::default(),
global_env, global_env,
},
} }
} }
@@ -85,8 +88,13 @@ impl Evaluator {
extra_scope: Option<Scope<'ctx>>, extra_scope: Option<Scope<'ctx>>,
force_mode: ForceMode, force_mode: ForceMode,
) -> Result<fix_common::Value> { ) -> Result<fix_common::Value> {
let root = self.downgrade(source, extra_scope)?; let ip = {
let ip = fix_codegen::compile_bytecode(root.as_ref(), self); let mut compiler = CompilerCtx {
code: &mut self.code,
runtime: &mut self.runtime,
};
compiler.compile_bytecode(source, extra_scope)?
};
Vm::run(self, ip, force_mode) Vm::run(self, ip, force_mode)
} }
@@ -100,55 +108,81 @@ impl Evaluator {
} }
pub fn compile_bytecode(&mut self, source: Source) -> Result<InstructionPtr> { pub fn compile_bytecode(&mut self, source: Source) -> Result<InstructionPtr> {
let root = self.downgrade(source, None)?; let mut compiler = CompilerCtx {
let ip = fix_codegen::compile_bytecode(root.as_ref(), self); code: &mut self.code,
Ok(ip) runtime: &mut self.runtime,
};
compiler.compile_bytecode(source, None)
} }
pub fn disassemble_colored(&self, ip: InstructionPtr) -> String { pub fn disassemble_colored(&self, ip: InstructionPtr) -> String {
Disassembler::new(ip, self).disassemble_colored() Disassembler::new(ip, self).disassemble_colored()
} }
}
fn downgrade_ctx<'a, 'bump, 'id>( impl VmRuntimeCtx for RuntimeState {
&'a mut self, fn intern_string(&mut self, s: impl AsRef<str>) -> StringId {
bump: &'bump Bump, StringId(self.strings.get_or_intern(s))
token: GhostToken<'id>, }
extra_scope: Option<Scope<'a>>, fn resolve_string(&self, id: StringId) -> &str {
) -> DowngradeCtx<'a, 'id, 'bump> { #[allow(clippy::unwrap_used)]
let Self { self.strings.resolve(id.0).unwrap()
global_env, }
sources, fn get_const(&self, id: u32) -> StaticValue {
thunk_count, #[allow(clippy::unwrap_used)]
strings, self.constants.get(id).unwrap()
.. }
} = self; fn add_const(&mut self, val: StaticValue) -> u32 {
DowngradeCtx { self.constants.insert(val)
bump,
token,
strings,
source: sources.last().expect("no current source").clone(),
scopes: [Scope::Global(global_env)]
.into_iter()
.chain(extra_scope)
.collect(),
with_scope_count: 0,
arg_count: 0,
thunk_count,
thunk_scopes: vec![ThunkScope::new_in(bump)],
} }
} }
fn downgrade<'a>( impl VmCode for CodeState {
&'a mut self, fn bytecode(&self) -> &[u8] {
&self.bytecode
}
fn compile(
&mut self,
source: Source, source: Source,
extra_scope: Option<Scope<'a>>, runtime: &mut impl VmRuntimeCtx,
) -> Result<OwnedIr> { ) -> Result<InstructionPtr> {
let mut compiler = CompilerCtx {
code: self,
runtime,
};
compiler.compile_bytecode(source, None)
}
}
impl VmContext for Evaluator {
fn split(&mut self) -> (&mut impl VmCode, &mut impl VmRuntimeCtx) {
(&mut self.code, &mut self.runtime)
}
}
struct CompilerCtx<'a, R: VmRuntimeCtx> {
code: &'a mut CodeState,
runtime: &'a mut R,
}
impl<'a, R: VmRuntimeCtx> CompilerCtx<'a, R> {
fn compile_bytecode(
&mut self,
source: Source,
extra_scope: Option<Scope>,
) -> Result<InstructionPtr> {
let root = self.downgrade(source, extra_scope)?;
let ip = fix_codegen::compile_bytecode(root.as_ref(), self);
Ok(ip)
}
fn downgrade(&mut self, source: Source, extra_scope: Option<Scope>) -> Result<OwnedIr> {
tracing::debug!("Parsing Nix expression"); tracing::debug!("Parsing Nix expression");
self.sources.push(source.clone()); self.code.sources.push(source.clone());
let root = rnix::Root::parse(&source.src); let root = rnix::Root::parse(&source.src);
handle_parse_error(root.errors(), source).map_or(Ok(()), Err)?; handle_parse_error(root.errors(), source.clone()).map_or(Ok(()), Err)?;
tracing::debug!("Downgrading Nix expression"); tracing::debug!("Downgrading Nix expression");
let expr = root let expr = root
@@ -157,38 +191,63 @@ impl Evaluator {
.ok_or_else(|| Error::parse_error("unexpected EOF".into()))?; .ok_or_else(|| Error::parse_error("unexpected EOF".into()))?;
let bump = Bump::new(); let bump = Bump::new();
GhostToken::new(|token| { GhostToken::new(|token| {
let ir = self let downgrade_ctx = DowngradeCtx::new(
.downgrade_ctx(&bump, token, extra_scope) &bump,
.downgrade_toplevel(expr)?; token,
self.runtime,
&self.code.global_env,
extra_scope,
&mut self.code.thunk_count,
source,
);
let ir = downgrade_ctx.downgrade_toplevel(expr)?;
let ir = unsafe { std::mem::transmute::<RawIrRef<'_>, RawIrRef<'static>>(ir) }; let ir = unsafe { std::mem::transmute::<RawIrRef<'_>, RawIrRef<'static>>(ir) };
Ok(OwnedIr { _bump: bump, ir }) Ok(OwnedIr { _bump: bump, ir })
}) })
} }
} }
impl VmContext for Evaluator { impl<'a, R: VmRuntimeCtx> BytecodeContext for CompilerCtx<'a, R> {
fn intern_string(&mut self, s: impl AsRef<str>) -> StringId { fn intern_string(&mut self, s: &str) -> StringId {
StringId(self.strings.get_or_intern(s)) self.runtime.intern_string(s)
}
fn resolve_string(&self, id: StringId) -> &str {
#[allow(clippy::unwrap_used)]
self.strings.resolve(id.0).unwrap()
}
fn bytecode(&self) -> &[u8] {
&self.bytecode
}
fn get_const(&self, id: u32) -> StaticValue {
#[allow(clippy::unwrap_used)]
self.constants.get(id).unwrap()
} }
fn compile(&mut self, _source: Source) { fn register_span(&mut self, range: rnix::TextRange) -> u32 {
todo!(); let id = self.code.spans.len();
let source_id = self
.code
.sources
.len()
.checked_sub(1)
.expect("current_source not set");
self.code.spans.push((source_id, range));
id as u32
}
fn get_code(&self) -> &[u8] {
&self.code.bytecode
}
fn get_code_mut(&mut self) -> &mut Vec<u8> {
&mut self.code.bytecode
}
fn add_constant(&mut self, val: fix_codegen::Const) -> u32 {
use fix_codegen::Const::*;
let val = match val {
Smi(x) => StaticValue::new_inline(x),
Float(x) => StaticValue::new_float(x),
Bool(x) => StaticValue::new_inline(x),
String(x) => StaticValue::new_inline(x),
PrimOp { id, arity } => StaticValue::new_primop(id, arity),
Null => StaticValue::default(),
};
self.runtime.add_const(val)
} }
} }
#[derive(Default)] #[derive(Default)]
struct Constants { pub struct Constants {
data: Vec<StaticValue>, data: Vec<StaticValue>,
dedup: HashMap<u64, u32>, dedup: HashMap<u64, u32>,
} }
@@ -236,10 +295,10 @@ fn handle_parse_error<'a>(
None None
} }
struct DowngradeCtx<'ctx, 'id, 'ir> { struct DowngradeCtx<'ctx, 'id, 'ir, R: VmRuntimeCtx> {
bump: &'ir Bump, bump: &'ir Bump,
token: GhostToken<'id>, token: GhostToken<'id>,
strings: &'ctx mut DefaultStringInterner, runtime: &'ctx mut R,
source: Source, source: Source,
scopes: Vec<Scope<'ctx>>, scopes: Vec<Scope<'ctx>>,
with_scope_count: u32, with_scope_count: u32,
@@ -262,11 +321,11 @@ fn should_thunk<'id>(ir: IrRef<'id, '_>, token: &GhostToken<'id>) -> bool {
) )
} }
impl<'ctx, 'id, 'ir> DowngradeCtx<'ctx, 'id, 'ir> { impl<'ctx, 'id, 'ir, R: VmRuntimeCtx> DowngradeCtx<'ctx, 'id, 'ir, R> {
fn new( fn new(
bump: &'ir Bump, bump: &'ir Bump,
token: GhostToken<'id>, token: GhostToken<'id>,
symbols: &'ctx mut DefaultStringInterner, runtime: &'ctx mut R,
global: &'ctx HashMap<StringId, Ir<'static, RawIrRef<'static>>>, global: &'ctx HashMap<StringId, Ir<'static, RawIrRef<'static>>>,
extra_scope: Option<Scope<'ctx>>, extra_scope: Option<Scope<'ctx>>,
thunk_count: &'ctx mut usize, thunk_count: &'ctx mut usize,
@@ -275,7 +334,7 @@ impl<'ctx, 'id, 'ir> DowngradeCtx<'ctx, 'id, 'ir> {
Self { Self {
bump, bump,
token, token,
strings: symbols, runtime,
source, source,
scopes: std::iter::once(Scope::Global(global)) scopes: std::iter::once(Scope::Global(global))
.chain(extra_scope) .chain(extra_scope)
@@ -288,7 +347,9 @@ impl<'ctx, 'id, 'ir> DowngradeCtx<'ctx, 'id, 'ir> {
} }
} }
impl<'ctx: 'ir, 'id, 'ir> DowngradeContext<'id, 'ir> for DowngradeCtx<'ctx, 'id, 'ir> { impl<'ctx: 'ir, 'id, 'ir, R: VmRuntimeCtx> DowngradeContext<'id, 'ir>
for DowngradeCtx<'ctx, 'id, 'ir, R>
{
fn new_expr(&self, expr: Ir<'ir, IrRef<'id, 'ir>>) -> IrRef<'id, 'ir> { fn new_expr(&self, expr: Ir<'ir, IrRef<'id, 'ir>>) -> IrRef<'id, 'ir> {
IrRef::new(self.bump.alloc(GhostCell::new(expr))) IrRef::new(self.bump.alloc(GhostCell::new(expr)))
} }
@@ -317,11 +378,11 @@ impl<'ctx: 'ir, 'id, 'ir> DowngradeContext<'id, 'ir> for DowngradeCtx<'ctx, 'id,
} }
fn intern_string(&mut self, sym: impl AsRef<str>) -> StringId { fn intern_string(&mut self, sym: impl AsRef<str>) -> StringId {
StringId(self.strings.get_or_intern(sym)) self.runtime.intern_string(sym)
} }
fn resolve_sym(&self, id: StringId) -> Symbol<'_> { fn resolve_sym(&self, id: StringId) -> Symbol<'_> {
self.strings.resolve(id.0).expect("no symbol found").into() self.runtime.resolve_string(id).into()
} }
fn lookup(&self, sym: StringId, span: rnix::TextRange) -> Result<MaybeThunk> { fn lookup(&self, sym: StringId, span: rnix::TextRange) -> Result<MaybeThunk> {
@@ -383,9 +444,9 @@ impl<'ctx: 'ir, 'id, 'ir> DowngradeContext<'id, 'ir> for DowngradeCtx<'ctx, 'id,
self.source.clone() self.source.clone()
} }
fn with_let_scope<F, R>(&mut self, keys: &[StringId], f: F) -> Result<R> fn with_let_scope<F, Ret>(&mut self, keys: &[StringId], f: F) -> Result<Ret>
where where
F: FnOnce(&mut Self) -> Result<(bumpalo::collections::Vec<'ir, IrRef<'id, 'ir>>, R)>, F: FnOnce(&mut Self) -> Result<(bumpalo::collections::Vec<'ir, IrRef<'id, 'ir>>, Ret)>,
{ {
let base = *self.thunk_count; let base = *self.thunk_count;
*self.thunk_count = self *self.thunk_count = self
@@ -407,9 +468,9 @@ impl<'ctx: 'ir, 'id, 'ir> DowngradeContext<'id, 'ir> for DowngradeCtx<'ctx, 'id,
Ok(ret) Ok(ret)
} }
fn with_param_scope<F, R>(&mut self, sym: StringId, f: F) -> R fn with_param_scope<F, Ret>(&mut self, sym: StringId, f: F) -> Ret
where where
F: FnOnce(&mut Self) -> R, F: FnOnce(&mut Self) -> Ret,
{ {
self.scopes.push(Scope::Param { self.scopes.push(Scope::Param {
sym, sym,
@@ -419,9 +480,9 @@ impl<'ctx: 'ir, 'id, 'ir> DowngradeContext<'id, 'ir> for DowngradeCtx<'ctx, 'id,
f(guard.as_ctx()) f(guard.as_ctx())
} }
fn with_with_scope<F, R>(&mut self, f: F) -> R fn with_with_scope<F, Ret>(&mut self, f: F) -> Ret
where where
F: FnOnce(&mut Self) -> R, F: FnOnce(&mut Self) -> Ret,
{ {
self.with_scope_count += 1; self.with_scope_count += 1;
let ret = f(self); let ret = f(self);
@@ -429,15 +490,15 @@ impl<'ctx: 'ir, 'id, 'ir> DowngradeContext<'id, 'ir> for DowngradeCtx<'ctx, 'id,
ret ret
} }
fn with_thunk_scope<F, R>( fn with_thunk_scope<F, Ret>(
&mut self, &mut self,
f: F, f: F,
) -> ( ) -> (
R, Ret,
bumpalo::collections::Vec<'ir, (ThunkId, IrRef<'id, 'ir>)>, bumpalo::collections::Vec<'ir, (ThunkId, IrRef<'id, 'ir>)>,
) )
where where
F: FnOnce(&mut Self) -> R, F: FnOnce(&mut Self) -> Ret,
{ {
self.thunk_scopes.push(ThunkScope::new_in(self.bump)); self.thunk_scopes.push(ThunkScope::new_in(self.bump));
let ret = f(self); let ret = f(self);
@@ -455,7 +516,7 @@ impl<'ctx: 'ir, 'id, 'ir> DowngradeContext<'id, 'ir> for DowngradeCtx<'ctx, 'id,
} }
} }
impl<'id, 'ir, 'ctx: 'ir> DowngradeCtx<'ctx, 'id, 'ir> { impl<'id, 'ir, 'ctx: 'ir, R: VmRuntimeCtx> DowngradeCtx<'ctx, 'id, 'ir, R> {
fn downgrade_toplevel(mut self, root: rnix::ast::Expr) -> Result<RawIrRef<'ir>> { fn downgrade_toplevel(mut self, root: rnix::ast::Expr) -> Result<RawIrRef<'ir>> {
let body = root.downgrade(&mut self)?; let body = root.downgrade(&mut self)?;
let thunks = self let thunks = self
@@ -496,18 +557,18 @@ enum Scope<'ctx> {
Param { sym: StringId, abs_layer: usize }, Param { sym: StringId, abs_layer: usize },
} }
struct ScopeGuard<'a, 'ctx, 'id, 'ir> { struct ScopeGuard<'a, 'ctx, 'id, 'ir, R: VmRuntimeCtx> {
ctx: &'a mut DowngradeCtx<'ctx, 'id, 'ir>, ctx: &'a mut DowngradeCtx<'ctx, 'id, 'ir, R>,
} }
impl Drop for ScopeGuard<'_, '_, '_, '_> { impl<'a, 'ctx, 'id, 'ir, R: VmRuntimeCtx> Drop for ScopeGuard<'a, 'ctx, 'id, 'ir, R> {
fn drop(&mut self) { fn drop(&mut self) {
self.ctx.scopes.pop(); self.ctx.scopes.pop();
} }
} }
impl<'id, 'ir, 'ctx> ScopeGuard<'_, 'ctx, 'id, 'ir> { impl<'a, 'ctx, 'id, 'ir, R: VmRuntimeCtx> ScopeGuard<'a, 'ctx, 'id, 'ir, R> {
fn as_ctx(&mut self) -> &mut DowngradeCtx<'ctx, 'id, 'ir> { fn as_ctx(&mut self) -> &mut DowngradeCtx<'ctx, 'id, 'ir, R> {
self.ctx self.ctx
} }
} }
@@ -518,9 +579,6 @@ struct OwnedIr {
} }
impl OwnedIr { impl OwnedIr {
/// # Safety
///
/// `ir` must be allocated from `bump`.
unsafe fn new(ir: RawIrRef<'_>, bump: Bump) -> Self { unsafe fn new(ir: RawIrRef<'_>, bump: Bump) -> Self {
Self { Self {
_bump: bump, _bump: bump,
@@ -533,52 +591,14 @@ impl OwnedIr {
} }
} }
impl BytecodeContext for Evaluator {
fn intern_string(&mut self, s: &str) -> StringId {
StringId(self.strings.get_or_intern(s))
}
fn register_span(&mut self, range: rnix::TextRange) -> u32 {
let id = self.spans.len();
let source_id = self
.sources
.len()
.checked_sub(1)
.expect("current_source not set");
self.spans.push((source_id, range));
id as u32
}
fn get_code(&self) -> &[u8] {
&self.bytecode
}
fn get_code_mut(&mut self) -> &mut Vec<u8> {
&mut self.bytecode
}
fn add_constant(&mut self, val: fix_codegen::Const) -> u32 {
use fix_codegen::Const::*;
let val = match val {
Smi(x) => StaticValue::new_inline(x),
Float(x) => StaticValue::new_float(x),
Bool(x) => StaticValue::new_inline(x),
String(x) => StaticValue::new_inline(x),
PrimOp { id, arity } => StaticValue::new_primop(id, arity),
Null => StaticValue::default(),
};
self.constants.insert(val)
}
}
impl DisassemblerContext for Evaluator { impl DisassemblerContext for Evaluator {
fn get_code(&self) -> &[u8] { fn get_code(&self) -> &[u8] {
&self.bytecode &self.code.bytecode
} }
#[allow(clippy::unwrap_used)] #[allow(clippy::unwrap_used)]
fn resolve_string(&self, id: u32) -> &str { fn resolve_string(&self, id: u32) -> &str {
let id = string_interner::symbol::SymbolU32::try_from_usize(id as usize).unwrap(); let id = string_interner::symbol::SymbolU32::try_from_usize(id as usize).unwrap();
self.strings.resolve(id).unwrap() self.runtime.strings.resolve(id).unwrap()
} }
} }