feat: add experimental tailcall vm backend
This commit is contained in:
@@ -72,25 +72,22 @@ impl<'gc> crate::Vm<'gc> {
|
||||
Some(v) => {
|
||||
self.replace_stack(0, v);
|
||||
}
|
||||
None => {
|
||||
loop {
|
||||
let byte = reader.bytecode()[reader.pc()];
|
||||
if byte == fix_codegen::Op::SelectStatic as u8 {
|
||||
reader.set_pc(reader.pc() + 1 + 4 + 4);
|
||||
} else if byte == fix_codegen::Op::SelectDynamic as u8 {
|
||||
reader.set_pc(reader.pc() + 1 + 4);
|
||||
} else if byte == fix_codegen::Op::JumpIfSelectSucceeded as u8 {
|
||||
reader.set_pc(reader.pc() + 1 + 4);
|
||||
let _ = self.pop_stack();
|
||||
break;
|
||||
} else {
|
||||
let name = ctx.resolve_string(key);
|
||||
return self.finish_err(Error::eval_error(format!(
|
||||
"attribute '{name}' missing"
|
||||
)));
|
||||
}
|
||||
None => loop {
|
||||
let byte = reader.bytecode()[reader.pc()];
|
||||
if byte == fix_codegen::Op::SelectStatic as u8 {
|
||||
reader.set_pc(reader.pc() + 1 + 4 + 4);
|
||||
} else if byte == fix_codegen::Op::SelectDynamic as u8 {
|
||||
reader.set_pc(reader.pc() + 1 + 4);
|
||||
} else if byte == fix_codegen::Op::JumpIfSelectSucceeded as u8 {
|
||||
reader.set_pc(reader.pc() + 1 + 4);
|
||||
let _ = self.pop_stack();
|
||||
break;
|
||||
} else {
|
||||
let name = ctx.resolve_string(key);
|
||||
return self
|
||||
.finish_err(Error::eval_error(format!("attribute '{name}' missing")));
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
StepResult::Continue
|
||||
}
|
||||
@@ -119,9 +116,7 @@ impl<'gc> crate::Vm<'gc> {
|
||||
} else if let Some(ns) = key_val.as_gc::<NixString>() {
|
||||
ctx.intern_string(ns.as_str())
|
||||
} else {
|
||||
return self.finish_err(Error::eval_error(
|
||||
"dynamic select key must be a string",
|
||||
));
|
||||
return self.finish_err(Error::eval_error("dynamic select key must be a string"));
|
||||
};
|
||||
|
||||
let attrset_val = self.stack[self.stack.len() - 2].restrict().expect("forced");
|
||||
@@ -138,16 +133,17 @@ impl<'gc> crate::Vm<'gc> {
|
||||
}
|
||||
None => {
|
||||
let name = ctx.resolve_string(key_sid);
|
||||
return self.finish_err(Error::eval_error(format!(
|
||||
"attribute '{name}' missing"
|
||||
)));
|
||||
return self.finish_err(Error::eval_error(format!("attribute '{name}' missing")));
|
||||
}
|
||||
}
|
||||
StepResult::Continue
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn op_jump_if_select_succeeded(&mut self, reader: &mut BytecodeReader<'_>) -> StepResult<'gc> {
|
||||
pub(crate) fn op_jump_if_select_succeeded(
|
||||
&mut self,
|
||||
reader: &mut BytecodeReader<'_>,
|
||||
) -> StepResult<'gc> {
|
||||
let offset = reader.read_i32();
|
||||
reader.set_pc(((reader.pc() as isize) + (offset as isize)) as usize);
|
||||
StepResult::Continue
|
||||
@@ -186,4 +182,4 @@ impl<'gc> crate::Vm<'gc> {
|
||||
pub(crate) struct AttrEntry {
|
||||
pub(crate) key: AttrKeyData,
|
||||
pub(crate) val: OperandData,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user