Merge pull request #60 from urbit/jon/stack-split-mem-rewrite

split stack
This commit is contained in:
Edward Amsden 2023-08-11 16:59:45 -05:00 committed by GitHub
commit 08690675f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 553 additions and 633 deletions

2
rust/ares/Cargo.lock generated
View File

@ -363,7 +363,7 @@ dependencies = [
[[package]]
name = "murmur3"
version = "0.5.2"
source = "git+https://github.com/tloncorp/murmur3?branch=eamsden/non_copying#dde46823a87f358eee5a928c27e2731f9a53d616"
source = "git+https://github.com/tloncorp/murmur3?rev=7878a0f#7878a0fbecf465720891b625f1a1fc3e19b6a960"
[[package]]
name = "num-derive"

View File

@ -440,21 +440,21 @@ impl<T: Copy> Default for Hamt<T> {
impl<T: Copy + Preserve> Preserve for Hamt<T> {
unsafe fn preserve(&mut self, stack: &mut NockStack) {
if stack.in_frame(self.0.buffer) {
if stack.is_in_frame(self.0.buffer) {
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;
let traversal_stack = stack.struct_alloc::<(Stem<T>, u32)>(6);
*(stack.push::<(Stem<T>, u32)>()) = (self.0, 0);
let mut traversal_depth = 1;
*traversal_stack = (self.0, 0);
'preserve: loop {
if traversal_depth == 0 {
break;
}
let (stem, mut position) = *traversal_stack.add(traversal_depth - 1);
let (stem, mut position) = *(stack.top::<(Stem<T>, u32)>());
// 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;
}
@ -464,7 +464,7 @@ impl<T: Copy + Preserve> Preserve for Hamt<T> {
continue 'preserve_stem;
}
Some((Left(next_stem), idx)) => {
if stack.in_frame(next_stem.buffer) {
if stack.is_in_frame(next_stem.buffer) {
let dest_buffer =
stack.struct_alloc_in_previous_frame(next_stem.size());
copy_nonoverlapping(
@ -479,8 +479,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
(*traversal_stack.add(traversal_depth - 1)).1 = position + 1;
*traversal_stack.add(traversal_depth) = (new_stem, 0);
(*(stack.top::<(Stem<T>, u32)>())).1 = position + 1;
*(stack.push::<(Stem<T>, u32)>()) = (new_stem, 0);
traversal_depth += 1;
continue 'preserve;
} else {
@ -489,7 +489,7 @@ impl<T: Copy + Preserve> Preserve for Hamt<T> {
}
}
Some((Right(leaf), idx)) => {
if stack.in_frame(leaf.buffer) {
if stack.is_in_frame(leaf.buffer) {
let dest_buffer = stack.struct_alloc_in_previous_frame(leaf.len);
copy_nonoverlapping(leaf.buffer, dest_buffer, leaf.len);
let new_leaf = Leaf {

View File

@ -77,7 +77,7 @@ pub fn interpret(
formula: Noun,
) -> Noun {
let mut res = unsafe { DirectAtom::new_unchecked(0).as_atom().as_noun() };
stack.push(1);
stack.frame_push(1);
let mut cache = Hamt::<Noun>::new();
unsafe {
*(stack.local_noun_pointer(0)) = work_to_noun(Done);
@ -89,7 +89,7 @@ pub fn interpret(
Done => {
stack.preserve(&mut cache);
stack.preserve(&mut res);
stack.pop();
stack.frame_pop();
break;
}
NockCellComputeHead => {
@ -106,25 +106,28 @@ pub fn interpret(
NockCellCons => {
let head = *stack.local_noun_pointer(1);
res = Cell::new(stack, head, res).as_noun();
stack.preserve(&mut cache);
stack.preserve(&mut res);
stack.pop();
stack.frame_pop();
}
Nock0Axis => {
if let Ok(atom) = (*(stack.local_noun_pointer(1))).as_atom() {
res = slot(subject, atom.as_bitslice());
stack.preserve(&mut cache);
stack.preserve(&mut res);
stack.pop();
stack.frame_pop();
} else {
panic!("Axis must be atom");
};
}
Nock1Constant => {
res = *(stack.local_noun_pointer(1));
stack.preserve(&mut cache);
stack.preserve(&mut res);
stack.pop();
stack.frame_pop();
}
Nock2ComputeSubject => {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock2ComputeFormula);
@ -145,9 +148,10 @@ pub fn interpret(
}
Nock2RestoreSubject => {
subject = *(stack.local_noun_pointer(2));
stack.preserve(&mut cache);
stack.preserve(&mut res);
stack.pop();
stack.frame_pop();
}
Nock3ComputeChild => {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock3ComputeType);
@ -160,9 +164,10 @@ pub fn interpret(
} else {
DirectAtom::new_unchecked(1).as_atom().as_noun()
};
stack.preserve(&mut cache);
stack.preserve(&mut res);
stack.pop();
stack.frame_pop();
}
Nock4ComputeChild => {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock4Increment);
@ -172,9 +177,10 @@ pub fn interpret(
Nock4Increment => {
if let Ok(atom) = res.as_atom() {
res = inc(stack, atom).as_noun();
stack.preserve(&mut cache);
stack.preserve(&mut res);
stack.pop();
stack.frame_pop();
} else {
panic!("Cannot increment (Nock 4) a cell");
};
@ -197,9 +203,10 @@ pub fn interpret(
} else {
DirectAtom::new_unchecked(1).as_atom().as_noun()
};
stack.preserve(&mut cache);
stack.preserve(&mut res);
stack.pop();
stack.frame_pop();
}
Nock6ComputeTest => {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock6ComputeBranch);
@ -225,7 +232,7 @@ pub fn interpret(
Nock6Done => {
stack.preserve(&mut cache);
stack.preserve(&mut res);
stack.pop();
stack.frame_pop();
}
Nock7ComputeSubject => {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock7ComputeResult);
@ -241,9 +248,10 @@ pub fn interpret(
}
Nock7RestoreSubject => {
subject = *(stack.local_noun_pointer(1));
stack.preserve(&mut cache);
stack.preserve(&mut res);
stack.pop();
stack.frame_pop();
}
Nock8ComputeSubject => {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock8ComputeResult);
@ -259,9 +267,10 @@ pub fn interpret(
}
Nock8RestoreSubject => {
subject = *(stack.local_noun_pointer(1));
stack.preserve(&mut cache);
stack.preserve(&mut res);
stack.pop();
stack.frame_pop();
}
Nock9ComputeCore => {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock9ComputeResult);
@ -280,9 +289,10 @@ pub fn interpret(
}
Nock9RestoreSubject => {
subject = *(stack.local_noun_pointer(2));
stack.preserve(&mut cache);
stack.preserve(&mut res);
stack.pop();
stack.frame_pop();
}
Nock10ComputeTree => {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock10ComputePatch);
@ -299,9 +309,10 @@ pub fn interpret(
if let Ok(edit_axis) = (*stack.local_noun_pointer(1)).as_atom() {
let tree = *stack.local_noun_pointer(3);
res = edit(stack, edit_axis.as_bitslice(), res, tree);
stack.preserve(&mut cache);
stack.preserve(&mut res);
stack.pop();
stack.frame_pop();
} else {
panic!("Axis into tree must be atom");
}
@ -314,9 +325,10 @@ pub fn interpret(
match_pre_hint(stack, newt, subject, hint_cell, formula, &cache)
{
res = found;
stack.preserve(&mut cache);
stack.preserve(&mut res);
stack.pop();
stack.frame_pop();
} else {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock11ComputeResult);
push_formula(stack, hint_cell.tail());
@ -329,9 +341,10 @@ pub fn interpret(
let hint = *stack.local_noun_pointer(1);
if let Ok(found) = match_post_hint(stack, newt, subject, hint, res) {
res = found;
stack.preserve(&mut cache);
stack.preserve(&mut res);
stack.pop();
stack.frame_pop();
} else {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock11Done);
let formula = *stack.local_noun_pointer(2);
@ -341,9 +354,10 @@ pub fn interpret(
Nock11Done => {
let hint = *stack.local_noun_pointer(1);
let _ = match_post_hinted(stack, subject, hint, res, &mut cache);
stack.preserve(&mut cache);
stack.preserve(&mut res);
stack.pop();
stack.frame_pop();
}
};
}
@ -356,7 +370,7 @@ fn push_formula(stack: &mut NockStack, formula: Noun) {
// Formula
match formula_cell.head().as_either_atom_cell() {
Right(_cell) => {
stack.push(3);
stack.frame_push(3);
unsafe {
*(stack.local_noun_pointer(0)) = work_to_noun(NockCellComputeHead);
*(stack.local_noun_pointer(1)) = formula_cell.head();
@ -367,14 +381,14 @@ fn push_formula(stack: &mut NockStack, formula: Noun) {
if let Ok(direct) = atom.as_direct() {
match direct.data() {
0 => {
stack.push(2);
stack.frame_push(2);
unsafe {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock0Axis);
*(stack.local_noun_pointer(1)) = formula_cell.tail();
};
}
1 => {
stack.push(2);
stack.frame_push(2);
unsafe {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock1Constant);
*(stack.local_noun_pointer(1)) = formula_cell.tail();
@ -382,7 +396,7 @@ fn push_formula(stack: &mut NockStack, formula: Noun) {
}
2 => {
if let Ok(arg_cell) = formula_cell.tail().as_cell() {
stack.push(3);
stack.frame_push(3);
unsafe {
*(stack.local_noun_pointer(0)) =
work_to_noun(Nock2ComputeSubject);
@ -394,14 +408,14 @@ fn push_formula(stack: &mut NockStack, formula: Noun) {
};
}
3 => {
stack.push(2);
stack.frame_push(2);
unsafe {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock3ComputeChild);
*(stack.local_noun_pointer(1)) = formula_cell.tail();
};
}
4 => {
stack.push(2);
stack.frame_push(2);
unsafe {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock4ComputeChild);
*(stack.local_noun_pointer(1)) = formula_cell.tail();
@ -409,7 +423,7 @@ fn push_formula(stack: &mut NockStack, formula: Noun) {
}
5 => {
if let Ok(arg_cell) = formula_cell.tail().as_cell() {
stack.push(3);
stack.frame_push(3);
unsafe {
*(stack.local_noun_pointer(0)) =
work_to_noun(Nock5ComputeLeftChild);
@ -423,7 +437,7 @@ fn push_formula(stack: &mut NockStack, formula: Noun) {
6 => {
if let Ok(arg_cell) = formula_cell.tail().as_cell() {
if let Ok(branch_cell) = arg_cell.tail().as_cell() {
stack.push(4);
stack.frame_push(4);
unsafe {
*(stack.local_noun_pointer(0)) =
work_to_noun(Nock6ComputeTest);
@ -440,7 +454,7 @@ fn push_formula(stack: &mut NockStack, formula: Noun) {
}
7 => {
if let Ok(arg_cell) = formula_cell.tail().as_cell() {
stack.push(3);
stack.frame_push(3);
unsafe {
*(stack.local_noun_pointer(0)) =
work_to_noun(Nock7ComputeSubject);
@ -453,7 +467,7 @@ fn push_formula(stack: &mut NockStack, formula: Noun) {
}
8 => {
if let Ok(arg_cell) = formula_cell.tail().as_cell() {
stack.push(3);
stack.frame_push(3);
unsafe {
*(stack.local_noun_pointer(0)) =
work_to_noun(Nock8ComputeSubject);
@ -466,7 +480,7 @@ fn push_formula(stack: &mut NockStack, formula: Noun) {
}
9 => {
if let Ok(arg_cell) = formula_cell.tail().as_cell() {
stack.push(3);
stack.frame_push(3);
unsafe {
*(stack.local_noun_pointer(0)) = work_to_noun(Nock9ComputeCore);
*(stack.local_noun_pointer(1)) = arg_cell.head();
@ -479,7 +493,7 @@ fn push_formula(stack: &mut NockStack, formula: Noun) {
10 => {
if let Ok(arg_cell) = formula_cell.tail().as_cell() {
if let Ok(patch_cell) = arg_cell.head().as_cell() {
stack.push(4);
stack.frame_push(4);
unsafe {
*(stack.local_noun_pointer(0)) =
work_to_noun(Nock10ComputeTree);
@ -496,7 +510,7 @@ fn push_formula(stack: &mut NockStack, formula: Noun) {
}
11 => {
if let Ok(arg_cell) = formula_cell.tail().as_cell() {
stack.push(3);
stack.frame_push(3);
unsafe {
*(stack.local_noun_pointer(0)) =
work_to_noun(if arg_cell.head().is_cell() {

View File

@ -43,7 +43,7 @@ fn main() -> io::Result<()> {
let in_map = Mmap::map(&f)?;
let word_len = (in_len + 7) >> 3;
let (mut atom, dest) = IndirectAtom::new_raw_mut(&mut stack, word_len as usize);
write_bytes(dest.add(word_len as usize - 1), 0, 8);
write_bytes(dest.add(word_len as usize - 1), 0, 1);
copy_nonoverlapping(in_map.as_ptr(), dest as *mut u8, in_len as usize);
mem::drop(in_map);
atom.normalize_as_atom()

File diff suppressed because it is too large Load Diff

View File

@ -120,46 +120,44 @@ pub fn mug_u32(stack: &mut NockStack, noun: Noun) -> u32 {
return mug;
}
assert_acyclic!(noun);
stack.push(1);
unsafe {
stack.save_prev_stack_pointer_to_local(0);
*(stack.alloc_in_previous_frame()) = noun;
*(stack.push()) = noun;
}
loop {
if unsafe { stack.prev_stack_pointer_equals_local(0) } {
if stack.stack_is_empty() {
break;
} else {
let noun: Noun = unsafe { *(stack.top_in_previous_frame()) };
let noun: Noun = unsafe { *(stack.top()) };
match noun.as_either_direct_allocated() {
Left(_direct) => {
unsafe {
stack.reclaim_in_previous_frame::<Noun>();
stack.pop::<Noun>();
}
continue;
} // no point in calculating a direct mug here as we wont cache it
Right(allocated) => match allocated.get_cached_mug() {
Some(_mug) => {
unsafe {
stack.reclaim_in_previous_frame::<Noun>();
stack.pop::<Noun>();
}
continue;
}
None => match allocated.as_either() {
Left(indirect) => unsafe {
set_mug(allocated, calc_atom_mug_u32(indirect.as_atom()));
stack.reclaim_in_previous_frame::<Noun>();
stack.pop::<Noun>();
continue;
},
Right(cell) => unsafe {
match (get_mug(cell.head()), get_mug(cell.tail())) {
(Some(head_mug), Some(tail_mug)) => {
set_mug(allocated, calc_cell_mug_u32(head_mug, tail_mug));
stack.reclaim_in_previous_frame::<Noun>();
stack.pop::<Noun>();
continue;
}
_ => {
*(stack.alloc_in_previous_frame()) = cell.tail();
*(stack.alloc_in_previous_frame()) = cell.head();
*(stack.push()) = cell.tail();
*(stack.push()) = cell.head();
continue;
}
}
@ -169,11 +167,8 @@ pub fn mug_u32(stack: &mut NockStack, noun: Noun) -> u32 {
}
}
}
unsafe {
stack.pop();
get_mug(noun).expect("Noun should have a mug once it is mugged.")
}
}
pub fn mug(stack: &mut NockStack, noun: Noun) -> DirectAtom {
unsafe { DirectAtom::new_unchecked(mug_u32(stack, noun) as u64) }

View File

@ -910,8 +910,8 @@ impl Noun {
/** Produce the size of a noun in the current frame, in words */
pub fn mass_frame(self, stack: &NockStack) -> usize {
unsafe {
let res = self.mass_wind(&|p| stack.in_frame(p));
self.mass_unwind(&|p| stack.in_frame(p));
let res = self.mass_wind(&|p| stack.is_in_frame(p));
self.mass_unwind(&|p| stack.is_in_frame(p));
res
}
}

View File

@ -27,22 +27,21 @@ pub fn cue(stack: &mut NockStack, buffer: Atom) -> Noun {
let buffer_bitslice = buffer.as_bitslice();
let mut cursor: usize = 0;
let backref_map = MutHamt::<Noun>::new(stack);
stack.push(2);
stack.frame_push(1);
unsafe {
stack.save_prev_stack_pointer_to_local(0);
*(stack.alloc_in_previous_frame()) = stack.local_noun_pointer(1);
*(stack.push::<*mut Noun>()) = stack.local_noun_pointer(0);
};
loop {
if unsafe { stack.prev_stack_pointer_equals_local(0) } {
let mut result = unsafe { *(stack.local_noun_pointer(1)) };
if stack.stack_is_empty() {
let mut result = unsafe { *stack.local_noun_pointer(0) };
assert_acyclic!(result);
unsafe {
stack.preserve(&mut result);
stack.pop();
stack.frame_pop();
}
break result;
} else {
let dest_ptr: *mut Noun = unsafe { *(stack.top_in_previous_frame()) };
let dest_ptr: *mut Noun = unsafe { *(stack.top()) };
if buffer_bitslice[cursor] {
// 1 bit
if buffer_bitslice[cursor + 1] {
@ -60,7 +59,7 @@ pub fn cue(stack: &mut NockStack, buffer: Atom) -> Noun {
}
*dest_ptr = reffed_noun;
assert_acyclic!(reffed_noun);
stack.reclaim_in_previous_frame::<*mut Noun>();
stack.pop::<*mut Noun>();
}
continue;
} else {
@ -72,15 +71,13 @@ pub fn cue(stack: &mut NockStack, buffer: Atom) -> Noun {
*dest_ptr = cell.as_noun();
let mut backref_atom = Atom::new(stack, backref as u64).as_noun();
backref_map.insert(stack, &mut backref_atom, *dest_ptr);
stack.reclaim_in_previous_frame::<*mut Noun>();
stack.pop::<*mut Noun>();
(*cell_mem_ptr).tail =
DirectAtom::new_unchecked(0xEDBEEF).as_atom().as_noun();
(*cell_mem_ptr).head =
DirectAtom::new_unchecked(0xDEBEEF).as_atom().as_noun();
*(stack.alloc_in_previous_frame::<*mut Noun>()) =
&mut ((*cell_mem_ptr).tail);
*(stack.alloc_in_previous_frame::<*mut Noun>()) =
&mut ((*cell_mem_ptr).head);
*(stack.push()) = &mut (*cell_mem_ptr).tail;
*(stack.push()) = &mut (*cell_mem_ptr).head;
}
continue;
}
@ -92,7 +89,7 @@ pub fn cue(stack: &mut NockStack, buffer: Atom) -> Noun {
*dest_ptr = rub_atom(stack, &mut cursor, buffer_bitslice).as_noun();
let mut backref_atom = Atom::new(stack, backref as u64).as_noun();
backref_map.insert(stack, &mut backref_atom, *dest_ptr);
stack.reclaim_in_previous_frame::<*mut Noun>();
stack.pop::<*mut Noun>();
};
continue;
}
@ -172,16 +169,14 @@ pub fn jam(stack: &mut NockStack, noun: Noun) -> Atom {
atom,
slice,
};
stack.push(1);
unsafe {
stack.save_prev_stack_pointer_to_local(0);
*(stack.alloc_in_previous_frame()) = noun;
*(stack.push::<Noun>()) = noun;
};
'jam: loop {
if unsafe { stack.prev_stack_pointer_equals_local(0) } {
if stack.stack_is_empty() {
break;
} else {
let mut noun = unsafe { *(stack.top_in_previous_frame::<Noun>()) };
let mut noun = unsafe { *(stack.top::<Noun>()) };
if let Some(backref) = backref_map.lookup(stack, &mut noun) {
match noun.as_either_atom_cell() {
Left(atom) => {
@ -198,7 +193,7 @@ pub fn jam(stack: &mut NockStack, noun: Noun) -> Atom {
}
}
unsafe {
stack.reclaim_in_previous_frame::<Noun>();
stack.pop::<Noun>();
};
continue 'jam;
};
@ -207,28 +202,23 @@ pub fn jam(stack: &mut NockStack, noun: Noun) -> Atom {
Left(atom) => {
jam_atom(stack, &mut state, atom);
unsafe {
stack.reclaim_in_previous_frame::<Noun>();
stack.pop::<Noun>();
};
continue;
}
Right(cell) => {
jam_cell(stack, &mut state);
unsafe {
stack.reclaim_in_previous_frame::<Noun>();
*(stack.alloc_in_previous_frame()) = cell.tail();
*(stack.alloc_in_previous_frame()) = cell.head();
stack.pop::<Noun>();
*(stack.push::<Noun>()) = cell.tail();
*(stack.push::<Noun>()) = cell.head();
};
continue;
}
}
}
}
unsafe {
let mut result = state.atom.normalize_as_atom();
stack.preserve(&mut result);
stack.pop();
result
}
unsafe { state.atom.normalize_as_atom() }
}
fn jam_atom(traversal: &mut NockStack, state: &mut JamState, atom: Atom) {

View File

@ -0,0 +1 @@
аиA╟ь XvАЬa&vЦЙ ╡D6и░и