fix leak of slaps with dropped payload
This commit is contained in:
22
src/arena.rs
22
src/arena.rs
@@ -197,6 +197,7 @@ pub enum ArenaHeaderTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[bitfield]
|
#[bitfield]
|
||||||
|
#[repr(align(8))]
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct ArenaHeader {
|
pub struct ArenaHeader {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
@@ -590,7 +591,16 @@ impl ArenaAllocated for LiveLoadState {
|
|||||||
|
|
||||||
unsafe fn dealloc(ptr: NonNull<TypedAllocSlab<Self>>) {
|
unsafe fn dealloc(ptr: NonNull<TypedAllocSlab<Self>>) {
|
||||||
let mut slab = unsafe { Box::from_raw(ptr.as_ptr()) };
|
let mut slab = unsafe { Box::from_raw(ptr.as_ptr()) };
|
||||||
unsafe { ManuallyDrop::drop(&mut slab.payload) };
|
|
||||||
|
match slab.tag() {
|
||||||
|
ArenaHeaderTag::LiveLoadState | ArenaHeaderTag::InactiveLoadState => {
|
||||||
|
unsafe { ManuallyDrop::drop(&mut slab.payload) };
|
||||||
|
}
|
||||||
|
ArenaHeaderTag::Dropped => {}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
drop(slab);
|
drop(slab);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -710,6 +720,7 @@ impl IndexPtrSlab {
|
|||||||
let untyped_arena = UntypedArenaSlab {
|
let untyped_arena = UntypedArenaSlab {
|
||||||
// safety: pointer from Box::into_raw is never null
|
// safety: pointer from Box::into_raw is never null
|
||||||
slab: unsafe { NonNull::new_unchecked(raw_box.cast::<AllocSlab>()) },
|
slab: unsafe { NonNull::new_unchecked(raw_box.cast::<AllocSlab>()) },
|
||||||
|
tag: <IndexPtr as ArenaAllocated>::tag(),
|
||||||
};
|
};
|
||||||
|
|
||||||
(allocated_ptr, untyped_arena)
|
(allocated_ptr, untyped_arena)
|
||||||
@@ -747,20 +758,21 @@ impl<T: ?Sized + ArenaAllocated> TypedAllocSlab<T> {
|
|||||||
UntypedArenaSlab {
|
UntypedArenaSlab {
|
||||||
// safety: pointer from Box::into_raw is never null
|
// safety: pointer from Box::into_raw is never null
|
||||||
slab: unsafe { NonNull::new_unchecked(raw_box.cast::<AllocSlab>()) },
|
slab: unsafe { NonNull::new_unchecked(raw_box.cast::<AllocSlab>()) },
|
||||||
|
tag: T::tag(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
#[repr(transparent)]
|
|
||||||
pub struct UntypedArenaSlab {
|
pub struct UntypedArenaSlab {
|
||||||
slab: NonNull<AllocSlab>,
|
slab: NonNull<AllocSlab>,
|
||||||
|
tag: ArenaHeaderTag,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for UntypedArenaSlab {
|
impl Drop for UntypedArenaSlab {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe { drop_slab_in_place(self.slab) };
|
unsafe { drop_slab_in_place(self.slab, self.tag) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -784,14 +796,14 @@ impl Arena {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn drop_slab_in_place(value: NonNull<AllocSlab>) {
|
unsafe fn drop_slab_in_place(value: NonNull<AllocSlab>, tag: ArenaHeaderTag) {
|
||||||
macro_rules! drop_typed_slab_in_place {
|
macro_rules! drop_typed_slab_in_place {
|
||||||
($payload: ty, $value: expr) => {
|
($payload: ty, $value: expr) => {
|
||||||
<$payload as ArenaAllocated>::dealloc($value.cast::<TypedAllocSlab<$payload>>())
|
<$payload as ArenaAllocated>::dealloc($value.cast::<TypedAllocSlab<$payload>>())
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
match (unsafe { value.as_ref() }).header.tag() {
|
match tag {
|
||||||
ArenaHeaderTag::Integer => {
|
ArenaHeaderTag::Integer => {
|
||||||
drop_typed_slab_in_place!(Integer, value);
|
drop_typed_slab_in_place!(Integer, value);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -470,7 +470,16 @@ macro_rules! arena_allocated_impl_for_stream {
|
|||||||
|
|
||||||
unsafe fn dealloc(ptr: std::ptr::NonNull<TypedAllocSlab<Self>>) {
|
unsafe fn dealloc(ptr: std::ptr::NonNull<TypedAllocSlab<Self>>) {
|
||||||
let mut slab = unsafe { Box::from_raw(ptr.as_ptr()) };
|
let mut slab = unsafe { Box::from_raw(ptr.as_ptr()) };
|
||||||
unsafe { std::mem::ManuallyDrop::drop(slab.payload()) };
|
|
||||||
|
match slab.tag() {
|
||||||
|
ArenaHeaderTag::$stream_tag => {
|
||||||
|
unsafe { std::mem::ManuallyDrop::drop(slab.payload()) };
|
||||||
|
}
|
||||||
|
ArenaHeaderTag::Dropped => {}
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
drop(slab);
|
drop(slab);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user