refactor(vm): DRY jump safety checks
This commit is contained in:
parent
bc96f9f130
commit
b410e7a5b8
|
@ -1,4 +1,4 @@
|
|||
use fogtix_bytecode::{Atom, Parse, Pointer, Value as BcValue};
|
||||
use fogtix_bytecode::{Atom, Instr, Parse, Pointer, Value as BcValue};
|
||||
use std::marker::PhantomData;
|
||||
use std::sync::Arc;
|
||||
|
||||
|
@ -59,10 +59,37 @@ struct Process {
|
|||
}
|
||||
|
||||
impl Process {
|
||||
fn is_call2jump(instrp: &(Arc<Module>, usize)) -> bool {
|
||||
let mut call2jump = false;
|
||||
if let Some(n2xti_arr) = instrp.0.h.get(instrp.1..) {
|
||||
if let Ok((_, Instr::Return)) = Instr::parse(n2xti_arr) {
|
||||
// tail-call optimization (would otherwise require another opcode)
|
||||
call2jump = true;
|
||||
}
|
||||
}
|
||||
call2jump
|
||||
}
|
||||
|
||||
fn verify_jumptarget(&self, previptr: usize, jinstr: &str) -> bool {
|
||||
if let Some(n2xti_arr) = self.instrp.0.h.get(self.instrp.1..) {
|
||||
if let Ok((_, trgi)) = Instr::parse(n2xti_arr) {
|
||||
if trgi != Instr::Label {
|
||||
tracing::error!(
|
||||
"`{}` arrived at non-jump target {:?} @ {}",
|
||||
jinstr,
|
||||
trgi,
|
||||
previptr,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn run(&mut self) {
|
||||
loop {
|
||||
use fogtix_bytecode::consts::{AtomOp, MathBinOp};
|
||||
use fogtix_bytecode::Instr;
|
||||
let previptr = self.instrp.1;
|
||||
tracing::trace!("previptr = {}", previptr);
|
||||
let nxti_arr = match self.instrp.0.h.get(previptr..) {
|
||||
|
@ -90,14 +117,7 @@ impl Process {
|
|||
match nxti {
|
||||
Instr::Label => {}
|
||||
Instr::CallRemote(atom, arity) => {
|
||||
let mut call2jump = false;
|
||||
if let Some(n2xti_arr) = self.instrp.0.h.get(self.instrp.1..) {
|
||||
if let Ok((_, Instr::Return)) = Instr::parse(n2xti_arr) {
|
||||
// tail-call optimization (would otherwise require another opcode)
|
||||
call2jump = true;
|
||||
}
|
||||
}
|
||||
if !call2jump {
|
||||
if !Self::is_call2jump(&self.instrp) {
|
||||
self.callstack.push(self.instrp.clone());
|
||||
}
|
||||
match self.stack.pop() {
|
||||
|
@ -120,28 +140,12 @@ impl Process {
|
|||
break;
|
||||
}
|
||||
}
|
||||
if let Some(n2xti_arr) = self.instrp.0.h.get(self.instrp.1..) {
|
||||
if let Ok((_, trgi)) = Instr::parse(n2xti_arr) {
|
||||
if trgi != Instr::Label {
|
||||
tracing::error!(
|
||||
"`call-r` arrived at non-jump target {:?} @ {}",
|
||||
trgi,
|
||||
previptr
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if !self.verify_jumptarget(previptr, "call-r") {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Instr::CallLocal(x) => {
|
||||
let mut call2jump = false;
|
||||
if let Some(n2xti_arr) = self.instrp.0.h.get(self.instrp.1..) {
|
||||
if let Ok((_, Instr::Return)) = Instr::parse(n2xti_arr) {
|
||||
// tail-call optimization (would otherwise require another opcode)
|
||||
call2jump = true;
|
||||
}
|
||||
}
|
||||
if !call2jump {
|
||||
if !Self::is_call2jump(&self.instrp) {
|
||||
self.callstack.push(self.instrp.clone());
|
||||
}
|
||||
self.instrp.1 = match x.try_into() {
|
||||
|
@ -155,17 +159,8 @@ impl Process {
|
|||
break;
|
||||
}
|
||||
};
|
||||
if let Some(n2xti_arr) = self.instrp.0.h.get(self.instrp.1..) {
|
||||
if let Ok((_, trgi)) = Instr::parse(n2xti_arr) {
|
||||
if trgi != Instr::Label {
|
||||
tracing::error!(
|
||||
"`call-l` arrived at non-jump target {:?} @ {}",
|
||||
trgi,
|
||||
previptr
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if !self.verify_jumptarget(previptr, "call-l") {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Instr::Jump(x) => {
|
||||
|
@ -180,17 +175,8 @@ impl Process {
|
|||
break;
|
||||
}
|
||||
};
|
||||
if let Some(n2xti_arr) = self.instrp.0.h.get(self.instrp.1..) {
|
||||
if let Ok((_, trgi)) = Instr::parse(n2xti_arr) {
|
||||
if trgi != Instr::Label {
|
||||
tracing::error!(
|
||||
"jump arrived at non-jump target {:?} @ {}",
|
||||
trgi,
|
||||
previptr
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if !self.verify_jumptarget(previptr, "jump") {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Instr::Return => match self.callstack.pop() {
|
||||
|
|
Loading…
Reference in a new issue