From 5d30719fa245a9afe1a9a9d3f40448107de2ad80 Mon Sep 17 00:00:00 2001 From: Alek Ratzloff Date: Mon, 17 Jan 2022 19:15:22 -0800 Subject: [PATCH] Remove Obj and Arena These weren't being used and they didn't have very good implementations. Movin' on up Signed-off-by: Alek Ratzloff --- src/object.rs | 323 ---------------------------------------------- src/vm/machine.rs | 10 +- 2 files changed, 1 insertion(+), 332 deletions(-) diff --git a/src/object.rs b/src/object.rs index 89730e5..e992dbe 100644 --- a/src/object.rs +++ b/src/object.rs @@ -172,326 +172,3 @@ impl Debug for BuiltinFn { ) } } - -// ///////////////////////////////////////////////////////////////////////////// -// Obj -// ///////////////////////////////////////////////////////////////////////////// - -#[derive(Debug, Clone)] -pub struct ObjPtr { - arena: Weak>, - slot: usize, -} - -impl ObjPtr { - pub fn slot(&self) -> usize { - self.slot - } -} - -#[derive(Debug, Default)] -pub struct Obj { - vtable: VTable, -} - -impl Obj { - pub fn new(vtable: VTable) -> Self { - Self { vtable } - } - - pub fn vtable(&self) -> &VTable { - &self.vtable - } - - pub fn vtable_mut(&mut self) -> &mut VTable { - &mut self.vtable - } -} - -// ///////////////////////////////////////////////////////////////////////////// -// Arena -// ///////////////////////////////////////////////////////////////////////////// - -#[derive(Debug)] -pub struct Arena { - slots: Vec, - slots_dirty: bool, - objects: BTreeMap, - max_size: Option, -} - -impl Arena { - pub fn new(max_size: Option) -> Self { - Arena { - slots: vec![SlotRange::Open(0)], - slots_dirty: false, - objects: Default::default(), - max_size, - } - } - - /// Compress the slots in the arena. - /// - /// This will: - /// 1. Sort all slots by their starting position, - /// 2. Merge all slots where necessary. - pub fn compress_slots(&mut self) { - use SlotRange::*; - self.slots.sort_by(|a, b| match (a, b) { - (Range(s1, _), Range(s2, _)) => s1.cmp(s2), - (Open(o1), Open(o2)) => o1.cmp(o2), - (Range(_, _), Open(_)) => std::cmp::Ordering::Less, - (Open(_), Range(_, _)) => std::cmp::Ordering::Greater, - }); - let mut slots: Vec = Vec::with_capacity(self.slots.len()); - for slot in &self.slots { - match slot { - // Remove invalid slots - Range(start, end) if start > end => continue, - _ => {} - } - if let Some(last) = slots.last().copied() { - if let Some(merged) = last.try_merge(slot) { - slots.pop(); - slots.push(merged); - } else { - slots.push(*slot); - } - } else { - slots.push(*slot); - } - } - self.slots = slots; - // Make sure to indicate that slots available are not dirty. - self.slots_dirty = false; - } - - /// Creates a shared pointer for an Obj value, using the next available slot. - /// - /// If no slot is available, None is returned. - pub fn alloc_obj(self_rc: &Rc>, obj: Obj) -> Option { - use SlotRange::*; - - let mut self_mut = self_rc - .try_borrow_mut() - .expect("could not get arena mutably from Rc pointer"); - // Compress if necessary - if self_mut.slots_dirty { - self_mut.compress_slots(); - } - if self_mut - .max_size - .map(|max_size| self_mut.objects.len() >= max_size) - .unwrap_or(false) - { - // TODO : return err instead of option - // Could not allocate a new object because of configuration - return None; - } - - // Get the next slot - let slots = &mut self_mut.slots; - let slot = match slots.first().copied().unwrap() { - Range(start, end) => { - if start == end { - slots.remove(0); - } else { - slots[0] = Range(start + 1, end); - } - start - } - Open(index) => { - slots[0] = Open(index + 1); - index - } - }; - let previous = self_mut.objects.insert(slot, obj); - assert!( - previous.is_none(), - "slot {} was allocated but is already in use", - slot - ); - Some(ObjPtr { - arena: Rc::downgrade(self_rc), - slot, - }) - } - - pub fn free_obj(&mut self, obj_ptr: ObjPtr) { - // Compress if necessary - if self.slots_dirty { - self.compress_slots(); - } - let value = self.objects.remove(&obj_ptr.slot); - assert!( - value.is_some(), - "attempted to free object that was not tracked (slot {})", - obj_ptr.slot - ); - self.slots - .push(SlotRange::Range(obj_ptr.slot, obj_ptr.slot)); - self.slots_dirty = true; // not my problem - } -} - -// ///////////////////////////////////////////////////////////////////////////// -// Slots -// ///////////////////////////////////////////////////////////////////////////// - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum SlotRange { - /// A list of slots that are in a range, exclusive. - /// - /// If the range start and end are equal, then it is a single opening. - Range(usize, usize), - /// Everything from here and onward is open. - Open(usize), -} - -impl SlotRange { - /// Try to merge this range with another range. - /// - /// If these ranges don't overlap one another, then None is returned. - /// - /// If a range is open, while the other is closed, the open range will take - /// precedent over the closed range. - /// - /// If both ranges are open, the smaller range is given precedent. - pub fn try_merge(&self, other: &SlotRange) -> Option { - use SlotRange::*; - match (self, other) { - (Range(s1, e1), Range(s2, e2)) if (e1 + 1) >= *s2 => { - let start = s1.min(s2); - let end = e1.max(e2); - Some(Range(*start, *end)) - } - (Range(s, e), Open(o)) | (Open(o), Range(s, e)) => { - if s <= o && (e + 1) >= *o { - Some(Open(*s)) - } else if s >= o { - Some(Open(*o)) - } else { - None - } - } - (Open(o1), Open(o2)) => Some(Open(*o1.min(o2))), - _ => None, - } - } -} - -#[test] -fn test_slot_range_merge() { - use SlotRange::*; - let tests = [ - (Range(0, 4), Range(0, 5), Some(Range(0, 5))), - (Range(1, 4), Range(0, 5), Some(Range(0, 5))), - (Range(0, 4), Range(1, 5), Some(Range(0, 5))), - // - (Range(0, 5), Range(0, 3), Some(Range(0, 5))), - (Range(0, 5), Range(1, 3), Some(Range(0, 5))), - (Range(1, 5), Range(0, 4), Some(Range(0, 5))), - // - (Range(0, 4), Open(4), Some(Open(0))), - (Range(1, 4), Open(4), Some(Open(1))), - (Range(2, 4), Open(4), Some(Open(2))), - // - (Range(0, 3), Range(4, 4), Some(Range(0, 4))), - (Range(0, 4), Range(6, 6), None), - // - (Range(0, 4), Range(2, 2), Some(Range(0, 4))), - ]; - - for (a, b, expected) in tests { - assert_eq!( - a.try_merge(&b), - expected, - "expected merge of {:?} and {:?} to be {:?}", - a, - b, - expected - ); - } -} - -#[test] -fn test_arena_compress_slots() { - use SlotRange::*; - let tests = [ - (vec![Range(0, 4), Range(2, 6), Open(0)], vec![Open(0)]), - (vec![Open(7), Range(0, 4), Range(2, 6)], vec![Open(0)]), - ( - vec![Open(8), Range(0, 4), Range(2, 6)], - vec![Range(0, 6), Open(8)], - ), - (vec![Range(0, 4), Range(2, 6)], vec![Range(0, 6)]), - (vec![Range(0, 4), Range(2, 6)], vec![Range(0, 6)]), - ( - vec![Range(0, 1), Range(2, 2), Range(3, 4)], - vec![Range(0, 4)], - ), - ( - vec![Range(0, 4), Range(3, 4), Range(2, 2)], - vec![Range(0, 4)], - ), - ( - vec![Range(3, 6), Range(0, 4), Range(2, 2)], - vec![Range(0, 6)], - ), - (vec![Range(0, 6), Range(6, 6)], vec![Range(0, 6)]), - (vec![Range(7, 6), Range(6, 6)], vec![Range(6, 6)]), - ( - vec![Range(0, 0), Range(1, 1), Range(2, 2)], - vec![Range(0, 2)], - ), - ( - vec![Range(0, 0), Range(1, 1), Range(2, 2), Open(3)], - vec![Open(0)], - ), - ]; - - for (slots, expected) in tests { - let mut arena = Arena { - slots, - slots_dirty: true, - objects: Default::default(), - max_size: None, - }; - arena.compress_slots(); - assert_eq!(arena.slots, expected); - } -} - -#[test] -fn test_arena_obj_lifetime() { - let arena = Rc::new(RefCell::new(Arena::new(None))); - - let p1 = Arena::alloc_obj(&arena, Obj::default()).unwrap(); - assert_eq!(arena.borrow().slots, vec![SlotRange::Open(1)]); - let p2 = Arena::alloc_obj(&arena, Obj::default()).unwrap(); - assert_eq!(arena.borrow().slots, vec![SlotRange::Open(2)]); - let p3 = Arena::alloc_obj(&arena, Obj::default()).unwrap(); - assert_eq!(arena.borrow().slots, vec![SlotRange::Open(3)]); - - { - let mut arena_mut = arena.borrow_mut(); - arena_mut.free_obj(p2); - arena_mut.compress_slots(); - assert_eq!( - arena_mut.slots, - vec![SlotRange::Range(1, 1), SlotRange::Open(3)] - ); - } - - let p4 = Arena::alloc_obj(&arena, Obj::default()).unwrap(); - assert_eq!(arena.borrow().slots, vec![SlotRange::Open(3)]); - - { - let mut arena_mut = arena.borrow_mut(); - arena_mut.free_obj(p1); - arena_mut.free_obj(p3); - arena_mut.free_obj(p4); - arena_mut.compress_slots(); - assert_eq!(arena_mut.slots, vec![SlotRange::Open(0)],); - } -} diff --git a/src/vm/machine.rs b/src/vm/machine.rs index ff1e6ca..8669cfa 100644 --- a/src/vm/machine.rs +++ b/src/vm/machine.rs @@ -67,7 +67,6 @@ pub struct Machine { globals: BTreeMap, stack: Vec, max_stack_size: Option, - _arena: Rc>, quote_table: QuoteTable, scope_stack: ScopeStack, call_stack: Vec, @@ -77,14 +76,12 @@ impl Machine { pub fn new( globals: BTreeMap, max_stack_size: Option, - arena: Arena, scope_stack: ScopeStack, ) -> Self { Machine { globals, stack: Default::default(), max_stack_size, - _arena: Rc::new(RefCell::new(arena)), quote_table: Default::default(), scope_stack, call_stack: Default::default(), @@ -354,11 +351,6 @@ impl MachineBuilder { pub fn finish(mut self) -> Machine { self.register_builtins(); - Machine::new( - self.globals, - self.max_stack_size, - Arena::new(self.max_arena_objects), - self.scope_stack, - ) + Machine::new(self.globals, self.max_stack_size, self.scope_stack) } }