From b2a90ddc2c31d43b76077c768d59587dec21889d Mon Sep 17 00:00:00 2001 From: TrueDoctor Date: Wed, 26 Oct 2022 00:35:30 +0200 Subject: [PATCH] Relax borrow stack lifetimes (#823) Relax lifetimes for borrow_stack --- Cargo.toml | 4 +- node-graph/borrow_stack/src/lib.rs | 31 +++++------ node-graph/gcore/src/lib.rs | 2 +- node-graph/graph-craft/src/lib.rs | 11 ++-- node-graph/graph-craft/src/node_registry.rs | 58 ++++++++------------- node-graph/gstd/src/document.rs | 19 ++++++- node-graph/gstd/src/raster.rs | 4 +- 7 files changed, 67 insertions(+), 62 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2dec3785..17b2ceb9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,5 +19,5 @@ opt-level = 3 [profile.dev.package.graphite-wasm] opt-level = 3 -[profile.dev] -opt-level = 3 +#[profile.dev] +#opt-level = 3 diff --git a/node-graph/borrow_stack/src/lib.rs b/node-graph/borrow_stack/src/lib.rs index d333f117..32c35c91 100644 --- a/node-graph/borrow_stack/src/lib.rs +++ b/node-graph/borrow_stack/src/lib.rs @@ -1,18 +1,18 @@ use std::{ - marker::PhantomData, mem::MaybeUninit, pin::Pin, sync::atomic::{AtomicUsize, Ordering}, }; -pub trait BorrowStack { - type Item; +use dyn_any::StaticTypeSized; + +pub trait BorrowStack { /// # Safety - unsafe fn push(&self, value: Self::Item); + unsafe fn push(&self, value: T); /// # Safety unsafe fn pop(&self); /// # Safety - unsafe fn get(&self) -> &'static [Self::Item]; + unsafe fn get<'a>(&self) -> &'a [::Static]; } #[derive(Debug)] @@ -22,11 +22,11 @@ pub struct FixedSizeStack { len: AtomicUsize, } -impl<'n, T: Unpin + 'n + dyn_any::StaticTypeSized> FixedSizeStack { +impl<'n, T: 'n + dyn_any::StaticTypeSized> FixedSizeStack { pub fn new(capacity: usize) -> Self { let layout = std::alloc::Layout::array::>(capacity).unwrap(); let array = unsafe { std::alloc::alloc(layout) }; - let array = Pin::new(unsafe { Box::from_raw(std::slice::from_raw_parts_mut(array as *mut MaybeUninit, capacity) as *mut [MaybeUninit]) }); + let array = Box::into_pin(unsafe { Box::from_raw(std::slice::from_raw_parts_mut(array as *mut MaybeUninit, capacity) as *mut [MaybeUninit]) }); Self { data: array, @@ -42,19 +42,20 @@ impl<'n, T: Unpin + 'n + dyn_any::StaticTypeSized> FixedSizeStack { pub fn is_empty(&self) -> bool { self.len.load(Ordering::SeqCst) == 0 } - pub fn push_fn(&self, f: impl FnOnce(&'static [T::Static]) -> T) { - unsafe { self.push(std::mem::transmute_copy(&f(self.get()))) } + pub fn push_fn<'a>(&self, f: impl FnOnce(&'a [T::Static]) -> T) { + assert_eq!(std::mem::size_of::(), std::mem::size_of::()); + unsafe { self.push(f(self.get())) } } } -impl<'n, T: 'n + dyn_any::StaticTypeSized> BorrowStack for FixedSizeStack { - type Item = T::Static; - - unsafe fn push(&self, value: Self::Item) { +impl BorrowStack for FixedSizeStack { + unsafe fn push(&self, value: T) { let len = self.len.load(Ordering::SeqCst); assert!(len < self.capacity); let ptr = self.data[len].as_ptr(); - (ptr as *mut T::Static).write(value); + let static_value = std::mem::transmute_copy(&value); + (ptr as *mut T::Static).write(static_value); + std::mem::forget(value); self.len.fetch_add(1, Ordering::SeqCst); } @@ -64,7 +65,7 @@ impl<'n, T: 'n + dyn_any::StaticTypeSized> BorrowStack for FixedSizeStack { self.len.fetch_sub(1, Ordering::SeqCst); } - unsafe fn get(&self) -> &'static [Self::Item] { + unsafe fn get<'a>(&self) -> &'a [T::Static] { std::slice::from_raw_parts(self.data.as_ptr() as *const T::Static, self.len.load(Ordering::SeqCst)) } } diff --git a/node-graph/gcore/src/lib.rs b/node-graph/gcore/src/lib.rs index dca1833a..11f0f375 100644 --- a/node-graph/gcore/src/lib.rs +++ b/node-graph/gcore/src/lib.rs @@ -59,7 +59,7 @@ where impl<'n, N: 'n, I> AsRefNode<'n, I> for N where - &'n N: Node, + &'n N: Node, N: Node, Self: 'n, { diff --git a/node-graph/graph-craft/src/lib.rs b/node-graph/graph-craft/src/lib.rs index f14018ed..9bc2021f 100644 --- a/node-graph/graph-craft/src/lib.rs +++ b/node-graph/graph-craft/src/lib.rs @@ -1,3 +1,4 @@ +#![feature(trait_upcasting)] pub mod node_registry; #[cfg(test)] @@ -17,7 +18,7 @@ mod tests { fn borrow_stack() { let stack = borrow_stack::FixedSizeStack::new(256); unsafe { - let dynanynode: DynAnyNode<_, (), _, _> = DynAnyNode::new(ValueNode(2_u32)); + let dynanynode: DynAnyNode, (), _, _> = DynAnyNode::new(ValueNode(2_u32)); stack.push(dynanynode.into_box()); } stack.push_fn(|nodes| { @@ -26,6 +27,7 @@ mod tests { let dynanynode: DynAnyNode>, u32, _, _> = DynAnyNode::new(ConsNode(downcast, PhantomData)); dynanynode.into_box() }); + /* stack.push_fn(|_| { let dynanynode: DynAnyNode<_, (u32, &u32), _, _> = DynAnyNode::new(AddNode); dynanynode.into_box() @@ -33,15 +35,18 @@ mod tests { stack.push_fn(|nodes| { let compose_node = nodes[1].after(&nodes[2]); TypeErasedNode(Box::new(compose_node)) - }); + });}*/ + let result = unsafe { &stack.get()[0] }.eval_ref(().into_dyn()); + assert_eq!(*downcast::<&u32>(result).unwrap(), &2_u32); let result = unsafe { &stack.get()[1] }.eval_ref(4_u32.into_dyn()); assert_eq!(*downcast::<(u32, &u32)>(result).unwrap(), (4_u32, &2_u32)); + /* let result = unsafe { &stack.get()[1] }.eval_ref(4_u32.into_dyn()); let add = unsafe { &stack.get()[2] }.eval_ref(result); assert_eq!(*downcast::(add).unwrap(), 6_u32); let add = unsafe { &stack.get()[3] }.eval_ref(4_u32.into_dyn()); - assert_eq!(*downcast::(add).unwrap(), 6_u32); + assert_eq!(*downcast::(add).unwrap(), 6_u32);*/ } #[test] diff --git a/node-graph/graph-craft/src/node_registry.rs b/node-graph/graph-craft/src/node_registry.rs index e122b808..75688549 100644 --- a/node-graph/graph-craft/src/node_registry.rs +++ b/node-graph/graph-craft/src/node_registry.rs @@ -1,6 +1,8 @@ use std::marker::PhantomData; use borrow_stack::FixedSizeStack; +use dyn_clone::DynClone; +use graphene_core::generic::FnNode; use graphene_core::ops::{AddNode, IdNode}; use graphene_core::structural::{ConsNode, Then}; use graphene_core::{AsRefNode, Node}; @@ -14,40 +16,6 @@ struct NodeIdentifier { types: &'static [&'static str], } -const fn annotate<'n, 's: 'n, F>(f: F) -> F -where - F: Fn(ProtoNode, FixedSizeStack>), -{ - f -} - -use borrow_stack::BorrowStack; -unsafe fn foo<'n>(proto_node: ProtoNode, stack: &'n FixedSizeStack>) { - let node_id = proto_node.input.unwrap_node() as usize; - let nodes = stack.get(); - let pre_node = nodes.get(node_id).unwrap(); - let downcast: DowncastNode<_, &u32> = DowncastNode::new(pre_node); - let dynanynode: DynAnyNode>, u32, _, _> = DynAnyNode::new(ConsNode(downcast, PhantomData)); - stack.push(dynanynode.into_box()); -} -fn borrow_stack() { - let stack = borrow_stack::FixedSizeStack::new(256); - unsafe { - { - let proto_node = ProtoNode::id(); - foo(proto_node, &stack); - let proto_node = ProtoNode::id(); - let stack = &stack; - let node_id = proto_node.input.unwrap_node() as usize; - let nodes = stack.get(); - let pre_node = nodes.get(node_id).unwrap(); - let downcast: DowncastNode<&TypeErasedNode, &u32> = DowncastNode::new(pre_node); - let dynanynode: DynAnyNode>, u32, _, _> = DynAnyNode::new(ConsNode(downcast, PhantomData)); - stack.push(dynanynode.into_box()); - } - }; -} - static NODE_REGISTRY: &[(NodeIdentifier, fn(ProtoNode, &FixedSizeStack>))] = &[ ( NodeIdentifier { @@ -77,7 +45,7 @@ static NODE_REGISTRY: &[(NodeIdentifier, fn(ProtoNode, &FixedSizeStack = DowncastNode::new(pre_node); - let dynanynode: DynAnyNode>, u32, _, _> = DynAnyNode::new(ConsNode(downcast, PhantomData)); + let dynanynode: DynAnyNode<_, u32, _, _> = DynAnyNode::new(ConsNode(downcast, PhantomData)); dynanynode.into_box() }) }, - ),*/ + ), ( NodeIdentifier { name: "graphene_core::any::DowncastNode", @@ -105,6 +73,22 @@ static NODE_REGISTRY: &[(NodeIdentifier, fn(ProtoNode, &FixedSizeStack"], + }, + |proto_node, stack| { + stack.push_fn(|nodes| { + if let ConstructionArgs::Value(value) = proto_node.construction_args { + let node = FnNode::new(move |_| value.clone() as Any<'static>); + node.into_type_erased() + } else { + unreachable!() + } + }) + }, + ), ]; #[cfg(test)] diff --git a/node-graph/gstd/src/document.rs b/node-graph/gstd/src/document.rs index ae651964..50f22c3d 100644 --- a/node-graph/gstd/src/document.rs +++ b/node-graph/gstd/src/document.rs @@ -3,6 +3,7 @@ use std::fmt::Display; use std::sync::Mutex; use dyn_any::{DynAny, StaticType}; +use dyn_clone::DynClone; use rand_chacha::{ rand_core::{RngCore, SeedableRng}, ChaCha20Rng, @@ -119,14 +120,14 @@ pub struct NodeNetwork { pub nodes: HashMap, } pub type Value = Box; -pub trait ValueTrait: DynAny<'static> + std::fmt::Debug {} +pub trait ValueTrait: DynAny<'static> + std::fmt::Debug + DynClone {} pub trait IntoValue: Sized + ValueTrait + 'static { fn into_any(self) -> Value { Box::new(self) } } -impl ValueTrait for T {} +impl ValueTrait for T {} impl IntoValue for T {} #[repr(C)] @@ -156,6 +157,20 @@ impl PartialEq for Box { } } +impl Clone for Value { + fn clone(&self) -> Self { + let self_trait_object = unsafe { std::mem::transmute::<&dyn ValueTrait, TraitObject>(self.as_ref()) }; + let size = self_trait_object.vtable.size; + let self_mem = unsafe { std::slice::from_raw_parts(self_trait_object.self_ptr, size) }.to_owned(); + let ptr = Vec::leak(self_mem); + unsafe { + std::mem::transmute(TraitObject { + self_ptr: ptr as *mut [u8] as *mut u8, + vtable: self_trait_object.vtable, + }) + } + } +} #[derive(Debug, Default)] pub enum ConstructionArgs { None, diff --git a/node-graph/gstd/src/raster.rs b/node-graph/gstd/src/raster.rs index 04922661..0ba7c7ce 100644 --- a/node-graph/gstd/src/raster.rs +++ b/node-graph/gstd/src/raster.rs @@ -111,8 +111,8 @@ impl<'a> IntoIterator for &'a Image { pub fn file_node<'n, P: AsRef + 'n>() -> impl Node, Error>> { let fs = ValueNode(StdFs).clone(); - let fs = ConsNode(fs, PhantomData); - let file: ComposeNode<_, _, P> = fs.then(FileNode(PhantomData)); + let fs = ConsNode::new(fs); + let file = fs.then(FileNode(PhantomData)); file.then(FlatMapResultNode::new(BufferNode)) }