Require an explicit drop call on a gc allocation

This commit is contained in:
bad 2022-09-16 23:27:49 +02:00
parent 2f690250ae
commit 8c95fcbd85
3 changed files with 24 additions and 15 deletions

View file

@ -30,8 +30,14 @@ impl GCAllocator {
root.trace(&mut tracer); root.trace(&mut tracer);
// And sweep // And sweep
self.allocations let inaccessible = self
.allocations
.drain_filter(|a| !tracer.is_accessible(a.ptr)); .drain_filter(|a| !tracer.is_accessible(a.ptr));
// And sweep
for mut to_free in inaccessible {
to_free.drop();
}
} }
// Specialization when ;-; // Specialization when ;-;
@ -46,9 +52,14 @@ impl GCAllocator {
tracer.mark_reachable_rec(root); tracer.mark_reachable_rec(root);
root.trace(&mut tracer); root.trace(&mut tracer);
// And sweep let inaccessible = self
self.allocations .allocations
.drain_filter(|a| !tracer.is_accessible(a.ptr)); .drain_filter(|a| !tracer.is_accessible(a.ptr));
// And sweep
for mut to_free in inaccessible {
to_free.drop();
}
} }
} }
@ -68,9 +79,7 @@ impl Allocation {
Self { ptr, drop } Self { ptr, drop }
} }
}
impl Drop for Allocation {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { (self.drop)(self.ptr) }; unsafe { (self.drop)(self.ptr) };
} }

View file

@ -13,9 +13,7 @@ pub mod test_utils;
pub(crate) mod tests { pub(crate) mod tests {
use super::allocator::GCAllocator; use super::allocator::GCAllocator;
use super::gc_ref::GcRef;
use super::test_utils::GotDropped; use super::test_utils::GotDropped;
use super::trace::GCTrace;
#[test] #[test]
fn gc_allocates_and_frees_structs() { fn gc_allocates_and_frees_structs() {

View file

@ -20,10 +20,10 @@ impl Environment {
pub fn update_var(&mut self, name: &str, v: Primitive) -> Option<Primitive> { pub fn update_var(&mut self, name: &str, v: Primitive) -> Option<Primitive> {
if let Some(cur) = self.variables.get_mut(name) { if let Some(cur) = self.variables.get_mut(name) {
Some(std::mem::replace(cur, v)) Some(std::mem::replace(cur, v))
} else if let Some(ref parent) = self.parent {
unsafe { parent.get().borrow_mut().update_var(name, v) }
} else { } else {
self.parent None
.as_ref()
.and_then(|parent| parent.borrow_mut().update_var(name, v))
} }
} }
@ -34,9 +34,11 @@ impl Environment {
pub fn get_var(&self, name: &str) -> Option<Primitive> { pub fn get_var(&self, name: &str) -> Option<Primitive> {
self.variables.get(name).cloned().or_else(|| { self.variables.get(name).cloned().or_else(|| {
self.parent if let Some(ref parent) = self.parent {
.as_ref() unsafe { parent.get().borrow().get_var(name) }
.and_then(|v| (**v).borrow().get_var(name)) } else {
None
}
}) })
} }
} }
@ -48,10 +50,10 @@ pub struct World {
impl World { impl World {
pub fn set_var(&mut self, name: String, v: Primitive) -> Option<Primitive> { pub fn set_var(&mut self, name: String, v: Primitive) -> Option<Primitive> {
self.env.borrow_mut().set_var(name, v) unsafe { self.env.get().borrow_mut().set_var(name, v) }
} }
pub fn get_var(&self, name: &str) -> Option<Primitive> { pub fn get_var(&self, name: &str) -> Option<Primitive> {
self.env.borrow().get_var(name) unsafe { self.env.get().borrow().get_var(name) }
} }
} }