Skip to content

Commit

Permalink
WIP: add mean stack and %spot hint
Browse files Browse the repository at this point in the history
  • Loading branch information
ashelkovnykov committed Jun 22, 2023
1 parent 37d1a73 commit 8e37c6b
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 56 deletions.
23 changes: 17 additions & 6 deletions rust/ares/src/interpreter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,14 @@ pub fn interpret(
formula: Noun,
) -> Noun {
let mut res = unsafe { DirectAtom::new_unchecked(0).as_atom().as_noun() };
stack.push(1);
let mut cache = Hamt::<Noun>::new();

stack.push(1);
unsafe {
*(stack.local_noun_pointer(0)) = work_to_noun(Done);
}
push_formula(stack, formula);

assert_no_alloc(|| unsafe {
loop {
match noun_to_work(*(stack.local_noun_pointer(0))) {
Expand Down Expand Up @@ -697,11 +699,15 @@ fn match_hint_pre_nock(
} else {
println!("raw slog: {} {}", pri, tank);
}

None
}
_ => None,
tas!(b"spot") => {
let trace = Cell::new(stack, tag.as_noun(), res).as_noun();
stack.trace_push(trace);
}
_ => {}
}

None
}

/** Match static and dynamic hints after the nock formula is evaluated */
Expand All @@ -721,8 +727,13 @@ fn match_hint_post_nock(
let formula = unsafe { *stack.local_noun_pointer(2) };
let mut key = Cell::new(stack, subject, formula).as_noun();
*cache = cache.insert(stack, &mut key, res);
None
}
_ => None,
tas!(b"spot") => {
// In the future, we should only do this if 11 is not in tail position
stack.trace_pop();
}
_ => {}
}

None
}
93 changes: 43 additions & 50 deletions rust/ares/src/mem.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::assert_acyclic;
use crate::noun::{Atom, Cell, CellMemory, IndirectAtom, Noun, NounAllocator};
use crate::noun::{Atom, Cell, CellMemory, IndirectAtom, Noun, NounAllocator, DirectAtom};
use crate::snapshot::pma::{pma_in_arena, pma_malloc};
use either::Either::{self, Left, Right};
use ibig::Stack;
Expand Down Expand Up @@ -32,6 +32,9 @@ pub enum Polarity {
West,
}

/** Number of reserved slots per stack frame */
const FRAME_SLOTS: usize = 3;

/* XX
* ~master-morzod suggests splitting stack frames:
* when FP-relative slots are on the west stack, allocate on the east stack, and vice versa.
Expand Down Expand Up @@ -81,29 +84,34 @@ pub struct NockStack {
stack_pointer: *mut u64,
/** Base pointer for the current stack frame. Accesses to slots are computed from this base. */
frame_pointer: *mut u64,
/** */
mean_pointer: *mut Noun,
/** MMap which must be kept alive as long as this NockStack is */
memory: MmapMut,
}

impl NockStack {
/** Size is in 64 bit words.
/** size is in 64-bit (i.e. 8-byte) words.
* top_slots is how many slots to allocate to the top stack frame.
*/
pub fn new(size: usize, top_slots: usize) -> NockStack {
let mut memory = MmapMut::map_anon(size << 3).expect("Mapping memory for nockstack failed");
let start = memory.as_ptr() as *const u64;
let frame_pointer = memory.as_mut_ptr() as *mut u64;
let stack_pointer = unsafe { frame_pointer.add(top_slots + 2) };
let stack_pointer = unsafe { frame_pointer.add(top_slots + FRAME_SLOTS) };
let mean_pointer = unsafe { frame_pointer.add(2) } as *mut Noun;
unsafe {
*frame_pointer = frame_pointer.add(size) as u64;
*frame_pointer.add(1) = ptr::null::<u64>() as u64;
*mean_pointer = DirectAtom::new_unchecked(0).as_atom().as_noun();
};
NockStack {
start,
size,
polarity: Polarity::West,
stack_pointer,
frame_pointer,
mean_pointer,
memory,
}
}
Expand Down Expand Up @@ -142,62 +150,21 @@ impl NockStack {

/** Pointer to a local slot typed as Noun */
pub unsafe fn local_noun_pointer(&mut self, local: usize) -> *mut Noun {
self.slot_pointer(local + 2) as *mut Noun
}

/** Save the stack pointer for the previous frame in a slot of an east frame */
unsafe fn save_prev_stack_pointer_to_local_east(&mut self, local: usize) {
*(self.slot_pointer_east(local + 2) as *mut *mut u64) =
*(self.previous_stack_pointer_pointer_east())
}

/** Save the stack pointer for the previous frame in a slot of a west frame */
unsafe fn save_prev_stack_pointer_to_local_west(&mut self, local: usize) {
*(self.slot_pointer_west(local + 2) as *mut *mut u64) =
*(self.previous_stack_pointer_pointer_west())
self.slot_pointer(local + FRAME_SLOTS) as *mut Noun
}

/** Save the stack pointer for the previous frame in a slot */
pub unsafe fn save_prev_stack_pointer_to_local(&mut self, local: usize) {
match &self.polarity {
Polarity::East => self.save_prev_stack_pointer_to_local_east(local),
Polarity::West => self.save_prev_stack_pointer_to_local_west(local),
}
}

unsafe fn restore_prev_stack_pointer_from_local_east(&mut self, local: usize) {
*(self.previous_stack_pointer_pointer_east()) =
*(self.slot_pointer_east(local + 2) as *mut *mut u64);
}

unsafe fn restore_prev_stack_pointer_from_local_west(&mut self, local: usize) {
*(self.previous_stack_pointer_pointer_west()) =
*(self.slot_pointer_west(local + 2) as *mut *mut u64);
*(self.local_noun_pointer(local) as *mut *mut u64) = *(self.previous_stack_pointer_pointer());
}

unsafe fn restore_prev_stack_pointer_from_local(&mut self, local: usize) {
match &self.polarity {
Polarity::East => self.restore_prev_stack_pointer_from_local_east(local),
Polarity::West => self.restore_prev_stack_pointer_from_local_west(local),
}
}

unsafe fn prev_stack_pointer_equals_local_east(&mut self, local: usize) -> bool {
*(self.slot_pointer_east(local + 2) as *const *mut u64)
== *(self.previous_stack_pointer_pointer_east())
}

unsafe fn prev_stack_pointer_equals_local_west(&mut self, local: usize) -> bool {
*(self.slot_pointer_west(local + 2) as *const *mut u64)
== *(self.previous_stack_pointer_pointer_west())
*(self.previous_stack_pointer_pointer()) = *(self.local_noun_pointer(local) as *mut *mut u64);
}

/** Test the stack pointer for the previous frame against a slot */
pub unsafe fn prev_stack_pointer_equals_local(&mut self, local: usize) -> bool {
match &self.polarity {
Polarity::East => self.prev_stack_pointer_equals_local_east(local),
Polarity::West => self.prev_stack_pointer_equals_local_west(local),
}
*(self.local_noun_pointer(local) as *mut *mut u64) == *(self.previous_stack_pointer_pointer())
}

unsafe fn alloc_in_previous_frame_west<T>(&mut self) -> *mut T {
Expand Down Expand Up @@ -298,6 +265,14 @@ impl NockStack {
self.slot_pointer_west(0) as *mut *mut u64
}

/** Pointer to where the previous (east) stack pointer is saved */
unsafe fn previous_stack_pointer_pointer(&mut self) -> *mut *mut u64 {
match self.polarity {
Polarity::East => self.previous_stack_pointer_pointer_east(),
Polarity::West => self.previous_stack_pointer_pointer_west(),
}
}

/** Pointer to where the previous (west) frame pointer is saved in an east frame */
unsafe fn previous_frame_pointer_pointer_east(&mut self) -> *mut *mut u64 {
self.slot_pointer_east(1) as *mut *mut u64
Expand Down Expand Up @@ -702,8 +677,10 @@ impl NockStack {
let previous_stack_pointer: *mut u64 = *self.previous_stack_pointer_pointer_east();
*previous_stack_pointer = self.stack_pointer as u64;
*(previous_stack_pointer.add(1)) = self.frame_pointer as u64;
self.stack_pointer = previous_stack_pointer.add(num_locals + 2);
*(previous_stack_pointer.add(2)) = self.mean_pointer as u64;
self.stack_pointer = previous_stack_pointer.add(num_locals + FRAME_SLOTS);
self.frame_pointer = previous_stack_pointer;
self.mean_pointer = previous_stack_pointer.add(2) as *mut Noun;
self.polarity = Polarity::West;
}

Expand All @@ -716,8 +693,10 @@ impl NockStack {
let previous_stack_pointer: *mut u64 = *self.previous_stack_pointer_pointer_west();
*(previous_stack_pointer.sub(1)) = self.stack_pointer as u64;
*(previous_stack_pointer.sub(2)) = self.frame_pointer as u64;
self.stack_pointer = previous_stack_pointer.sub(num_locals + 2);
*(previous_stack_pointer.sub(3)) = self.mean_pointer as u64;
self.stack_pointer = previous_stack_pointer.sub(num_locals + FRAME_SLOTS);
self.frame_pointer = previous_stack_pointer;
self.mean_pointer = previous_stack_pointer.sub(3) as *mut Noun;
self.polarity = Polarity::East;
}

Expand All @@ -730,6 +709,20 @@ impl NockStack {
}
}
}

/** Push onto the mean stack (for tracing) */
pub fn trace_push(&mut self, mon: Noun) {
unsafe {
*(self.mean_pointer) = Cell::new(self, mon, *self.mean_pointer).as_noun();
}
}

/** Pop from the mean stack (for tracing) */
pub fn trace_pop(&mut self) {
unsafe {
*(self.mean_pointer) = (*self.mean_pointer).as_cell().expect("mean stack should be non-null when popped").tail();
}
}
}

/** Unifying equality compares nouns for equality structurally. It *unifies* noun representations
Expand Down

0 comments on commit 8e37c6b

Please sign in to comment.