From 285f11ccdc18c11dd0a2a91840a7f158fb9a2b5a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bennet=20Ble=C3=9Fmann?= Date: Sat, 6 Jul 2024 15:37:08 +0200 Subject: [PATCH] add associated Payload type to ArenaAllocated --- src/arena.rs | 120 ++++++++++++++++++++++++------------ src/machine/loader.rs | 2 +- src/machine/streams.rs | 30 ++++----- src/machine/system_calls.rs | 50 +++++++-------- src/types.rs | 10 ++- 5 files changed, 131 insertions(+), 81 deletions(-) diff --git a/src/arena.rs b/src/arena.rs index 571595a6..58f321f0 100644 --- a/src/arena.rs +++ b/src/arena.rs @@ -5,7 +5,6 @@ use crate::http::{HttpListener, HttpResponse}; use crate::machine::loader::LiveLoadState; use crate::machine::machine_indices::*; use crate::machine::streams::*; -use crate::parser::char_reader::CharReader; use crate::raw_block::*; use crate::read::*; use crate::types::UntypedArenaPtr; @@ -45,9 +44,12 @@ macro_rules! float_alloc { }}; } -pub fn header_offset_from_payload() -> usize { - let payload_offset = mem::offset_of!(TypedAllocSlab, payload); - let slab_offset = mem::offset_of!(TypedAllocSlab, slab); +pub fn header_offset_from_payload() -> usize +where + T::Payload: Sized, +{ + let payload_offset = mem::offset_of!(TypedAllocSlab, payload); + let slab_offset = mem::offset_of!(TypedAllocSlab, slab); let header_offset = slab_offset + mem::offset_of!(AllocSlab, header); debug_assert!(payload_offset > header_offset); @@ -220,60 +222,75 @@ impl ArenaHeader { } #[derive(Debug)] -pub struct TypedArenaPtr(ptr::NonNull); +pub struct TypedArenaPtr(ptr::NonNull); -impl PartialOrd for TypedArenaPtr { +impl PartialOrd for TypedArenaPtr +where + T::Payload: PartialOrd, +{ fn partial_cmp(&self, other: &Self) -> Option { (**self).partial_cmp(&**other) } } -impl PartialEq for TypedArenaPtr { +impl PartialEq for TypedArenaPtr +where + T::Payload: PartialEq, +{ fn eq(&self, other: &TypedArenaPtr) -> bool { std::ptr::addr_eq(self.0.as_ptr(), other.0.as_ptr()) || **self == **other } } -impl Eq for TypedArenaPtr {} +impl Eq for TypedArenaPtr where T::Payload: Eq {} -impl Ord for TypedArenaPtr { +impl Ord for TypedArenaPtr +where + T::Payload: Ord, +{ fn cmp(&self, other: &Self) -> std::cmp::Ordering { (**self).cmp(&**other) } } -impl Hash for TypedArenaPtr { +impl Hash for TypedArenaPtr +where + T::Payload: Hash, +{ #[inline(always)] fn hash(&self, hasher: &mut H) { - (self as &T).hash(hasher) + (self as &T::Payload).hash(hasher) } } -impl Clone for TypedArenaPtr { +impl Clone for TypedArenaPtr { fn clone(&self) -> Self { *self } } -impl Copy for TypedArenaPtr {} +impl Copy for TypedArenaPtr {} -impl Deref for TypedArenaPtr { - type Target = T; +impl Deref for TypedArenaPtr { + type Target = T::Payload; fn deref(&self) -> &Self::Target { unsafe { self.0.as_ref() } } } -impl DerefMut for TypedArenaPtr { +impl DerefMut for TypedArenaPtr { fn deref_mut(&mut self) -> &mut Self::Target { unsafe { self.0.as_mut() } } } -impl fmt::Display for TypedArenaPtr { +impl fmt::Display for TypedArenaPtr +where + T::Payload: fmt::Display, +{ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", **self) + write!(f, "{}", (self as &T::Payload)) } } @@ -282,15 +299,20 @@ impl TypedArenaPtr { /// - the pointers referee type is correct, safe code depends on the correctness of the type argument /// - the pointer is allocated in the arena #[inline] - pub const unsafe fn new(data: *mut T) -> Self { + pub const unsafe fn new(data: *mut T::Payload) -> Self { unsafe { TypedArenaPtr(ptr::NonNull::new_unchecked(data)) } } #[inline] - pub fn as_ptr(&self) -> *mut T { + pub fn as_ptr(&self) -> *mut T::Payload { self.0.as_ptr() } +} +impl TypedArenaPtr +where + T::Payload: Sized, +{ #[inline] pub fn header_ptr(&self) -> *const ArenaHeader { unsafe { self.as_ptr().byte_sub(T::header_offset_from_payload()) as *const _ } @@ -333,24 +355,35 @@ impl TypedArenaPtr { } } -pub trait ArenaAllocated: Sized { +pub trait ArenaAllocated { + type Payload: ?Sized; + fn tag() -> ArenaHeaderTag; - fn header_offset_from_payload() -> usize { + fn header_offset_from_payload() -> usize + where + Self::Payload: Sized, + { header_offset_from_payload::() } /// # Safety /// - the caller must guarantee that the pointee type of UntypedArenaPtr is Self - unsafe fn typed_ptr(ptr: UntypedArenaPtr) -> TypedArenaPtr { + unsafe fn typed_ptr(ptr: UntypedArenaPtr) -> TypedArenaPtr + where + Self::Payload: Sized, + { // safety: // - allocated in an arena as from an UntypedArenaPtr // - caller guarantees the type is correct - unsafe { TypedArenaPtr::new(ptr.payload_offset().cast_mut().cast::()) } + unsafe { TypedArenaPtr::new(ptr.payload_offset().cast_mut().cast::()) } } #[allow(clippy::missing_safety_doc)] - fn alloc(arena: &mut Arena, value: Self) -> TypedArenaPtr { + fn alloc(arena: &mut Arena, value: Self::Payload) -> TypedArenaPtr + where + Self::Payload: Sized, + { let size = mem::size_of::>(); let slab = Box::new(TypedAllocSlab { slab: AllocSlab { @@ -512,6 +545,7 @@ impl fmt::Display for F64Offset { } impl ArenaAllocated for Integer { + type Payload = Self; #[inline] fn tag() -> ArenaHeaderTag { ArenaHeaderTag::Integer @@ -519,6 +553,7 @@ impl ArenaAllocated for Integer { } impl ArenaAllocated for Rational { + type Payload = Self; #[inline] fn tag() -> ArenaHeaderTag { ArenaHeaderTag::Rational @@ -526,6 +561,7 @@ impl ArenaAllocated for Rational { } impl ArenaAllocated for LiveLoadState { + type Payload = Self; #[inline] fn tag() -> ArenaHeaderTag { ArenaHeaderTag::LiveLoadState @@ -533,6 +569,7 @@ impl ArenaAllocated for LiveLoadState { } impl ArenaAllocated for TcpListener { + type Payload = Self; #[inline] fn tag() -> ArenaHeaderTag { ArenaHeaderTag::TcpListener @@ -541,6 +578,7 @@ impl ArenaAllocated for TcpListener { #[cfg(feature = "http")] impl ArenaAllocated for HttpListener { + type Payload = Self; #[inline] fn tag() -> ArenaHeaderTag { ArenaHeaderTag::HttpListener @@ -549,6 +587,7 @@ impl ArenaAllocated for HttpListener { #[cfg(feature = "http")] impl ArenaAllocated for HttpResponse { + type Payload = Self; #[inline] fn tag() -> ArenaHeaderTag { ArenaHeaderTag::HttpResponse @@ -556,6 +595,7 @@ impl ArenaAllocated for HttpResponse { } impl ArenaAllocated for IndexPtr { + type Payload = Self; #[inline] fn tag() -> ArenaHeaderTag { ArenaHeaderTag::IndexPtrUndefined @@ -625,16 +665,16 @@ pub struct AllocSlab { #[repr(C)] #[derive(Clone, Debug)] -pub struct TypedAllocSlab { +pub struct TypedAllocSlab { slab: AllocSlab, - payload: Payload, + payload: T::Payload, } -impl TypedAllocSlab { +impl TypedAllocSlab { /// # Safety /// - ptr points to a valid allocation of Self #[inline] - pub unsafe fn to_typed_arena_ptr(ptr: *mut Self) -> TypedArenaPtr { + pub unsafe fn to_typed_arena_ptr(ptr: *mut Self) -> TypedArenaPtr { // safety: // - this is the arena allocation of corresponding type unsafe { TypedArenaPtr::new(addr_of_mut!((*ptr).payload)) } @@ -676,34 +716,34 @@ unsafe fn drop_slab_in_place(value: NonNull) { drop_typed_slab_in_place!(Rational, value); } ArenaHeaderTag::InputFileStream => { - drop_typed_slab_in_place!(StreamLayout>, value); + drop_typed_slab_in_place!(InputFileStream, value); } ArenaHeaderTag::OutputFileStream => { - drop_typed_slab_in_place!(StreamLayout, value); + drop_typed_slab_in_place!(OutputFileStream, value); } ArenaHeaderTag::NamedTcpStream => { - drop_typed_slab_in_place!(StreamLayout>, value); + drop_typed_slab_in_place!(NamedTcpStream, value); } ArenaHeaderTag::NamedTlsStream => { #[cfg(feature = "tls")] - drop_typed_slab_in_place!(StreamLayout>, value); + drop_typed_slab_in_place!(NamedTlsStream, value); } ArenaHeaderTag::HttpReadStream => { #[cfg(feature = "http")] - drop_typed_slab_in_place!(StreamLayout>, value); + drop_typed_slab_in_place!(HttpReadStream, value); } ArenaHeaderTag::HttpWriteStream => { #[cfg(feature = "http")] - drop_typed_slab_in_place!(StreamLayout>, value); + drop_typed_slab_in_place!(HttpWriteStream, value); } ArenaHeaderTag::ReadlineStream => { - drop_typed_slab_in_place!(StreamLayout, value); + drop_typed_slab_in_place!(ReadlineStream, value); } ArenaHeaderTag::StaticStringStream => { - drop_typed_slab_in_place!(StreamLayout, value); + drop_typed_slab_in_place!(StaticStringStream, value); } ArenaHeaderTag::ByteStream => { - drop_typed_slab_in_place!(StreamLayout>, value); + drop_typed_slab_in_place!(ByteStream, value); } ArenaHeaderTag::LiveLoadState | ArenaHeaderTag::InactiveLoadState => { drop_typed_slab_in_place!(LiveLoadState, value); @@ -721,10 +761,10 @@ unsafe fn drop_slab_in_place(value: NonNull) { drop_typed_slab_in_place!(HttpResponse, value); } ArenaHeaderTag::StandardOutputStream => { - drop_typed_slab_in_place!(StreamLayout, value); + drop_typed_slab_in_place!(StandardOutputStream, value); } ArenaHeaderTag::StandardErrorStream => { - drop_typed_slab_in_place!(StreamLayout, value); + drop_typed_slab_in_place!(StandardErrorStream, value); } ArenaHeaderTag::NullStream | ArenaHeaderTag::IndexPtrUndefined diff --git a/src/machine/loader.rs b/src/machine/loader.rs index cd4f419a..dd4f54bd 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1757,7 +1757,7 @@ impl Machine { #[inline] pub(crate) fn push_load_state_payload(&mut self) { - let payload = arena_alloc!( + let payload: TypedArenaPtr = arena_alloc!( LoadStatePayload::new(self.code.len(), LiveTermStream::new(ListingSource::User),), &mut self.machine_st.arena ); diff --git a/src/machine/streams.rs b/src/machine/streams.rs index aec6464a..ad09e858 100644 --- a/src/machine/streams.rs +++ b/src/machine/streams.rs @@ -451,7 +451,9 @@ impl DerefMut for StreamLayout { macro_rules! arena_allocated_impl_for_stream { ($stream_type:ty, $stream_tag:ident) => { - impl ArenaAllocated for StreamLayout<$stream_type> { + impl ArenaAllocated for $stream_tag { + type Payload = StreamLayout<$stream_type>; + #[inline] fn tag() -> ArenaHeaderTag { ArenaHeaderTag::$stream_tag @@ -477,26 +479,26 @@ arena_allocated_impl_for_stream!(StandardErrorStream, StandardErrorStream); #[derive(Debug, Copy, Clone)] pub enum Stream { - Byte(TypedArenaPtr>>), - InputFile(TypedArenaPtr>>), - OutputFile(TypedArenaPtr>), - StaticString(TypedArenaPtr>), - NamedTcp(TypedArenaPtr>>), + Byte(TypedArenaPtr), + InputFile(TypedArenaPtr), + OutputFile(TypedArenaPtr), + StaticString(TypedArenaPtr), + NamedTcp(TypedArenaPtr), #[cfg(feature = "tls")] - NamedTls(TypedArenaPtr>>), + NamedTls(TypedArenaPtr), #[cfg(feature = "http")] - HttpRead(TypedArenaPtr>>), + HttpRead(TypedArenaPtr), #[cfg(feature = "http")] - HttpWrite(TypedArenaPtr>>), + HttpWrite(TypedArenaPtr), Null(StreamOptions), - Readline(TypedArenaPtr>), - StandardOutput(TypedArenaPtr>), - StandardError(TypedArenaPtr>), + Readline(TypedArenaPtr), + StandardOutput(TypedArenaPtr), + StandardError(TypedArenaPtr), } -impl From>> for Stream { +impl From> for Stream { #[inline] - fn from(stream: TypedArenaPtr>) -> Stream { + fn from(stream: TypedArenaPtr) -> Stream { Stream::Readline(stream) } } diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index 80b579e7..5cddb644 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -4519,7 +4519,8 @@ impl Machine { }); let http_listener = HttpListener { incoming: rx }; - let http_listener = arena_alloc!(http_listener, &mut self.machine_st.arena); + let http_listener: TypedArenaPtr = + arena_alloc!(http_listener, &mut self.machine_st.arena); let addr = self.deref_register(2); self.machine_st.bind( @@ -4584,7 +4585,7 @@ impl Machine { self.indices.streams.insert(stream); let stream = stream_as_cell!(stream); - let handle = arena_alloc!(request.response, &mut self.machine_st.arena); + let handle: TypedArenaPtr = arena_alloc!(request.response, &mut self.machine_st.arena); self.machine_st.bind(method.as_var().unwrap(), atom_as_cell!(method_atom)); self.machine_st.bind(path.as_var().unwrap(), path_cell); @@ -6516,32 +6517,33 @@ impl Machine { format!("{}:{}", socket_atom.as_str(), port) }; - let (tcp_listener, port) = match TcpListener::bind(server_addr).map_err(|e| e.kind()) { - Ok(tcp_listener) => { - let port = tcp_listener.local_addr().map(|addr| addr.port()).ok(); + let (tcp_listener, port): (TypedArenaPtr, _) = + match TcpListener::bind(server_addr).map_err(|e| e.kind()) { + Ok(tcp_listener) => { + let port = tcp_listener.local_addr().map(|addr| addr.port()).ok(); - if let Some(port) = port { - ( - arena_alloc!(tcp_listener, &mut self.machine_st.arena), - port as usize, - ) - } else { + if let Some(port) = port { + ( + arena_alloc!(tcp_listener, &mut self.machine_st.arena), + port as usize, + ) + } else { + self.machine_st.fail = true; + return Ok(()); + } + } + Err(ErrorKind::PermissionDenied) => { + return Err(self.machine_st.open_permission_error( + addr, + atom!("socket_server_open"), + 2, + )); + } + _ => { self.machine_st.fail = true; return Ok(()); } - } - Err(ErrorKind::PermissionDenied) => { - return Err(self.machine_st.open_permission_error( - addr, - atom!("socket_server_open"), - 2, - )); - } - _ => { - self.machine_st.fail = true; - return Ok(()); - } - }; + }; let addr = self.deref_register(3); self.machine_st.bind( diff --git a/src/types.rs b/src/types.rs index 2872f541..07328a07 100644 --- a/src/types.rs +++ b/src/types.rs @@ -300,7 +300,10 @@ impl fmt::Debug for HeapCellValue { } } -impl From> for HeapCellValue { +impl From> for HeapCellValue +where + T::Payload: Sized, +{ #[inline] fn from(arena_ptr: TypedArenaPtr) -> HeapCellValue { HeapCellValue::from(arena_ptr.header_ptr() as u64) @@ -708,7 +711,10 @@ impl UntypedArenaPtr { /// # Safety /// - this UntypedArenaPtr actuall pointee type is T #[inline] - pub unsafe fn as_typed_ptr(self) -> TypedArenaPtr { + pub unsafe fn as_typed_ptr(self) -> TypedArenaPtr + where + T::Payload: Sized, + { T::typed_ptr(self) } -- 2.54.0