feat: no clone in JIT
IMPORTANT: should not drop or create values in JIT anymore
This commit is contained in:
@@ -11,7 +11,7 @@ use super::public as p;
|
||||
|
||||
use crate::bytecode::OpCodes;
|
||||
use crate::error::*;
|
||||
use crate::vm::{VmEnv, VM};
|
||||
use crate::vm::{VM, VmEnv};
|
||||
|
||||
mod attrset;
|
||||
mod func;
|
||||
@@ -28,7 +28,6 @@ pub use primop::*;
|
||||
pub enum Value<'jit: 'vm, 'vm> {
|
||||
Const(Const),
|
||||
Thunk(Rc<Thunk<'jit, 'vm>>),
|
||||
ThunkRef(&'vm Thunk<'jit, 'vm>),
|
||||
AttrSet(Rc<AttrSet<'jit, 'vm>>),
|
||||
List(Rc<List<'jit, 'vm>>),
|
||||
Catchable(Catchable),
|
||||
@@ -45,7 +44,6 @@ impl Hash for Value<'_, '_> {
|
||||
match self {
|
||||
Const(x) => x.hash(state),
|
||||
Thunk(x) => (x.as_ref() as *const self::Thunk).hash(state),
|
||||
ThunkRef(x) => (*x as *const self::Thunk).hash(state),
|
||||
AttrSet(x) => (x.as_ref() as *const self::AttrSet).hash(state),
|
||||
List(x) => (x.as_ref() as *const self::List).hash(state),
|
||||
Catchable(x) => x.hash(state),
|
||||
@@ -119,7 +117,6 @@ impl<'v, 'vm: 'v, 'jit: 'vm> Value<'jit, 'vm> {
|
||||
match self {
|
||||
Const(x) => R::Const(x),
|
||||
Thunk(x) => R::Thunk(x),
|
||||
ThunkRef(x) => R::Thunk(x),
|
||||
AttrSet(x) => R::AttrSet(x),
|
||||
List(x) => R::List(x),
|
||||
Catchable(x) => R::Catchable(x),
|
||||
@@ -136,7 +133,6 @@ impl<'v, 'vm: 'v, 'jit: 'vm> Value<'jit, 'vm> {
|
||||
match self {
|
||||
Const(x) => M::Const(x),
|
||||
Thunk(x) => M::Thunk(x),
|
||||
ThunkRef(x) => M::Thunk(x),
|
||||
AttrSet(x) => M::AttrSet(Rc::make_mut(x)),
|
||||
List(x) => M::List(Rc::make_mut(x)),
|
||||
Catchable(x) => M::Catchable(x),
|
||||
@@ -163,7 +159,6 @@ impl<'jit, 'vm> Value<'jit, 'vm> {
|
||||
Const(self::Const::String(_)) => "string",
|
||||
Const(self::Const::Null) => "null",
|
||||
Thunk(_) => "thunk",
|
||||
ThunkRef(_) => "thunk",
|
||||
AttrSet(_) => "set",
|
||||
List(_) => "list",
|
||||
Catchable(_) => unreachable!(),
|
||||
@@ -420,10 +415,7 @@ impl<'jit, 'vm> Value<'jit, 'vm> {
|
||||
|
||||
pub fn force(&mut self, vm: &'vm VM<'jit>) -> Result<&mut Self> {
|
||||
if let Value::Thunk(thunk) = self {
|
||||
let value = thunk.force(vm)?;
|
||||
*self = value
|
||||
} else if let Value::ThunkRef(thunk) = self {
|
||||
let value = thunk.force(vm)?;
|
||||
let value = thunk.force(vm)?.clone();
|
||||
*self = value
|
||||
}
|
||||
Ok(self)
|
||||
@@ -432,12 +424,7 @@ impl<'jit, 'vm> Value<'jit, 'vm> {
|
||||
pub fn force_deep(&mut self, vm: &'vm VM<'jit>) -> Result<&mut Self> {
|
||||
match self {
|
||||
Value::Thunk(thunk) => {
|
||||
let mut value = thunk.force(vm)?;
|
||||
let _ = value.force_deep(vm)?;
|
||||
*self = value;
|
||||
}
|
||||
Value::ThunkRef(thunk) => {
|
||||
let mut value = thunk.force(vm)?;
|
||||
let mut value = thunk.force(vm)?.clone();
|
||||
let _ = value.force_deep(vm)?;
|
||||
*self = value;
|
||||
}
|
||||
@@ -461,7 +448,6 @@ impl<'jit, 'vm> Value<'jit, 'vm> {
|
||||
Catchable(catchable) => Value::Catchable(catchable.clone()),
|
||||
Const(cnst) => Value::Const(cnst.clone()),
|
||||
Thunk(_) => Value::Thunk,
|
||||
ThunkRef(_) => Value::Thunk,
|
||||
PrimOp(primop) => Value::PrimOp(primop.name),
|
||||
PartialPrimOp(primop) => Value::PartialPrimOp(primop.name),
|
||||
Func(_) => Value::Func,
|
||||
@@ -477,11 +463,17 @@ pub struct Thunk<'jit, 'vm> {
|
||||
|
||||
#[derive(Debug, IsVariant, Unwrap, Clone)]
|
||||
pub enum _Thunk<'jit, 'vm> {
|
||||
Code(&'vm OpCodes, OnceCell<Rc<VmEnv<'jit, 'vm>>>),
|
||||
Code(&'vm OpCodes, OnceCell<EnvRef<'jit, 'vm>>),
|
||||
SuspendedFrom(*const Thunk<'jit, 'vm>),
|
||||
Value(Value<'jit, 'vm>),
|
||||
}
|
||||
|
||||
#[derive(Debug, IsVariant, Unwrap, Clone)]
|
||||
pub enum EnvRef<'jit, 'vm> {
|
||||
Strong(Rc<VmEnv<'jit, 'vm>>),
|
||||
Weak(Weak<VmEnv<'jit, 'vm>>),
|
||||
}
|
||||
|
||||
impl<'jit, 'vm> Thunk<'jit, 'vm> {
|
||||
pub fn new(opcodes: &'vm OpCodes) -> Self {
|
||||
Thunk {
|
||||
@@ -491,32 +483,48 @@ impl<'jit, 'vm> Thunk<'jit, 'vm> {
|
||||
|
||||
pub fn capture(&self, env: Rc<VmEnv<'jit, 'vm>>) {
|
||||
if let _Thunk::Code(_, envcell) = &*self.thunk.borrow() {
|
||||
envcell.get_or_init(|| env);
|
||||
envcell.get_or_init(|| EnvRef::Strong(env));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn force(&self, vm: &'vm VM<'jit>) -> Result<Value<'jit, 'vm>> {
|
||||
pub fn capture_weak(&self, env: Weak<VmEnv<'jit, 'vm>>) {
|
||||
if let _Thunk::Code(_, envcell) = &*self.thunk.borrow() {
|
||||
envcell.get_or_init(|| EnvRef::Weak(env));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn force(&self, vm: &'vm VM<'jit>) -> Result<&Value<'jit, 'vm>> {
|
||||
use _Thunk::*;
|
||||
match &*self.thunk.borrow() {
|
||||
_Thunk::Value(value) => return Ok(value.clone()),
|
||||
_Thunk::SuspendedFrom(from) => {
|
||||
Value(_) => {
|
||||
return Ok(match unsafe { &*(&*self.thunk.borrow() as *const _) } {
|
||||
Value(value) => value,
|
||||
_ => unreachable!(),
|
||||
});
|
||||
}
|
||||
SuspendedFrom(from) => {
|
||||
return Err(Error::EvalError(format!(
|
||||
"thunk {:p} already suspended from {from:p} (infinite recursion encountered)",
|
||||
self as *const Thunk
|
||||
)));
|
||||
}
|
||||
_Thunk::Code(..) => (),
|
||||
Code(..) => (),
|
||||
}
|
||||
let (opcodes, env) = std::mem::replace(
|
||||
&mut *self.thunk.borrow_mut(),
|
||||
_Thunk::SuspendedFrom(self as *const Thunk),
|
||||
)
|
||||
.unwrap_code();
|
||||
let value = vm.eval(opcodes.iter().copied(), env.get().unwrap().clone())?;
|
||||
let _ = std::mem::replace(
|
||||
&mut *self.thunk.borrow_mut(),
|
||||
_Thunk::Value(value.clone()),
|
||||
);
|
||||
Ok(value)
|
||||
let env = match env.get().unwrap() {
|
||||
EnvRef::Strong(env) => env.clone(),
|
||||
EnvRef::Weak(env) => env.upgrade().unwrap(),
|
||||
};
|
||||
let value = vm.eval(opcodes.iter().copied(), env)?;
|
||||
let _ = std::mem::replace(&mut *self.thunk.borrow_mut(), _Thunk::Value(value));
|
||||
Ok(match unsafe { &*(&*self.thunk.borrow() as *const _) } {
|
||||
Value(value) => value,
|
||||
_ => unreachable!(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn value(&'vm self) -> Option<Value<'jit, 'vm>> {
|
||||
|
||||
Reference in New Issue
Block a user