diff --git a/server/src/engine/core/util.rs b/server/src/engine/core/util.rs index b6c9bc84..7693545f 100644 --- a/server/src/engine/core/util.rs +++ b/server/src/engine/core/util.rs @@ -24,14 +24,9 @@ * */ -use std::{ - alloc::{dealloc, Layout}, - borrow::Borrow, - fmt, - hash::Hash, - marker::PhantomData, - mem::ManuallyDrop, - slice, str, +use { + crate::engine::mem::unsafe_apis, + std::{borrow::Borrow, fmt, hash::Hash, marker::PhantomData, mem::ManuallyDrop, slice, str}, }; pub struct EntityID { @@ -63,8 +58,8 @@ impl EntityID { impl Drop for EntityID { fn drop(&mut self) { unsafe { - dealloc(self.sp, Layout::array::(self.sl).unwrap_unchecked()); - dealloc(self.ep, Layout::array::(self.el).unwrap_unchecked()); + unsafe_apis::dealloc_array(self.sp, self.sl); + unsafe_apis::dealloc_array(self.ep, self.el); } } } diff --git a/server/src/engine/idx/stord/mod.rs b/server/src/engine/idx/stord/mod.rs index a6ce8b0a..11a31200 100644 --- a/server/src/engine/idx/stord/mod.rs +++ b/server/src/engine/idx/stord/mod.rs @@ -38,9 +38,9 @@ use { super::{ AsKey, AsKeyClone, AsValue, AsValueClone, IndexBaseSpec, STIndex, STIndexExt, STIndexSeq, }, - crate::engine::mem::StatelessLen, + crate::engine::mem::{unsafe_apis, StatelessLen}, std::{ - alloc::{alloc as std_alloc, dealloc as std_dealloc, Layout}, + alloc::Layout, borrow::Borrow, collections::HashMap as StdMap, fmt::{self, Debug}, @@ -163,9 +163,7 @@ impl IndexSTSeqDllNode { fn _alloc_with_garbage() -> *mut Self { unsafe { // UNSAFE(@ohsayan): aight shut up, it's a malloc - let ptr = std_alloc(Self::LAYOUT) as *mut Self; - assert!(!ptr.is_null(), "damn the allocator failed"); - ptr + unsafe_apis::alloc_layout(Self::LAYOUT) } } #[inline(always)] @@ -191,7 +189,7 @@ impl IndexSTSeqDllNode { #[inline(always)] /// LEAK: K, V unsafe fn dealloc_headless(slf: *mut Self) { - std_dealloc(slf as *mut u8, Self::LAYOUT) + unsafe_apis::dealloc_layout(slf as *mut u8, Self::LAYOUT) } #[inline(always)] unsafe fn unlink(node: *mut Self) { diff --git a/server/src/engine/mem/uarray.rs b/server/src/engine/mem/uarray.rs index 6e71c2f1..83f00a5f 100644 --- a/server/src/engine/mem/uarray.rs +++ b/server/src/engine/mem/uarray.rs @@ -24,13 +24,16 @@ * */ -use core::{ - fmt, - hash::{Hash, Hasher}, - iter::FusedIterator, - mem::MaybeUninit, - ops::{Deref, DerefMut}, - ptr, slice, +use { + crate::engine::mem::unsafe_apis, + core::{ + fmt, + hash::{Hash, Hasher}, + iter::FusedIterator, + mem::MaybeUninit, + ops::{Deref, DerefMut}, + ptr, slice, + }, }; pub struct UArray { @@ -88,9 +91,8 @@ impl UArray { } pub fn clear(&mut self) { unsafe { - let ptr = self.as_slice_mut(); // UNSAFE(@ohsayan): We know this is the initialized length - ptr::drop_in_place(ptr); + unsafe_apis::drop_slice_in_place_ref(self.as_slice_mut()); // UNSAFE(@ohsayan): we've destroyed everything, so yeah, all g self.set_len(0); } @@ -176,7 +178,7 @@ impl Drop for UArray { if !self.is_empty() { unsafe { // UNSAFE(@ohsayan): as_slice_mut returns a correct offset - ptr::drop_in_place(self.as_slice_mut()) + unsafe_apis::drop_slice_in_place_ref(self.as_slice_mut()) } } } @@ -263,7 +265,7 @@ impl Drop for IntoIter { let ptr = self.d.a.as_mut_ptr().add(self.i) as *mut T; let len = self.l - self.i; // UNSAFE(@ohsayan): we know the segment to drop - ptr::drop_in_place(ptr::slice_from_raw_parts_mut(ptr, len)) + unsafe_apis::drop_slice_in_place(ptr, len) } } } diff --git a/server/src/engine/mem/unsafe_apis.rs b/server/src/engine/mem/unsafe_apis.rs index 2080137c..da1ed9aa 100644 --- a/server/src/engine/mem/unsafe_apis.rs +++ b/server/src/engine/mem/unsafe_apis.rs @@ -24,28 +24,54 @@ * */ -use std::alloc::{self, Layout}; +/*! + # Unsafe APIs + This module provides abstractions (unsafe, still) over unsafe allocator and related APIs. + +*/ + +use std::{ + alloc::{self, Layout}, + ptr, +}; + +/// Allocate the given layout. This will panic if the allocator returns an error pub unsafe fn alloc_layout(layout: Layout) -> *mut T { let ptr = alloc::alloc(layout); assert!(!ptr.is_null(), "malloc failed"); ptr as _ } +/// Allocate an block with an array layout of type `T` with space for `l` elements pub unsafe fn alloc_array(l: usize) -> *mut T { self::alloc_layout(Layout::array::(l).unwrap_unchecked()) } +/// Deallocate the given layout pub unsafe fn dealloc_layout(ptr: *mut u8, layout: Layout) { alloc::dealloc(ptr, layout) } +/// Deallocate an array of type `T` with size `l`. This function will ensure that nonzero calls to the +/// allocator are made pub unsafe fn dealloc_array(ptr: *mut T, l: usize) { if l != 0 { self::dealloc_layout(ptr as *mut u8, Layout::array::(l).unwrap_unchecked()) } } +/// Run the dtor for the given slice (range) +pub unsafe fn drop_slice_in_place_ref(ptr: &mut [T]) { + ptr::drop_in_place(ptr as *mut [T]) +} + +/// Run the dtor for the given slice (defined using ptr and len) +pub unsafe fn drop_slice_in_place(ptr: *mut T, l: usize) { + ptr::drop_in_place(ptr::slice_from_raw_parts_mut(ptr, l)) +} + +/// Copy exactly `N` bytes from `src` to a new array of size `N` pub unsafe fn memcpy(src: &[u8]) -> [u8; N] { let mut dst = [0u8; N]; src.as_ptr().copy_to_nonoverlapping(dst.as_mut_ptr(), N); diff --git a/server/src/engine/mem/vinline.rs b/server/src/engine/mem/vinline.rs index 43a756c0..dccb06e3 100644 --- a/server/src/engine/mem/vinline.rs +++ b/server/src/engine/mem/vinline.rs @@ -24,13 +24,15 @@ * */ -use std::{ - alloc::{alloc, dealloc, Layout}, - fmt, - iter::FusedIterator, - mem::{self, ManuallyDrop, MaybeUninit}, - ops::{Deref, DerefMut}, - ptr, slice, +use { + super::unsafe_apis, + std::{ + fmt, + iter::FusedIterator, + mem::{self, ManuallyDrop, MaybeUninit}, + ops::{Deref, DerefMut}, + ptr, slice, + }, }; union VData { @@ -77,7 +79,7 @@ impl VInline { pub fn clear(&mut self) { unsafe { // UNSAFE(@ohsayan): as_slice_mut will always give a valid ptr - ptr::drop_in_place(self._as_slice_mut()); + unsafe_apis::drop_slice_in_place_ref(self._as_slice_mut()) } self.l = 0; } @@ -171,19 +173,13 @@ impl VInline { } } #[inline(always)] - fn layout(cap: usize) -> Layout { - Layout::array::(cap).unwrap() - } - #[inline(always)] fn ncap(&self) -> usize { self.c * Self::ALLOC_MULTIPLIER } fn alloc_block(cap: usize) -> *mut T { unsafe { - // UNSAFE(@ohsayan): malloc bro - let p = alloc(Self::layout(cap)); - assert!(!p.is_null(), "alloc,0"); - p as *mut T + // UNSAFE(@ohsayan): this is a malloc + unsafe_apis::alloc_array(cap) } } pub unsafe fn push_unchecked(&mut self, v: T) { @@ -248,7 +244,7 @@ impl VInline { } #[inline(always)] unsafe fn dealloc_heap(&mut self, heap: *mut T) { - dealloc(heap as *mut u8, Self::layout(self.capacity())) + unsafe_apis::dealloc_array(heap, self.capacity()) } } @@ -275,7 +271,7 @@ impl Drop for VInline { fn drop(&mut self) { unsafe { // UNSAFE(@ohsayan): correct ptr guaranteed by safe impl of _as_slice_mut() - ptr::drop_in_place(self._as_slice_mut()); + unsafe_apis::drop_slice_in_place_ref(self._as_slice_mut()); if !self.on_stack() { // UNSAFE(@ohsayan): non-null heap self.dealloc_heap(self.d.h); @@ -357,10 +353,7 @@ impl Drop for IntoIter { // sweet unsafe { // UNSAFE(@ohsayan): Safe because we maintain the EOA cond; second, the l is the remaining part - ptr::drop_in_place(ptr::slice_from_raw_parts_mut( - self.v._as_mut_ptr().add(self.i), - self.l - self.i, - )) + unsafe_apis::drop_slice_in_place(self.v._as_mut_ptr().add(self.i), self.l - self.i) } } } diff --git a/server/src/engine/sync/smart.rs b/server/src/engine/sync/smart.rs index 59c710fb..b02330d5 100644 --- a/server/src/engine/sync/smart.rs +++ b/server/src/engine/sync/smart.rs @@ -26,15 +26,15 @@ use { super::atm::{ORD_ACQ, ORD_REL, ORD_RLX}, + crate::engine::mem::unsafe_apis, std::{ - alloc::{dealloc, Layout}, borrow::Borrow, fmt, hash::{Hash, Hasher}, mem::{self, ManuallyDrop}, ops::Deref, process, - ptr::{self, NonNull}, + ptr::NonNull, slice, str, sync::atomic::{self, AtomicUsize}, }, @@ -141,13 +141,11 @@ impl Drop for SliceRC { // dtor if mem::needs_drop::() { // UNSAFE(@ohsayan): dtor through, the ctor guarantees correct alignment and len - ptr::drop_in_place(ptr::slice_from_raw_parts_mut(self.ptr.as_ptr(), self.len)); + unsafe_apis::drop_slice_in_place(self.ptr.as_ptr(), self.len) } // dealloc - // UNSAFE(@ohsayan): we allocated it - let layout = Layout::array::(self.len).unwrap_unchecked(); - // UNSAFE(@ohsayan): layout structure guaranteed by ctor - dealloc(self.ptr.as_ptr() as *mut u8, layout); + // UNSAFE(@ohsayan): we allocated it + layout structure guaranteed by ctor + unsafe_apis::dealloc_array(self.ptr.as_ptr(), self.len) }) } }