Require an explicit drop call on a gc allocation
This commit is contained in:
parent
2f690250ae
commit
8c95fcbd85
3 changed files with 24 additions and 15 deletions
|
@ -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) };
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue