mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-10-04 02:18:11 +08:00
Close the memoize frame on a valueless materialization and trace node exits
This commit is contained in:
@@ -2510,13 +2510,25 @@ pub(crate) fn generate_node_impl(crate_ident: &CrateIdent, parsed: &ParsedNodeFn
|
|||||||
type Output = #trait_output;
|
type Output = #trait_output;
|
||||||
|
|
||||||
fn eval(&self, __input: &#ctx_ident) -> #core_types::gpoll::GPoll<Self::Output> {
|
fn eval(&self, __input: &#ctx_ident) -> #core_types::gpoll::GPoll<Self::Output> {
|
||||||
|
// The exit trace rides a guard so early returns report too, which
|
||||||
|
// is what pins a frame leak to its node.
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
{
|
let __sp_trace = {
|
||||||
static __SP_TRACE: ::std::sync::OnceLock<bool> = ::std::sync::OnceLock::new();
|
static __SP_TRACE: ::std::sync::OnceLock<bool> = ::std::sync::OnceLock::new();
|
||||||
if *__SP_TRACE.get_or_init(|| ::std::env::var_os("GRAPHENE_SP_DEBUG").is_some()) {
|
struct __SpTrace(&'static str, usize);
|
||||||
::std::eprintln!("node> {} enter sp {}", ::std::stringify!(#fn_name), #core_types::record::stack::sp());
|
impl ::core::ops::Drop for __SpTrace {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
::std::eprintln!("node> {} exit sp {} -> {}", self.0, self.1, #core_types::record::stack::sp());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
match *__SP_TRACE.get_or_init(|| ::std::env::var_os("GRAPHENE_SP_DEBUG").is_some()) {
|
||||||
|
true => {
|
||||||
|
::std::eprintln!("node> {} enter sp {}", ::std::stringify!(#fn_name), #core_types::record::stack::sp());
|
||||||
|
Some(__SpTrace(::std::stringify!(#fn_name), #core_types::record::stack::sp()))
|
||||||
|
}
|
||||||
|
false => None,
|
||||||
|
}
|
||||||
|
};
|
||||||
let _entry_sp = #core_types::record::stack::sp();
|
let _entry_sp = #core_types::record::stack::sp();
|
||||||
let __cell = #cell_constructor;
|
let __cell = #cell_constructor;
|
||||||
#reclaim_guard
|
#reclaim_guard
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ fn memoize<'e>(
|
|||||||
#[data] cache: Arc<Mutex<Option<MemoLevel>>>,
|
#[data] cache: Arc<Mutex<Option<MemoLevel>>>,
|
||||||
content: impl Node<Context<'_>, Output = RecordValue<'e>>,
|
content: impl Node<Context<'_>, Output = RecordValue<'e>>,
|
||||||
) -> GPoll<RecordValue<'e>> {
|
) -> GPoll<RecordValue<'e>> {
|
||||||
|
let entry_sp = core_types::record::stack::sp();
|
||||||
// A scalar wire's value may depend on the consuming lane (index readers),
|
// A scalar wire's value may depend on the consuming lane (index readers),
|
||||||
// so only a leveled wire, whose level covers every lane by construction,
|
// so only a leveled wire, whose level covers every lane by construction,
|
||||||
// keys with the lane normalized away.
|
// keys with the lane normalized away.
|
||||||
@@ -99,12 +100,16 @@ fn memoize<'e>(
|
|||||||
*cache.lock().unwrap() = Some(entry);
|
*cache.lock().unwrap() = Some(entry);
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
// A valueless materialization caches nothing, so the frames it left
|
||||||
|
// behind have no reader and must not be counted against this node.
|
||||||
LevelStatus::Pending => {
|
LevelStatus::Pending => {
|
||||||
claim_frame(content.layout());
|
// SAFETY: nothing borrows the frames above the entry mark.
|
||||||
|
unsafe { core_types::record::interrupt_frame(entry_sp, content.layout()) };
|
||||||
GPoll::Pending
|
GPoll::Pending
|
||||||
}
|
}
|
||||||
LevelStatus::Error(error) => {
|
LevelStatus::Error(error) => {
|
||||||
claim_frame(content.layout());
|
// SAFETY: nothing borrows the frames above the entry mark.
|
||||||
|
unsafe { core_types::record::interrupt_frame(entry_sp, content.layout()) };
|
||||||
GPoll::Error(Box::new(error))
|
GPoll::Error(Box::new(error))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user