feat: less clone, avoid evaluating not depended thunk

This commit is contained in:
2025-06-18 09:32:00 +08:00
parent 3e9f0a72a0
commit d875951c09
14 changed files with 409 additions and 192 deletions

View File

@@ -1,15 +1,15 @@
use std::rc::Rc;
use crate::env::VmEnv;
use crate::env::Env;
use crate::ir;
pub struct Func<'gc> {
pub func: &'gc ir::Func,
pub env: Rc<VmEnv>,
pub env: Rc<Env>,
}
impl<'gc> Func<'gc> {
pub fn new(func: &'gc ir::Func, env: Rc<VmEnv>) -> Self {
pub fn new(func: &'gc ir::Func, env: Rc<Env>) -> Self {
Self { func, env }
}
}

View File

@@ -5,7 +5,7 @@ use ecow::EcoVec;
use hashbrown::HashSet;
use crate::engine::Engine;
use crate::env::VmEnv;
use crate::env::Env;
use crate::ty::public as p;
use super::Value;

View File

@@ -10,7 +10,7 @@ use super::common::*;
use super::public as p;
use crate::engine::Engine;
use crate::env::{VmEnv, VmEnvWeak};
use crate::env::{Env, VmEnvWeak};
use crate::error::*;
mod attrset;
@@ -23,45 +23,6 @@ pub use attrset::*;
pub use list::List;
pub use primop::*;
#[derive(Clone)]
pub enum EnvRef {
Strong(VmEnv),
Weak(VmEnvWeak),
}
#[derive(Clone, Debug)]
pub struct ThunkRef {
pub idx: usize,
// pub env: Option<EnvRef>,
}
impl ThunkRef {
pub fn new(idx: usize) -> Self {
ThunkRef {
idx, /* env: None */
}
}
/*
pub fn capture(&mut self, env: EnvRef) {
let _ = self.env.insert(env);
}
pub fn upgrade(&mut self) {
replace_with_or_abort(&mut self.env, |env| {
env.map(|env| EnvRef::Strong(env.upgraded()))
});
} */
}
/*
impl EnvRef {
pub fn upgraded(self) -> VmEnv {
match self {
EnvRef::Weak(weak) => weak.upgrade(),
EnvRef::Strong(strong) => strong,
}
}
} */
#[derive(IsVariant, Unwrap, Clone, Debug)]
pub enum Value {
Int(i64),
@@ -69,7 +30,7 @@ pub enum Value {
Bool(bool),
String(EcoString),
Null,
Thunk(ThunkRef),
Thunk(usize),
AttrSet(Rc<AttrSet>),
List(List),
Catchable(EcoString),
@@ -129,7 +90,7 @@ pub enum ValueAsRef<'v> {
Bool(bool),
String(&'v EcoString),
Null,
Thunk(&'v ThunkRef),
Thunk(usize),
AttrSet(&'v AttrSet),
List(&'v List),
Catchable(&'v str),
@@ -149,7 +110,7 @@ impl Value {
Bool(x) => R::Bool(*x),
String(x) => R::String(x),
Null => R::Null,
Thunk(x) => R::Thunk(x),
Thunk(x) => R::Thunk(*x),
AttrSet(x) => R::AttrSet(x),
List(x) => R::List(x),
Catchable(x) => R::Catchable(x),
@@ -192,7 +153,7 @@ impl Value {
}
}
pub fn call(&mut self, args: Vec<Self>, engine: &mut Engine, env: &mut VmEnv) -> Result<()> {
pub fn call(&mut self, args: Vec<Self>, engine: &mut Engine, env: &mut Env) -> Result<()> {
use Value::*;
for arg in args.iter() {
if matches!(arg, Value::Catchable(_)) {
@@ -206,6 +167,7 @@ impl Value {
PartialFunc(idx, old) => {
let idx = *idx;
let len = args.len() + old.len();
env.reserve_args(len);
env.enter_args(std::mem::take(old));
env.enter_cache_level(|env| {
let mut args = args.into_iter().peekable();
@@ -240,6 +202,7 @@ impl Value {
&mut Func(idx) => {
let len = args.len();
let mut args = args.into_iter().peekable();
env.reserve_args(len);
env.enter_cache_level(|env| {
env.enter_arg(args.next().unwrap());
let mut ret = engine.eval_thunk(idx, env)?;
@@ -510,18 +473,9 @@ impl Value {
self
}
pub fn force(&mut self, engine: &mut Engine, env: &mut VmEnv) -> Result<&mut Self> {
if let Value::Thunk(thunk) = self {
unsafe {
let old = std::ptr::read(thunk);
match env.lookup_cache(old.idx, |env| engine.eval_thunk(old.idx, env)) {
Ok(ok) => std::ptr::write(self, ok),
Err(err) => {
std::ptr::write(self, Self::Null);
return Err(err);
}
}
}
pub fn force(&mut self, engine: &mut Engine, env: &mut Env) -> Result<&mut Self> {
if let &mut Value::Thunk(idx) = self {
*self = env.lookup_cache(idx, |env| engine.eval_thunk(idx, env))?
}
Ok(self)
}