optimize: remove {StepResult,TailResult}::ForceThunk
This commit is contained in:
+1
-1
@@ -10,4 +10,4 @@ prof.json
|
||||
*.cpuprofile
|
||||
*.cpuprofile.gz
|
||||
*v8.log*
|
||||
callgrind.out.*
|
||||
callgrind.*
|
||||
|
||||
@@ -2,11 +2,10 @@
|
||||
|
||||
use gc_arena::Mutation;
|
||||
|
||||
use crate::{BytecodeReader, ForceInfo, StepResult, Vm, VmContext};
|
||||
use crate::{BytecodeReader, StepResult, Vm, VmContext};
|
||||
|
||||
pub(crate) enum TailResult<'gc> {
|
||||
pub(crate) enum TailResult {
|
||||
YieldFuel(u32),
|
||||
ForceThunk(ForceInfo<'gc>),
|
||||
Done,
|
||||
}
|
||||
|
||||
@@ -18,7 +17,7 @@ pub(crate) type OpFn<'gc, C> = extern "rust-preserve-none" fn(
|
||||
&DispatchTable<'gc, C>,
|
||||
u32,
|
||||
u32,
|
||||
) -> TailResult<'gc>;
|
||||
) -> TailResult;
|
||||
|
||||
pub(crate) struct DispatchTable<'gc, C: VmContext>(pub(crate) [OpFn<'gc, C>; 256]);
|
||||
|
||||
@@ -30,7 +29,7 @@ extern "rust-preserve-none" fn op_illegal<'gc, C: VmContext>(
|
||||
_table: &DispatchTable<'gc, C>,
|
||||
pc: u32,
|
||||
_fuel: u32,
|
||||
) -> TailResult<'gc> {
|
||||
) -> TailResult {
|
||||
panic!("illegal opcode at pc = {pc}");
|
||||
}
|
||||
|
||||
@@ -38,7 +37,6 @@ macro_rules! tail_dispatch_after {
|
||||
($result:expr, $new_pc:expr, $vm:ident, $mc:ident, $ctx:ident, $bc:ident, $table:ident, $fuel:ident) => {{
|
||||
match $result {
|
||||
StepResult::Continue => {}
|
||||
StepResult::ForceThunk(info) => return TailResult::ForceThunk(info),
|
||||
StepResult::Done => return TailResult::Done,
|
||||
}
|
||||
let new_pc: u32 = $new_pc;
|
||||
@@ -60,7 +58,7 @@ macro_rules! tail_fn {
|
||||
table: &DispatchTable<'gc, C>,
|
||||
pc: u32,
|
||||
fuel: u32,
|
||||
) -> TailResult<'gc> {
|
||||
) -> TailResult {
|
||||
let result = vm.$name();
|
||||
tail_dispatch_after!(result, pc + 1, vm, mc, ctx, bc, table, fuel)
|
||||
}
|
||||
@@ -74,7 +72,7 @@ macro_rules! tail_fn {
|
||||
table: &DispatchTable<'gc, C>,
|
||||
pc: u32,
|
||||
fuel: u32,
|
||||
) -> TailResult<'gc> {
|
||||
) -> TailResult {
|
||||
let mut reader = BytecodeReader::from_after_op(bc, pc as usize);
|
||||
let result = vm.$name(&mut reader);
|
||||
tail_dispatch_after!(result, reader.pc() as u32, vm, mc, ctx, bc, table, fuel)
|
||||
@@ -89,7 +87,7 @@ macro_rules! tail_fn {
|
||||
table: &DispatchTable<'gc, C>,
|
||||
pc: u32,
|
||||
fuel: u32,
|
||||
) -> TailResult<'gc> {
|
||||
) -> TailResult {
|
||||
let mut reader = BytecodeReader::from_after_op(bc, pc as usize);
|
||||
let result = vm.$name(&mut reader, mc);
|
||||
tail_dispatch_after!(result, reader.pc() as u32, vm, mc, ctx, bc, table, fuel)
|
||||
@@ -104,26 +102,12 @@ macro_rules! tail_fn {
|
||||
table: &DispatchTable<'gc, C>,
|
||||
pc: u32,
|
||||
fuel: u32,
|
||||
) -> TailResult<'gc> {
|
||||
) -> TailResult {
|
||||
let mut reader = BytecodeReader::from_after_op(bc, pc as usize);
|
||||
let result = vm.$name(ctx, &mut reader, mc);
|
||||
tail_dispatch_after!(result, reader.pc() as u32, vm, mc, ctx, bc, table, fuel)
|
||||
}
|
||||
};
|
||||
($name:ident, (mc, inst_start_pc)) => {
|
||||
extern "rust-preserve-none" fn $name<'gc, C: VmContext>(
|
||||
vm: &mut Vm<'gc>,
|
||||
mc: &Mutation<'gc>,
|
||||
ctx: &mut C,
|
||||
bc: &[u8],
|
||||
table: &DispatchTable<'gc, C>,
|
||||
pc: u32,
|
||||
fuel: u32,
|
||||
) -> TailResult<'gc> {
|
||||
let result = vm.$name(mc, pc as usize);
|
||||
tail_dispatch_after!(result, pc + 1, vm, mc, ctx, bc, table, fuel)
|
||||
}
|
||||
};
|
||||
($name:ident, (ctx)) => {
|
||||
extern "rust-preserve-none" fn $name<'gc, C: VmContext>(
|
||||
vm: &mut Vm<'gc>,
|
||||
@@ -133,7 +117,7 @@ macro_rules! tail_fn {
|
||||
table: &DispatchTable<'gc, C>,
|
||||
pc: u32,
|
||||
fuel: u32,
|
||||
) -> TailResult<'gc> {
|
||||
) -> TailResult {
|
||||
let result = vm.$name(ctx);
|
||||
tail_dispatch_after!(result, pc + 1, vm, mc, ctx, bc, table, fuel)
|
||||
}
|
||||
@@ -181,7 +165,7 @@ tail_fn!(op_gt, (ctx, reader, mc));
|
||||
tail_fn!(op_leq, (ctx, reader, mc));
|
||||
tail_fn!(op_geq, (ctx, reader, mc));
|
||||
tail_fn!(op_concat, (reader, mc));
|
||||
tail_fn!(op_update, (mc, inst_start_pc));
|
||||
tail_fn!(op_update, (reader, mc));
|
||||
|
||||
tail_fn!(op_neg, ());
|
||||
tail_fn!(op_not, ());
|
||||
@@ -303,7 +287,7 @@ pub(crate) fn run_tailcall<'gc, C: VmContext>(
|
||||
ctx: &mut C,
|
||||
bc: &[u8],
|
||||
pc: u32,
|
||||
) -> TailResult<'gc> {
|
||||
) -> TailResult {
|
||||
const FUEL: u32 = 1024;
|
||||
let table = &DispatchTable::<'gc, C>::NEW;
|
||||
let op = bc[pc as usize] as usize;
|
||||
|
||||
@@ -11,11 +11,11 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &mut impl crate::VmContext,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult<'gc> {
|
||||
if let Some(step) = self.try_force_resolved(1, reader.inst_start_pc(), mc) {
|
||||
) -> StepResult {
|
||||
if let Some(step) = self.try_force(1, reader, mc) {
|
||||
return step;
|
||||
}
|
||||
if let Some(step) = self.try_force_resolved(0, reader.inst_start_pc(), mc) {
|
||||
if let Some(step) = self.try_force(0, reader, mc) {
|
||||
return step;
|
||||
}
|
||||
let rhs = self.pop_stack_forced();
|
||||
@@ -43,8 +43,8 @@ impl<'gc> crate::Vm<'gc> {
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult<'gc> {
|
||||
self.op_arith(mc, i64::wrapping_sub, |a, b| a - b, reader.inst_start_pc())
|
||||
) -> StepResult {
|
||||
self.op_arith(reader, mc, i64::wrapping_sub, |a, b| a - b)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -52,22 +52,22 @@ impl<'gc> crate::Vm<'gc> {
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult<'gc> {
|
||||
self.op_arith(mc, i64::wrapping_mul, |a, b| a * b, reader.inst_start_pc())
|
||||
) -> StepResult {
|
||||
self.op_arith(reader, mc, i64::wrapping_mul, |a, b| a * b)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn op_arith(
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
int_op: fn(i64, i64) -> i64,
|
||||
float_op: fn(f64, f64) -> f64,
|
||||
inst_start_pc: usize,
|
||||
) -> StepResult<'gc> {
|
||||
if let Some(step) = self.try_force_resolved(1, inst_start_pc, mc) {
|
||||
) -> StepResult {
|
||||
if let Some(step) = self.try_force(1, reader, mc) {
|
||||
return step;
|
||||
}
|
||||
if let Some(step) = self.try_force_resolved(0, inst_start_pc, mc) {
|
||||
if let Some(step) = self.try_force(0, reader, mc) {
|
||||
return step;
|
||||
}
|
||||
let rhs = self.pop_stack_forced();
|
||||
@@ -87,11 +87,11 @@ impl<'gc> crate::Vm<'gc> {
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult<'gc> {
|
||||
if let Some(step) = self.try_force_resolved(1, reader.inst_start_pc(), mc) {
|
||||
) -> StepResult {
|
||||
if let Some(step) = self.try_force(1, reader, mc) {
|
||||
return step;
|
||||
}
|
||||
if let Some(step) = self.try_force_resolved(0, reader.inst_start_pc(), mc) {
|
||||
if let Some(step) = self.try_force(0, reader, mc) {
|
||||
return step;
|
||||
}
|
||||
let rhs = self.pop_stack_forced();
|
||||
@@ -120,11 +120,11 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &mut impl crate::VmContext,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult<'gc> {
|
||||
if let Some(step) = self.try_force_resolved(1, reader.inst_start_pc(), mc) {
|
||||
) -> StepResult {
|
||||
if let Some(step) = self.try_force(1, reader, mc) {
|
||||
return step;
|
||||
}
|
||||
if let Some(step) = self.try_force_resolved(0, reader.inst_start_pc(), mc) {
|
||||
if let Some(step) = self.try_force(0, reader, mc) {
|
||||
return step;
|
||||
}
|
||||
let eq = match self.values_equal(ctx) {
|
||||
@@ -141,11 +141,11 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &mut impl crate::VmContext,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult<'gc> {
|
||||
if let Some(step) = self.try_force_resolved(1, reader.inst_start_pc(), mc) {
|
||||
) -> StepResult {
|
||||
if let Some(step) = self.try_force(1, reader, mc) {
|
||||
return step;
|
||||
}
|
||||
if let Some(step) = self.try_force_resolved(0, reader.inst_start_pc(), mc) {
|
||||
if let Some(step) = self.try_force(0, reader, mc) {
|
||||
return step;
|
||||
}
|
||||
let eq = match self.values_equal(ctx) {
|
||||
@@ -162,7 +162,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &mut impl crate::VmContext,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult<'gc> {
|
||||
) -> StepResult {
|
||||
self.compare_values(ctx, reader, mc, Ordering::is_lt)
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &mut impl crate::VmContext,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult<'gc> {
|
||||
) -> StepResult {
|
||||
self.compare_values(ctx, reader, mc, Ordering::is_gt)
|
||||
}
|
||||
|
||||
@@ -182,7 +182,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &mut impl crate::VmContext,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult<'gc> {
|
||||
) -> StepResult {
|
||||
self.compare_values(ctx, reader, mc, Ordering::is_le)
|
||||
}
|
||||
|
||||
@@ -192,7 +192,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &mut impl crate::VmContext,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult<'gc> {
|
||||
) -> StepResult {
|
||||
self.compare_values(ctx, reader, mc, Ordering::is_ge)
|
||||
}
|
||||
|
||||
@@ -202,11 +202,11 @@ impl<'gc> crate::Vm<'gc> {
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
pred: fn(Ordering) -> bool,
|
||||
) -> StepResult<'gc> {
|
||||
if let Some(step) = self.try_force_resolved(1, reader.inst_start_pc(), mc) {
|
||||
) -> StepResult {
|
||||
if let Some(step) = self.try_force(1, reader, mc) {
|
||||
return step;
|
||||
}
|
||||
if let Some(step) = self.try_force_resolved(0, reader.inst_start_pc(), mc) {
|
||||
if let Some(step) = self.try_force(0, reader, mc) {
|
||||
return step;
|
||||
}
|
||||
match self.compare_values_inner(ctx, pred) {
|
||||
@@ -220,11 +220,11 @@ impl<'gc> crate::Vm<'gc> {
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult<'gc> {
|
||||
if let Some(step) = self.try_force_resolved(1, reader.inst_start_pc(), mc) {
|
||||
) -> StepResult {
|
||||
if let Some(step) = self.try_force(1, reader, mc) {
|
||||
return step;
|
||||
}
|
||||
if let Some(step) = self.try_force_resolved(0, reader.inst_start_pc(), mc) {
|
||||
if let Some(step) = self.try_force(0, reader, mc) {
|
||||
return step;
|
||||
}
|
||||
let rhs = self.pop_stack_forced();
|
||||
@@ -249,13 +249,13 @@ impl<'gc> crate::Vm<'gc> {
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_update(
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
inst_start_pc: usize,
|
||||
) -> StepResult<'gc> {
|
||||
if let Some(step) = self.try_force_resolved(1, inst_start_pc, mc) {
|
||||
) -> StepResult {
|
||||
if let Some(step) = self.try_force(1, reader, mc) {
|
||||
return step;
|
||||
}
|
||||
if let Some(step) = self.try_force_resolved(0, inst_start_pc, mc) {
|
||||
if let Some(step) = self.try_force(0, reader, mc) {
|
||||
return step;
|
||||
}
|
||||
let rhs = self.pop_stack_forced();
|
||||
@@ -275,12 +275,12 @@ impl<'gc> crate::Vm<'gc> {
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_neg(&mut self) -> StepResult<'gc> {
|
||||
pub(crate) fn op_neg(&mut self) -> StepResult {
|
||||
todo!("implement unary operation");
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_not(&mut self) -> StepResult<'gc> {
|
||||
pub(crate) fn op_not(&mut self) -> StepResult {
|
||||
todo!("implement unary operation");
|
||||
}
|
||||
|
||||
|
||||
@@ -5,13 +5,13 @@ use crate::{BytecodeReader, PrimOp, StepResult, Value};
|
||||
|
||||
impl<'gc> crate::Vm<'gc> {
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_load_builtins(&mut self) -> StepResult<'gc> {
|
||||
pub(crate) fn op_load_builtins(&mut self) -> StepResult {
|
||||
self.push_stack(self.builtins);
|
||||
StepResult::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_load_builtin(&mut self, reader: &mut BytecodeReader<'_>) -> StepResult<'gc> {
|
||||
pub(crate) fn op_load_builtin(&mut self, reader: &mut BytecodeReader<'_>) -> StepResult {
|
||||
let Ok(id) = BuiltinId::try_from_primitive(reader.read_u8())
|
||||
.map_err(|err| panic!("unknown builtin id: {}", err.number));
|
||||
self.push_stack(Value::new_inline(PrimOp {
|
||||
@@ -22,7 +22,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_mk_pos(&mut self, reader: &mut BytecodeReader<'_>) -> StepResult<'gc> {
|
||||
pub(crate) fn op_mk_pos(&mut self, reader: &mut BytecodeReader<'_>) -> StepResult {
|
||||
let _span_id = reader.read_u32();
|
||||
todo!("MkPos");
|
||||
}
|
||||
@@ -31,7 +31,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
pub(crate) fn op_load_repl_binding(
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
) -> StepResult<'gc> {
|
||||
) -> StepResult {
|
||||
let _name = reader.read_string_id();
|
||||
todo!("LoadReplBinding");
|
||||
}
|
||||
@@ -40,7 +40,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
pub(crate) fn op_load_scoped_binding(
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
) -> StepResult<'gc> {
|
||||
) -> StepResult {
|
||||
let _name = reader.read_string_id();
|
||||
todo!("LoadScopedBinding");
|
||||
}
|
||||
@@ -51,7 +51,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &mut impl crate::VmContext,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
_mc: &gc_arena::Mutation<'gc>,
|
||||
) -> StepResult<'gc> {
|
||||
) -> StepResult {
|
||||
let _parts_count = reader.read_u16() as usize;
|
||||
let _force_string = reader.read_u8() != 0;
|
||||
let mut _operands: smallvec::SmallVec<[crate::OperandData; 4]> =
|
||||
@@ -63,7 +63,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_resolve_path(&mut self, _ctx: &mut impl crate::VmContext) -> StepResult<'gc> {
|
||||
pub(crate) fn op_resolve_path(&mut self, _ctx: &mut impl crate::VmContext) -> StepResult {
|
||||
todo!("implement ResolvePath");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@ impl<'gc> crate::Vm<'gc> {
|
||||
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) {
|
||||
) -> StepResult {
|
||||
if let Some(step) = self.try_force(0, reader, mc) {
|
||||
return step;
|
||||
}
|
||||
if self.call_depth > 10000 {
|
||||
@@ -50,7 +50,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &mut impl crate::VmContext,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult<'gc> {
|
||||
) -> StepResult {
|
||||
self.handle_return(reader, ctx, mc)
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
ctx: &C,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult<'gc> {
|
||||
) -> StepResult {
|
||||
let ret_inst_pc = reader.pc() - 1;
|
||||
let Some(CallFrame {
|
||||
pc: ret_pc,
|
||||
|
||||
@@ -8,7 +8,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult<'gc> {
|
||||
) -> StepResult {
|
||||
let entry_point = reader.read_u32();
|
||||
let thunk = Gc::new(
|
||||
mc,
|
||||
@@ -27,7 +27,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult<'gc> {
|
||||
) -> StepResult {
|
||||
let entry_point = reader.read_u32();
|
||||
let n_locals = reader.read_u32();
|
||||
let closure = Gc::new(
|
||||
@@ -48,7 +48,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult<'gc> {
|
||||
) -> StepResult {
|
||||
let entry_point = reader.read_u32();
|
||||
let n_locals = reader.read_u32();
|
||||
let req_count = reader.read_u16() as usize;
|
||||
|
||||
@@ -13,7 +13,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &mut impl crate::VmContext,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &gc_arena::Mutation<'gc>,
|
||||
) -> StepResult<'gc> {
|
||||
) -> StepResult {
|
||||
let count = reader.read_u32() as usize;
|
||||
let mut entries: SmallVec<[AttrEntry; 4]> = SmallVec::with_capacity(count);
|
||||
for _ in 0..count {
|
||||
@@ -42,7 +42,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_make_empty_attrs(&mut self) -> StepResult<'gc> {
|
||||
pub(crate) fn op_make_empty_attrs(&mut self) -> StepResult {
|
||||
self.push_stack(self.empty_attrs);
|
||||
StepResult::Continue
|
||||
}
|
||||
@@ -53,11 +53,11 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &mut impl crate::VmContext,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &gc_arena::Mutation<'gc>,
|
||||
) -> StepResult<'gc> {
|
||||
) -> StepResult {
|
||||
let _span_id = reader.read_u32();
|
||||
let key = reader.read_string_id();
|
||||
|
||||
if let Some(step) = self.try_force_resolved(0, reader.inst_start_pc(), mc) {
|
||||
if let Some(step) = self.try_force(0, reader, mc) {
|
||||
return step;
|
||||
}
|
||||
|
||||
@@ -98,13 +98,13 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &mut impl crate::VmContext,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &gc_arena::Mutation<'gc>,
|
||||
) -> StepResult<'gc> {
|
||||
) -> StepResult {
|
||||
let _span_id = reader.read_u32();
|
||||
|
||||
if let Some(step) = self.try_force_resolved(0, reader.inst_start_pc(), mc) {
|
||||
if let Some(step) = self.try_force(0, reader, mc) {
|
||||
return step;
|
||||
}
|
||||
if let Some(step) = self.try_force_resolved(1, reader.inst_start_pc(), mc) {
|
||||
if let Some(step) = self.try_force(1, reader, mc) {
|
||||
return step;
|
||||
}
|
||||
|
||||
@@ -143,14 +143,14 @@ impl<'gc> crate::Vm<'gc> {
|
||||
pub(crate) fn op_jump_if_select_succeeded(
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
) -> StepResult<'gc> {
|
||||
) -> StepResult {
|
||||
let offset = reader.read_i32();
|
||||
reader.set_pc(((reader.pc() as isize) + (offset as isize)) as usize);
|
||||
StepResult::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_has_attr(&mut self, reader: &mut BytecodeReader<'_>) -> StepResult<'gc> {
|
||||
pub(crate) fn op_has_attr(&mut self, reader: &mut BytecodeReader<'_>) -> StepResult {
|
||||
let _n = reader.read_u16() as usize;
|
||||
todo!("HasAttr");
|
||||
}
|
||||
@@ -161,7 +161,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &mut impl crate::VmContext,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &gc_arena::Mutation<'gc>,
|
||||
) -> StepResult<'gc> {
|
||||
) -> StepResult {
|
||||
let count = reader.read_u32() as usize;
|
||||
let mut items: SmallVec<[Value; 4]> = SmallVec::with_capacity(count);
|
||||
for _ in 0..count {
|
||||
@@ -173,7 +173,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_make_empty_list(&mut self) -> StepResult<'gc> {
|
||||
pub(crate) fn op_make_empty_list(&mut self) -> StepResult {
|
||||
self.push_stack(self.empty_list);
|
||||
StepResult::Continue
|
||||
}
|
||||
|
||||
@@ -6,9 +6,9 @@ impl<'gc> crate::Vm<'gc> {
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &gc_arena::Mutation<'gc>,
|
||||
) -> StepResult<'gc> {
|
||||
) -> StepResult {
|
||||
let offset = reader.read_i32();
|
||||
if let Some(step) = self.try_force_resolved(0, reader.inst_start_pc(), mc) {
|
||||
if let Some(step) = self.try_force(0, reader, mc) {
|
||||
return step;
|
||||
}
|
||||
let cond = self.pop_stack();
|
||||
@@ -23,9 +23,9 @@ impl<'gc> crate::Vm<'gc> {
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &gc_arena::Mutation<'gc>,
|
||||
) -> StepResult<'gc> {
|
||||
) -> StepResult {
|
||||
let offset = reader.read_i32();
|
||||
if let Some(step) = self.try_force_resolved(0, reader.inst_start_pc(), mc) {
|
||||
if let Some(step) = self.try_force(0, reader, mc) {
|
||||
return step;
|
||||
}
|
||||
let cond = self.pop_stack();
|
||||
@@ -36,14 +36,14 @@ impl<'gc> crate::Vm<'gc> {
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_jump(&mut self, reader: &mut BytecodeReader<'_>) -> StepResult<'gc> {
|
||||
pub(crate) fn op_jump(&mut self, reader: &mut BytecodeReader<'_>) -> StepResult {
|
||||
let offset = reader.read_i32();
|
||||
reader.set_pc(((reader.pc() as isize) + (offset as isize)) as usize);
|
||||
StepResult::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_assert(&mut self, reader: &mut BytecodeReader<'_>) -> StepResult<'gc> {
|
||||
pub(crate) fn op_assert(&mut self, reader: &mut BytecodeReader<'_>) -> StepResult {
|
||||
let _raw_idx = reader.read_u32();
|
||||
let _span_id = reader.read_u32();
|
||||
todo!("implement Assert (force TOS)");
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::{BytecodeReader, StepResult, Value};
|
||||
|
||||
impl<'gc> crate::Vm<'gc> {
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_push_smi(&mut self, reader: &mut BytecodeReader<'_>) -> StepResult<'gc> {
|
||||
pub(crate) fn op_push_smi(&mut self, reader: &mut BytecodeReader<'_>) -> StepResult {
|
||||
let val = reader.read_i32();
|
||||
self.push_stack(Value::new_inline(val));
|
||||
StepResult::Continue
|
||||
@@ -15,40 +15,40 @@ impl<'gc> crate::Vm<'gc> {
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult<'gc> {
|
||||
) -> StepResult {
|
||||
let val = reader.read_i64();
|
||||
self.push_stack(Value::new_gc(Gc::new(mc, val)));
|
||||
StepResult::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_push_float(&mut self, reader: &mut BytecodeReader<'_>) -> StepResult<'gc> {
|
||||
pub(crate) fn op_push_float(&mut self, reader: &mut BytecodeReader<'_>) -> StepResult {
|
||||
let val = reader.read_f64();
|
||||
self.push_stack(Value::new_float(val));
|
||||
StepResult::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_push_string(&mut self, reader: &mut BytecodeReader<'_>) -> StepResult<'gc> {
|
||||
pub(crate) fn op_push_string(&mut self, reader: &mut BytecodeReader<'_>) -> StepResult {
|
||||
let sid = reader.read_string_id();
|
||||
self.push_stack(Value::new_inline(sid));
|
||||
StepResult::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_push_null(&mut self) -> StepResult<'gc> {
|
||||
pub(crate) fn op_push_null(&mut self) -> StepResult {
|
||||
self.push_stack(Value::new_inline(crate::Null));
|
||||
StepResult::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_push_true(&mut self) -> StepResult<'gc> {
|
||||
pub(crate) fn op_push_true(&mut self) -> StepResult {
|
||||
self.push_stack(Value::new_inline(true));
|
||||
StepResult::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_push_false(&mut self) -> StepResult<'gc> {
|
||||
pub(crate) fn op_push_false(&mut self) -> StepResult {
|
||||
self.push_stack(Value::new_inline(false));
|
||||
StepResult::Continue
|
||||
}
|
||||
|
||||
@@ -2,14 +2,14 @@ use crate::{BytecodeReader, Mutation, StepResult, Value};
|
||||
|
||||
impl<'gc> crate::Vm<'gc> {
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_load_local(&mut self, reader: &mut BytecodeReader<'_>) -> StepResult<'gc> {
|
||||
pub(crate) fn op_load_local(&mut self, reader: &mut BytecodeReader<'_>) -> StepResult {
|
||||
let idx = reader.read_u32() as usize;
|
||||
self.push_stack(self.env.borrow().locals[idx]);
|
||||
StepResult::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_load_outer(&mut self, reader: &mut BytecodeReader<'_>) -> StepResult<'gc> {
|
||||
pub(crate) fn op_load_outer(&mut self, reader: &mut BytecodeReader<'_>) -> StepResult {
|
||||
let layer = reader.read_u8();
|
||||
let idx = reader.read_u32() as usize;
|
||||
let mut cur = self.env;
|
||||
@@ -27,7 +27,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult<'gc> {
|
||||
) -> StepResult {
|
||||
let idx = reader.read_u32() as usize;
|
||||
let val = self.pop_stack();
|
||||
self.env.borrow_mut(mc).locals[idx] = val;
|
||||
@@ -39,7 +39,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult<'gc> {
|
||||
) -> StepResult {
|
||||
let count = reader.read_u32() as usize;
|
||||
self.env
|
||||
.borrow_mut(mc)
|
||||
|
||||
@@ -11,7 +11,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &mut impl crate::VmContext,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &gc_arena::Mutation<'gc>,
|
||||
) -> StepResult<'gc> {
|
||||
) -> StepResult {
|
||||
let env = reader.read_operand_data(ctx).resolve(mc, self);
|
||||
let scope = Gc::new(
|
||||
mc,
|
||||
@@ -25,7 +25,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_pop_with(&mut self) -> StepResult<'gc> {
|
||||
pub(crate) fn op_pop_with(&mut self) -> StepResult {
|
||||
let Some(scope) = self.with_env else {
|
||||
unreachable!("no with_scope to pop");
|
||||
};
|
||||
@@ -34,7 +34,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_prepare_with(&mut self) -> StepResult<'gc> {
|
||||
pub(crate) fn op_prepare_with(&mut self) -> StepResult {
|
||||
self.call_stack.push(CallFrame {
|
||||
pc: usize::MAX,
|
||||
stack_depth: 0,
|
||||
@@ -51,7 +51,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
ctx: &mut impl crate::VmContext,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &gc_arena::Mutation<'gc>,
|
||||
) -> StepResult<'gc> {
|
||||
) -> StepResult {
|
||||
let name = reader.read_string_id();
|
||||
|
||||
let Some(&WithEnv { env, prev }) = self.with_env.as_deref() else {
|
||||
@@ -65,7 +65,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
)));
|
||||
};
|
||||
self.push_stack(env);
|
||||
if let Some(step) = self.try_force_resolved(0, reader.inst_start_pc(), mc) {
|
||||
if let Some(step) = self.try_force(0, reader, mc) {
|
||||
return step;
|
||||
}
|
||||
|
||||
|
||||
+37
-77
@@ -131,21 +131,12 @@ impl<T: VmContext> VmContextExt for T {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) enum StepResult<'gc> {
|
||||
#[repr(u8)]
|
||||
pub(crate) enum StepResult {
|
||||
Continue,
|
||||
ForceThunk(ForceInfo<'gc>),
|
||||
Done,
|
||||
}
|
||||
|
||||
pub(crate) struct ForceInfo<'gc> {
|
||||
pub(crate) thunk: Gc<'gc, Thunk<'gc>>,
|
||||
pub(crate) stack_depth: usize,
|
||||
pub(crate) inst_start_pc: usize,
|
||||
pub(crate) ip: usize,
|
||||
pub(crate) env: GcEnv<'gc>,
|
||||
pub(crate) with_env: Option<GcWithEnv<'gc>>,
|
||||
}
|
||||
|
||||
#[derive(Collect)]
|
||||
#[collect(no_drop)]
|
||||
pub struct Vm<'gc> {
|
||||
@@ -279,19 +270,19 @@ impl<'gc> Vm<'gc> {
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn finish_ok(&mut self, val: fix_common::Value) -> StepResult<'gc> {
|
||||
pub(crate) fn finish_ok(&mut self, val: fix_common::Value) -> StepResult {
|
||||
self.result = Some(Ok(val));
|
||||
StepResult::Done
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn finish_err(&mut self, err: Box<Error>) -> StepResult<'gc> {
|
||||
pub(crate) fn finish_err(&mut self, err: Box<Error>) -> StepResult {
|
||||
self.result = Some(Err(err));
|
||||
StepResult::Done
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn finish_vm_err(&mut self, err: VmError) -> StepResult<'gc> {
|
||||
pub(crate) fn finish_vm_err(&mut self, err: VmError) -> StepResult {
|
||||
self.finish_err(err.into_error())
|
||||
}
|
||||
|
||||
@@ -338,65 +329,42 @@ impl<'gc> Vm<'gc> {
|
||||
pub(crate) fn try_force(
|
||||
&mut self,
|
||||
depth: usize,
|
||||
inst_start_pc: usize,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> StepResult<'gc> {
|
||||
) -> Option<StepResult> {
|
||||
let val = self.peek_stack(depth);
|
||||
if let Some(thunk) = val.as_gc::<Thunk>() {
|
||||
let mut state = thunk.borrow_mut(mc);
|
||||
match *state {
|
||||
ThunkState::Pending { ip, env, with_env } => {
|
||||
*state = ThunkState::Blackhole;
|
||||
drop(state);
|
||||
StepResult::ForceThunk(ForceInfo {
|
||||
thunk,
|
||||
stack_depth: depth,
|
||||
inst_start_pc,
|
||||
ip,
|
||||
env,
|
||||
with_env,
|
||||
})
|
||||
}
|
||||
ThunkState::Evaluated(v) => {
|
||||
self.replace_stack(depth, v.relax());
|
||||
StepResult::Continue
|
||||
}
|
||||
ThunkState::Apply { .. } => todo!("force apply"),
|
||||
ThunkState::Blackhole => {
|
||||
self.finish_err(Error::eval_error("infinite recursion encountered"))
|
||||
}
|
||||
let Some(thunk) = val.as_gc::<Thunk>() else {
|
||||
return None;
|
||||
};
|
||||
let mut state = thunk.borrow_mut(mc);
|
||||
match *state {
|
||||
ThunkState::Pending { ip, env, with_env } => {
|
||||
*state = ThunkState::Blackhole;
|
||||
drop(state);
|
||||
self.call_stack.push(CallFrame {
|
||||
thunk: Some(thunk),
|
||||
stack_depth: depth,
|
||||
pc: reader.inst_start_pc(),
|
||||
env: self.env,
|
||||
with_env: self.with_env,
|
||||
});
|
||||
self.env = env;
|
||||
self.with_env = with_env;
|
||||
reader.set_pc(ip);
|
||||
Some(StepResult::Continue)
|
||||
}
|
||||
ThunkState::Evaluated(v) => {
|
||||
drop(state);
|
||||
self.replace_stack(depth, v.relax());
|
||||
None
|
||||
}
|
||||
ThunkState::Apply { .. } => todo!("force apply"),
|
||||
ThunkState::Blackhole => {
|
||||
drop(state);
|
||||
Some(self.finish_err(Error::eval_error("infinite recursion encountered")))
|
||||
}
|
||||
} else {
|
||||
StepResult::Continue
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn try_force_resolved(
|
||||
&mut self,
|
||||
depth: usize,
|
||||
inst_start_pc: usize,
|
||||
mc: &Mutation<'gc>,
|
||||
) -> Option<StepResult<'gc>> {
|
||||
match self.try_force(depth, inst_start_pc, mc) {
|
||||
StepResult::Continue => None,
|
||||
other => Some(other),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn apply_force_thunk(&mut self, info: ForceInfo<'gc>) -> usize {
|
||||
self.call_stack.push(CallFrame {
|
||||
thunk: Some(info.thunk),
|
||||
stack_depth: info.stack_depth,
|
||||
pc: info.inst_start_pc,
|
||||
env: self.env,
|
||||
with_env: self.with_env,
|
||||
});
|
||||
self.env = info.env;
|
||||
self.with_env = info.with_env;
|
||||
info.ip
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
@@ -476,10 +444,6 @@ impl<'gc> Vm<'gc> {
|
||||
TailResult::YieldFuel(new_pc) => Action::Continue {
|
||||
pc: new_pc as usize,
|
||||
},
|
||||
TailResult::ForceThunk(info) => {
|
||||
let new_pc = self.apply_force_thunk(info);
|
||||
Action::Continue { pc: new_pc }
|
||||
}
|
||||
TailResult::Done => {
|
||||
Action::Done(self.result.take().expect("TailResult::Done without result"))
|
||||
}
|
||||
@@ -552,7 +516,7 @@ impl<'gc> Vm<'gc> {
|
||||
OpLeq => self.op_leq(ctx, &mut reader, mc),
|
||||
OpGeq => self.op_geq(ctx, &mut reader, mc),
|
||||
OpConcat => self.op_concat(&mut reader, mc),
|
||||
OpUpdate => self.op_update(mc, reader.inst_start_pc()),
|
||||
OpUpdate => self.op_update(&mut reader, mc),
|
||||
|
||||
OpNeg => self.op_neg(),
|
||||
OpNot => self.op_not(),
|
||||
@@ -583,10 +547,6 @@ impl<'gc> Vm<'gc> {
|
||||
|
||||
match result {
|
||||
StepResult::Continue => {}
|
||||
StepResult::ForceThunk(info) => {
|
||||
let new_pc = self.apply_force_thunk(info);
|
||||
reader.set_pc(new_pc);
|
||||
}
|
||||
StepResult::Done => {
|
||||
return Action::Done(
|
||||
self.result.take().expect("StepResult::Done without result"),
|
||||
|
||||
Reference in New Issue
Block a user