Store record batches in caller-owned frame buffers instead of aliased stack pointers

This commit is contained in:
Dennis Kobert
2026-08-16 11:29:20 +00:00
parent 9055a5f3d5
commit ac40f1838f
6 changed files with 292 additions and 289 deletions

View File

@@ -457,6 +457,42 @@ mod tests {
assert_eq!(unsafe { out.rec(&value).element::<f64>() }, 21.);
}
#[test]
fn reducer_folds_varying_copies_of_a_generic_repeat() {
let arena = Arena::new(1024).unwrap();
let generations = [];
let scope = scope_fixture(&generations, &arena);
let ctx = ContextImpl::root(&scope);
let base = f64_layout(&[]);
let (count_edge, count_layout) = lifted_value(4u32);
let out = f64_layout(&[]);
reserve_for(&[&base, &count_layout, &out]);
let meta = core_types::record::LayoutMeta {
sources: vec![0],
reads: vec![],
element: core_types::record::ElementSpec::Carried,
writes: vec![],
removes: vec![],
level_delta: 1,
};
let repeat = install(
RepeatNode::new(RecordSource::new(IndexSourceNode { layout: base.clone() }, &base, &base), count_edge, &base, &count_layout),
meta,
&[Some(&base)],
);
let leveled = Node::<ContextImpl>::layout(&repeat).clone();
let node = install_flip(SumNode::new(repeat, &leveled), &out);
let GPoll::Final(value) = node.eval(&ctx) else {
panic!("expected a final record");
};
// Every copy evaluates at its own index, so the lanes must be distinct
// storage: sum(0 + 1 + 2 + 3), not four aliases of the last copy.
assert_eq!(unsafe { out.rec(&value).element::<f64>() }, 6.);
}
#[test]
fn layout_meta_folds_to_construction() {
let base = f64_layout(&[]);

View File

@@ -1140,13 +1140,14 @@ mod graphene_test {
reserve_for(&[&li, &ls, &out]);
let erased: Box<ErasedRecordNode> = Box::new(node);
// One u64 word per lane: the uninstalled layout keeps the f64 inline.
let mut scratch = [const { MaybeUninit::uninit() }; 4];
let status = erased.eval_batch(&ctx, 2..6, Some(&mut scratch));
let BatchStatus::Filled(batch, finality) = status else {
panic!("expected filled, got {status:?}");
};
let mut got = Vec::new();
batch.for_each(|_, lane| got.push(unsafe { lane.element::<f64>() }));
batch.share().for_each(|_, lane| got.push(unsafe { lane.element::<f64>() }));
assert_eq!(got, vec![12.0, 13.0, 14.0, 15.0]);
assert_eq!(finality, Finality::AllFinal);
}