hamt: preserve traversal_stack uses rust stack

this was using the lightweight stack, but this presented the following
issue: NockStack::copy() can be called during the Hamt::preserve() call,
and the lightweight stack may not be empty. NockStack::copy() presumes
that the lightweight stack is empty when it is called, and thus tried to
pop elements that preserve() had pushed onto it.

NockStack::copy() should probably assert that the lightweight stack is
empty when its called
This commit is contained in:
Jonathan Paprocki 2023-09-13 13:23:05 -04:00
parent 21a13ee444
commit 2bfe5a06c6

View File

@ -437,17 +437,26 @@ impl<T: Copy + Preserve> Preserve for Hamt<T> {
let dest_buffer = stack.struct_alloc_in_previous_frame(self.0.size());
copy_nonoverlapping(self.0.buffer, dest_buffer, self.0.size());
self.0.buffer = dest_buffer;
*(stack.push::<(Stem<T>, u32)>()) = (self.0, 0);
// Here we're using the Rust stack since the array is a fixed
// size. Thus it will be cleaned up if the Rust thread running
// this is killed, and is therefore not an issue vs. if it were allocated
// on the heap.
//
// In the past, this traversal stack was allocated in NockStack, but
// exactly the right way to do this is less clear with the split stack.
let mut traversal_stack: [Option<(Stem<T>, u32)>; 6] = [None; 6];
traversal_stack[0] = Some((self.0, 0));
let mut traversal_depth = 1;
'preserve: loop {
if traversal_depth == 0 {
break;
}
let (stem, mut position) = *(stack.top::<(Stem<T>, u32)>());
let Some((stem, mut position)) = traversal_stack[traversal_depth - 1] else {
panic!("Attempted to access uninitialized array element");
};
// can we loop over the size and count leading 0s remaining in the bitmap?
'preserve_stem: loop {
if position >= 32 {
stack.pop::<(Stem<T>, u32)>();
traversal_depth -= 1;
continue 'preserve;
}
@ -472,8 +481,8 @@ impl<T: Copy + Preserve> Preserve for Hamt<T> {
};
*(stem.buffer.add(idx) as *mut Entry<T>) = Entry { stem: new_stem };
assert!(traversal_depth <= 5); // will increment
(*(stack.top::<(Stem<T>, u32)>())).1 = position + 1;
*(stack.push::<(Stem<T>, u32)>()) = (new_stem, 0);
traversal_stack[traversal_depth - 1].unwrap().1 = position + 1;
traversal_stack[traversal_depth] = Some((new_stem, 0));
traversal_depth += 1;
continue 'preserve;
} else {