Merge branch 'status' into ctrlc

This commit is contained in:
Alex Shelkovnykov 2023-10-04 13:09:18 -06:00
commit 2d1296c258
5 changed files with 94 additions and 60 deletions

View File

@ -12,6 +12,8 @@ edition = "2018"
[dependencies]
ares_macros = { path = "../ares_macros" }
assert_no_alloc = "1.1.2"
# use this when debugging requires allocation (e.g. eprintln)
# assert_no_alloc = {version="1.1.2", features=["warn_debug"]}
bitvec = "1.0.0"
criterion = "0.4"
either = "1.9.0"

View File

@ -14,6 +14,11 @@ use std::ptr::copy_nonoverlapping;
use std::ptr::write_bytes;
fn main() -> io::Result<()> {
// eprintln!("serf: pid {}", std::process::id());
// if unsafe { libc::kill(std::process::id() as i32, libc::SIGSTOP) } != 0 {
// panic!("Could not stop ourselves.");
// };
let filename = env::args().nth(1).expect("Must provide input filename");
if filename == "see gdb! definition in lib.rs about this" {

View File

@ -70,9 +70,9 @@ impl NockStack {
let stack_pointer = frame_pointer;
let alloc_pointer = unsafe { start.add(size) } as *mut u64;
unsafe {
*frame_pointer.sub(1) = ptr::null::<u64>() as u64; // "frame pointer" from "previous" frame
*frame_pointer.sub(FRAME + 1) = ptr::null::<u64>() as u64; // "frame pointer" from "previous" frame
*frame_pointer.sub(STACK + 1) = ptr::null::<u64>() as u64; // "stack pointer" from "previous" frame
*frame_pointer.sub(ALLOC + 1) = start as u64; // "alloc pointer" from "previous" frame
*frame_pointer.sub(ALLOC + 1) = ptr::null::<u64>() as u64; // "alloc pointer" from "previous" frame
};
NockStack {
start,
@ -751,8 +751,8 @@ pub unsafe fn unifying_equality(stack: &mut NockStack, a: *mut Noun, b: *mut Nou
}
}
(Right(x_cell), Right(y_cell)) => {
let x_as_ptr = x_cell.to_raw_pointer();
let y_as_ptr = y_cell.to_raw_pointer();
let x_as_ptr = x_cell.to_raw_pointer() as *const u64;
let y_as_ptr = y_cell.to_raw_pointer() as *const u64;
if x_cell.head().raw_equals(y_cell.head())
&& x_cell.tail().raw_equals(y_cell.tail())
{
@ -793,70 +793,87 @@ pub unsafe fn unifying_equality(stack: &mut NockStack, a: *mut Noun, b: *mut Nou
(*a).raw_equals(*b)
}
unsafe fn senior_pointer_first<T>(
unsafe fn senior_pointer_first(
stack: &NockStack,
a: *const T,
b: *const T,
) -> (*const T, *const T) {
let mut frame_pointer = stack.frame_pointer as *const u64;
let mut stack_pointer = stack.stack_pointer as *const u64;
let mut alloc_pointer = stack.alloc_pointer as *const u64;
let prev_stack_pointer = *(stack.prev_stack_pointer_pointer()) as *const u64;
a: *const u64,
b: *const u64,
) -> (*const u64, *const u64) {
let mut frame_pointer: *const u64 = stack.frame_pointer;
let mut stack_pointer: *const u64 = stack.stack_pointer;
let mut alloc_pointer: *const u64 = stack.alloc_pointer;
let prev_stack_pointer = *(stack.prev_stack_pointer_pointer());
let (mut high_pointer, mut low_pointer) = if stack.is_west() {
(
prev_stack_pointer as *const T,
(stack.alloc_pointer as *const T),
)
let (mut high_pointer, mut low_pointer): (*const u64, *const u64) = if stack.is_west() {
(prev_stack_pointer, alloc_pointer)
} else {
(
stack.alloc_pointer as *const T,
prev_stack_pointer as *const T,
)
(alloc_pointer, prev_stack_pointer)
};
loop {
if low_pointer.is_null() || high_pointer.is_null() {
// we found the bottom of the stack; check entirety of the stack
low_pointer = stack.start;
high_pointer = stack.start.add(stack.size);
}
match (
a < high_pointer && a >= low_pointer,
b < high_pointer && b >= low_pointer,
) {
(true, true) => break (a, b), // both pointers are in the same frame, pick arbitrarily
(true, true) => {
// both pointers are in the same frame, pick arbitrarily (lower in mem)
break lower_pointer_first(a, b);
}
(true, false) => break (b, a), // a is in the frame, b is not, so b is senior
(false, true) => break (a, b), // b is in the frame, a is not, so a is senior
(false, false) => {
// chase up the stack
#[allow(clippy::comparison_chain)]
if frame_pointer.is_null() {
// we found the top of the stack
break (a, b); // both are in the bottom frame, pick arbitrarily
// test to see if the frame under consideration is a west frame
if stack_pointer < alloc_pointer {
stack_pointer = *(frame_pointer.sub(STACK + 1)) as *const u64;
alloc_pointer = *(frame_pointer.sub(ALLOC + 1)) as *const u64;
frame_pointer = *(frame_pointer.sub(FRAME + 1)) as *const u64;
// both pointers are in the PMA, pick arbitrarily (lower in mem)
if frame_pointer.is_null() {
break lower_pointer_first(a, b);
};
// previous allocation pointer
high_pointer = alloc_pointer;
// "previous previous" stack pointer. this is the other boundary of the previous allocation arena
low_pointer = *(frame_pointer.add(STACK)) as *const u64;
} else if stack_pointer > alloc_pointer {
stack_pointer = *(frame_pointer.add(STACK)) as *const u64;
alloc_pointer = *(frame_pointer.add(ALLOC)) as *const u64;
frame_pointer = *(frame_pointer.add(FRAME)) as *const u64;
// both pointers are in the PMA, pick arbitrarily (lower in mem)
if frame_pointer.is_null() {
break lower_pointer_first(a, b);
};
// previous allocation pointer
low_pointer = alloc_pointer;
// "previous previous" stack pointer. this is the other boundary of the previous allocation arena
high_pointer = *(frame_pointer.sub(STACK + 1)) as *const u64;
} else {
// test to see if the frame under consideration is a west frame
if stack_pointer < alloc_pointer {
stack_pointer = *(frame_pointer.sub(STACK + 1)) as *const u64;
alloc_pointer = *(frame_pointer.sub(ALLOC + 1)) as *const u64;
frame_pointer = *(frame_pointer.sub(FRAME + 1)) as *const u64;
// previous allocation pointer
high_pointer = alloc_pointer as *const T;
// "previous previous" stack pointer. this is the other boundary of the previous allocation arena
low_pointer = (frame_pointer.add(STACK)) as *const T;
continue;
} else if stack_pointer > alloc_pointer {
stack_pointer = *(frame_pointer.add(STACK)) as *const u64;
alloc_pointer = *(frame_pointer.add(ALLOC)) as *const u64;
frame_pointer = *(frame_pointer.add(FRAME)) as *const u64;
// previous allocation pointer
low_pointer = alloc_pointer as *const T;
// "previous previous" stack pointer. this is the other boundary of the previous allocation arena
high_pointer = (frame_pointer.sub(STACK + 1)) as *const T;
} else {
panic!("senior_pointer_first: stack_pointer == alloc_pointer");
}
panic!("senior_pointer_first: stack_pointer == alloc_pointer");
}
}
}
}
}
fn lower_pointer_first(a: *const u64, b: *const u64) -> (*const u64, *const u64) {
if a < b {
(a, b)
} else {
(b, a)
}
}
impl NounAllocator for NockStack {
unsafe fn alloc_indirect(&mut self, words: usize) -> *mut u64 {
self.indirect_alloc(words)

View File

@ -186,6 +186,11 @@ impl DirectAtom {
pub fn as_bitslice_mut(&mut self) -> &mut BitSlice<u64, Lsb0> {
BitSlice::from_element_mut(&mut self.0)
}
pub fn as_bytes(&self) -> &[u8] {
let bytes: &[u8; 8] = unsafe { std::mem::transmute(self.0) };
&bytes[..]
}
}
impl fmt::Display for DirectAtom {
@ -231,7 +236,6 @@ pub fn T<A: NounAllocator>(allocator: &mut A, tup: &[Noun]) -> Noun {
pub fn tape<A: NounAllocator>(allocator: &mut A, text: &str) -> Noun {
// XX: Needs unit tests
let mut res = D(0);
// XX: Switch to using Cell::new_raw_mut
for c in text.bytes().rev() {
res = T(allocator, &[D(c as u64), res])
}
@ -593,6 +597,7 @@ impl Slots for Cell {}
impl private::RawSlots for Cell {
fn raw_slot(&self, axis: &BitSlice<u64, Lsb0>) -> Result<Noun> {
let mut noun: Noun = self.as_noun();
// Panic because all of the logic to guard against this is in Noun::RawSlots, Noun::Slots
let mut cursor = axis.last_one().expect("raw_slow somehow by-passed 0 check");
while cursor != 0 {
@ -761,6 +766,14 @@ impl Atom {
pub fn as_noun(self) -> Noun {
Noun { atom: self }
}
pub fn as_bytes(&self) -> &[u8] {
if self.is_direct() {
unsafe { self.direct.as_bytes() }
} else {
unsafe { self.indirect.as_bytes() }
}
}
}
impl fmt::Display for Atom {
@ -1092,7 +1105,14 @@ impl private::RawSlots for Noun {
fn raw_slot(&self, axis: &BitSlice<u64, Lsb0>) -> Result<Noun> {
match self.as_either_atom_cell() {
Right(cell) => cell.raw_slot(axis),
Left(_atom) => Err(Error::NotCell), // Axis tried to descend through atom
Left(_atom) => {
if axis.last_one() == Some(0) {
Ok(*self)
} else {
// Axis tried to descend through atom
Err(Error::NotCell)
}
}
}
}
}
@ -1132,17 +1152,7 @@ pub trait Slots: private::RawSlots {
* Retrieve component Noun at axis given as Atom, or fail with descriptive error
*/
fn slot_atom(&self, atom: Atom) -> Result<Noun> {
atom.as_either().either(
|d| self.slot(d.data()),
|i| {
if unsafe { i.as_noun().raw_equals(D(0)) } {
// 0 is not allowed as an axis
Err(Error::NotRepresentable)
} else {
self.raw_slot(i.as_bitslice())
}
},
)
self.raw_slot(atom.as_bitslice())
}
}

View File

@ -78,7 +78,7 @@ impl DoubleJam {
| ((*in_ptr.add(1) as u32) << 8)
| ((*in_ptr.add(2) as u32) << 16)
| ((*in_ptr.add(3) as u32) << 24);
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_ptr.add(8), dest as *mut u8, in_len as usize);
mem::drop(in_map);
state.normalize(); // know it's not direct because first word is event number