API BREAK: use simple byteslices for module; -ModuleKind

This commit is contained in:
Alain Zscheile 2022-10-15 17:18:17 +02:00
parent 25ae04cb37
commit ff2d189344
3 changed files with 20 additions and 40 deletions

View file

@ -151,7 +151,7 @@ mod tests {
#[test]
fn doesnt_crash(inp in proptest::collection::vec(0..=u8::MAX, 0..1024)) {
let mut inp = &inp[..];
while let Ok((xinp, v)) = <Instr as crate::Parse<'_>>::parse(&inp[..]) {
while let Ok((xinp, v)) = <Instr as crate::Parse<'_>>::parse(inp) {
let mut buf = alloc::vec::Vec::with_capacity(inp.len() - xinp.len());
v.write_to(&mut buf).unwrap();
assert_eq!(buf[..], inp[..inp.len() - xinp.len()]);

View file

@ -1,5 +1,3 @@
use std::sync::Arc;
fn main() {
use clap::Arg;
let matches = clap::Command::new("fogtix-vm")
@ -17,15 +15,13 @@ fn main() {
let main_mod_path = matches.get_one::<String>("main").unwrap();
let main_mod = Arc::new(
readfilez::read_from_file(std::fs::File::open(main_mod_path))
.expect("unable to open/load main module"),
);
let main_mod = readfilez::read_from_file(std::fs::File::open(main_mod_path))
.expect("unable to open/load main module");
let mut p = fogtix_vm::Process {
stack: Vec::new(),
callstack: Vec::new(),
m: main_mod,
m: &main_mod,
instrp: 0,
};

View file

@ -3,33 +3,19 @@
extern crate alloc;
use alloc::{sync::Arc, vec::Vec};
use alloc::vec::Vec;
use core::fmt;
use fogtix_bytecode::{consts, Instr, Parse};
pub type Module = Arc<dyn ModuleKind>;
pub trait ModuleKind: Send + Sync {
fn as_slice(&self) -> &[u8];
}
impl<T: AsRef<[u8]> + Send + Sync + ?Sized> ModuleKind for T {
#[inline(always)]
fn as_slice(&self) -> &[u8] {
self.as_ref()
}
}
fn next_instr(m: &dyn ModuleKind, pos: usize) -> Option<Result<(usize, Instr), &[u8]>> {
m.as_slice()
.get(pos..)
fn next_instr(m: &[u8], pos: usize) -> Option<Result<(usize, Instr), &[u8]>> {
m.get(pos..)
.map(|nxti_arr| match Instr::parse(nxti_arr) {
Err(_) => Err(&nxti_arr[..core::cmp::min(nxti_arr.len(), 20)]),
Ok((ptr, i)) => Ok((nxti_arr.len() - ptr.len(), i)),
})
}
fn is_call2jump(m: &dyn ModuleKind, pos: usize) -> bool {
fn is_call2jump(m: &[u8], pos: usize) -> bool {
// tail-call optimization (would otherwise require much more opcodes)
matches!(next_instr(m, pos), Some(Ok((_, Instr::Return))))
}
@ -75,16 +61,16 @@ impl fmt::Display for Error {
}
}
pub struct Process {
pub struct Process<'m> {
pub stack: Vec<StackEntValue>,
pub m: Module,
pub m: &'m [u8],
pub callstack: Vec<usize>,
pub instrp: usize,
}
fn verify_jumptarget_explicit(
jinstr: &'static str,
m: &dyn ModuleKind,
m: &[u8],
from: usize,
to: usize,
) -> Result<(), Error> {
@ -101,9 +87,9 @@ fn verify_jumptarget_explicit(
}
}
impl Process {
impl Process<'_> {
fn verify_jumptarget(&self, jinstr: &'static str, from: usize) -> Result<(), Error> {
verify_jumptarget_explicit(jinstr, &*self.m, from, self.instrp)
verify_jumptarget_explicit(jinstr, self.m, from, self.instrp)
}
fn stpop(&mut self) -> Result<StackEntValue, Error> {
@ -120,7 +106,7 @@ impl Process {
}
**x -= 1;
}
let (nxtidelta, nxti) = match next_instr(&*self.m, self.instrp) {
let (nxtidelta, nxti) = match next_instr(self.m, self.instrp) {
None => return Err(Error::InstrpOutOfBounds),
Some(Err(code)) => return Err(Error::UnparsableInstruction(code.to_vec())),
Some(Ok(x)) => x,
@ -129,14 +115,14 @@ impl Process {
match nxti {
Instr::Label => {}
Instr::CallRemote => {
if !is_call2jump(&*self.m, self.instrp) {
if !is_call2jump(self.m, self.instrp) {
self.callstack.push(self.instrp);
}
return Err(Error::RemoteCall(self.stpop()?));
}
Instr::CallLocal(x) => {
if !is_call2jump(&*self.m, self.instrp) {
self.callstack.push(self.instrp.clone());
if !is_call2jump(self.m, self.instrp) {
self.callstack.push(self.instrp);
}
self.instrp = match x.try_into() {
Ok(y) => y,
@ -152,11 +138,11 @@ impl Process {
let jtip = pos;
verify_jumptarget_explicit(
"call-l-defer",
&*self.m,
self.m,
previptr,
jtip,
)?;
if is_call2jump(&*self.m, self.instrp) {
if is_call2jump(self.m, self.instrp) {
self.instrp = jtip;
} else {
self.callstack.push(jtip);
@ -271,12 +257,10 @@ mod tests {
#[test]
fn doesnt_crash(inp in proptest::collection::vec(0..=u8::MAX, 0..1024)) {
let inp: Arc<Vec<u8>> = Arc::new(inp);
let module: Module = inp;
let mut p = Process {
stack: Vec::new(),
callstack: Vec::new(),
m: module,
m: &inp[..],
instrp: 0,
};
let _ = p.run(Some(&mut 2048));