mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 22:28:10 +08:00
Retire the lend machinery and flip the clone node onto record wires
This commit is contained in:
@@ -905,111 +905,6 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Lifts a lending producer onto a record wire: a parked element carries the
|
||||
/// lent reference directly, a byte-carried one copies out of the borrow.
|
||||
pub struct RecordLiftLend<El, N> {
|
||||
edge: N,
|
||||
layout: Layout,
|
||||
_marker: std::marker::PhantomData<fn() -> El>,
|
||||
}
|
||||
|
||||
impl<El: Clone + Send + Sync + 'static, N> RecordLiftLend<El, N> {
|
||||
pub fn new(edge: N) -> Self {
|
||||
Self {
|
||||
edge,
|
||||
layout: Layout::default().with_writes(0, element_write::<El>(), &[]),
|
||||
_marker: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'e, C, El, N> Node<C> for RecordLiftLend<El, N>
|
||||
where
|
||||
C: crate::context::ExtractArena<ArenaRef = &'e crate::arena::Arena>,
|
||||
El: Send + Sync + 'static,
|
||||
N: Node<C, Output = &'e El>,
|
||||
{
|
||||
type Output = RecordValue<'e>;
|
||||
|
||||
fn eval(&self, input: &C) -> GPoll<RecordValue<'e>> {
|
||||
let build = |element: &'e El| {
|
||||
let write = |dst: *mut u8| match element_parked::<El>() {
|
||||
true => unsafe { dst.cast::<&El>().write(element) },
|
||||
false => unsafe { std::ptr::copy_nonoverlapping((element as *const El).cast::<u8>(), dst, size_of::<El>()) },
|
||||
};
|
||||
if self.layout.is_inline() {
|
||||
let mut value = RecordValue::zeroed();
|
||||
write(value.as_mut_ptr());
|
||||
value
|
||||
} else {
|
||||
let dst = stack::push(self.layout.frame_bytes());
|
||||
write(dst);
|
||||
stack::pop(dst);
|
||||
RecordValue::spilled(unsafe { Rec::new(dst.cast_const()) })
|
||||
}
|
||||
};
|
||||
self.edge.eval(input).map(build)
|
||||
}
|
||||
|
||||
fn layout(&self) -> Option<&Layout> {
|
||||
Some(&self.layout)
|
||||
}
|
||||
}
|
||||
|
||||
/// Lends a record wire's element: a parked element lends its arena-backed
|
||||
/// reference directly, a byte-carried one parks a copy so the borrow
|
||||
/// outlives the record.
|
||||
pub struct RecordExtractLend<El, N> {
|
||||
edge: N,
|
||||
layout: Layout,
|
||||
_marker: std::marker::PhantomData<fn() -> El>,
|
||||
}
|
||||
|
||||
impl<El, N> RecordExtractLend<El, N> {
|
||||
pub fn new(edge: N, layout: &Layout) -> Self {
|
||||
Self {
|
||||
edge,
|
||||
layout: layout.clone(),
|
||||
_marker: std::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'e, C, El, N> Node<C> for RecordExtractLend<El, N>
|
||||
where
|
||||
C: crate::context::ExtractArena<ArenaRef = &'e crate::arena::Arena>,
|
||||
El: Clone + Send + Sync + 'static,
|
||||
N: Node<C, Output = RecordValue<'e>>,
|
||||
{
|
||||
type Output = &'e El;
|
||||
|
||||
fn eval(&self, input: &C) -> GPoll<&'e El> {
|
||||
let exhausted = || {
|
||||
GPoll::Error(Box::new(crate::gpoll::GraphError {
|
||||
kind: crate::gpoll::ErrorKind::ArenaExhausted,
|
||||
trace: Vec::new(),
|
||||
}))
|
||||
};
|
||||
let lend = |value: RecordValue<'e>| {
|
||||
let rec = self.layout.rec(&value);
|
||||
match element_parked::<El>() {
|
||||
true => Some(unsafe { borrow_element::<El>(rec) }),
|
||||
false => input.arena().alloc(unsafe { read_element::<El>(rec) }).map(|(parked, _)| parked),
|
||||
}
|
||||
};
|
||||
match self.edge.eval(input) {
|
||||
GPoll::Final(value) => lend(value).map_or_else(exhausted, GPoll::Final),
|
||||
GPoll::Partial(value) => lend(value).map_or_else(exhausted, GPoll::Partial),
|
||||
GPoll::Fallback(boxed) => {
|
||||
let (value, error) = *boxed;
|
||||
lend(value).map_or_else(exhausted, |element| GPoll::Fallback(Box::new((element, error))))
|
||||
}
|
||||
GPoll::Pending => GPoll::Pending,
|
||||
GPoll::Error(error) => GPoll::Error(error),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Extracts the element from a record wire for a plain consumer, cloning out
|
||||
/// of the parked reference when the element carries drop glue.
|
||||
pub struct RecordExtract<El, N> {
|
||||
|
||||
@@ -290,15 +290,13 @@ pub struct RegistryEntry {
|
||||
pub constructor: NodeConstructor,
|
||||
}
|
||||
|
||||
/// The four bridge rows of `T`: plain and lend producers onto record wires,
|
||||
/// record wires into plain and lend consumers. One set exists per wire type
|
||||
/// while the worlds coexist.
|
||||
pub fn record_bridge_rows<T: Clone + Send + Sync + 'static>() -> [(crate::ProtoNodeIdentifier, RegistryEntry); 4] {
|
||||
/// The bridge rows of `T`: a plain producer onto a record wire and a record
|
||||
/// wire into a plain consumer. One pair exists per wire type while the
|
||||
/// deferred plain classes (shader, batch) coexist with record wires.
|
||||
pub fn record_bridge_rows<T: Clone + Send + Sync + 'static>() -> [(crate::ProtoNodeIdentifier, RegistryEntry); 2] {
|
||||
[
|
||||
(crate::ProtoNodeIdentifier::new("core_types::record::RecordLiftNode"), record_lift_entry::<T>()),
|
||||
(crate::ProtoNodeIdentifier::new("core_types::record::RecordExtractNode"), record_extract_entry::<T>()),
|
||||
(crate::ProtoNodeIdentifier::new("core_types::record::RecordLiftLendNode"), record_lift_lend_entry::<T>()),
|
||||
(crate::ProtoNodeIdentifier::new("core_types::record::RecordExtractLendNode"), record_extract_lend_entry::<T>()),
|
||||
]
|
||||
}
|
||||
|
||||
@@ -335,38 +333,6 @@ pub fn record_extract_entry<T: Clone + Send + Sync + 'static>() -> RegistryEntry
|
||||
}
|
||||
}
|
||||
|
||||
/// The lend-lift bridge row for `T`: a lending producer onto a record wire.
|
||||
pub fn record_lift_lend_entry<T: Clone + Send + Sync + 'static>() -> RegistryEntry {
|
||||
RegistryEntry {
|
||||
io: NodeIOTypes::new(concrete!(Context), record_type::<T>(), vec![lend_edge_type::<T>()]),
|
||||
constructor: |inputs| {
|
||||
if inputs.len() != 1 {
|
||||
return Err(ConstructionError::Arity { expected: 1, got: inputs.len() });
|
||||
}
|
||||
let mut inputs = inputs.into_iter();
|
||||
let node = crate::record::RecordLiftLend::<T, _>::new(inputs.next().unwrap().downcast_lend::<T>()?);
|
||||
Ok(EdgeHandle::new_record::<T>(std::sync::Arc::new(node) as std::sync::Arc<ErasedRecordNode>))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// The lend-extract bridge row for `T`: a record wire into a lend consumer.
|
||||
pub fn record_extract_lend_entry<T: Clone + Send + Sync + 'static>() -> RegistryEntry {
|
||||
RegistryEntry {
|
||||
io: NodeIOTypes::new(concrete!(Context), ref_type::<T>(), vec![record_edge_type::<T>()]),
|
||||
constructor: |inputs| {
|
||||
if inputs.len() != 1 {
|
||||
return Err(ConstructionError::Arity { expected: 1, got: inputs.len() });
|
||||
}
|
||||
let mut inputs = inputs.into_iter();
|
||||
let edge = inputs.next().unwrap();
|
||||
let layout = edge.layout().ok_or(ConstructionError::MissingLayout)?.clone();
|
||||
let node = crate::record::RecordExtractLend::<T, _>::new(edge.downcast_record::<T>()?, &layout);
|
||||
Ok(EdgeHandle::new_ref(std::sync::Arc::new(node) as std::sync::Arc<ErasedLendNode<T>>))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn construct(entry: &RegistryEntry, inputs: Vec<EdgeHandle>) -> Result<EdgeHandle, ConstructionError> {
|
||||
if inputs.len() != entry.io.inputs.len() {
|
||||
return Err(ConstructionError::Arity {
|
||||
|
||||
Reference in New Issue
Block a user