]> Repositorios git - scryer-prolog.git/commitdiff
add associated Payload type to ArenaAllocated
authorBennet Bleßmann <[email protected]>
Sat, 6 Jul 2024 13:37:08 +0000 (15:37 +0200)
committerBennet Bleßmann <[email protected]>
Sat, 6 Jul 2024 13:37:08 +0000 (15:37 +0200)
src/arena.rs
src/machine/loader.rs
src/machine/streams.rs
src/machine/system_calls.rs
src/types.rs

index 571595a6687c6f3c8063117cb1edb67b27b426fe..58f321f0b479f1bf25c3112db960a154648b77ea 100644 (file)
@@ -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<Payload: Sized>() -> usize {
-    let payload_offset = mem::offset_of!(TypedAllocSlab<Payload>, payload);
-    let slab_offset = mem::offset_of!(TypedAllocSlab<Payload>, slab);
+pub fn header_offset_from_payload<T: ?Sized + ArenaAllocated>() -> usize
+where
+    T::Payload: Sized,
+{
+    let payload_offset = mem::offset_of!(TypedAllocSlab<T>, payload);
+    let slab_offset = mem::offset_of!(TypedAllocSlab<T>, 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<T: ?Sized>(ptr::NonNull<T>);
+pub struct TypedArenaPtr<T: ?Sized + ArenaAllocated>(ptr::NonNull<T::Payload>);
 
-impl<T: ?Sized + PartialOrd> PartialOrd for TypedArenaPtr<T> {
+impl<T: ?Sized + ArenaAllocated> PartialOrd for TypedArenaPtr<T>
+where
+    T::Payload: PartialOrd,
+{
     fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
         (**self).partial_cmp(&**other)
     }
 }
 
-impl<T: ?Sized + PartialEq> PartialEq for TypedArenaPtr<T> {
+impl<T: ?Sized + ArenaAllocated> PartialEq for TypedArenaPtr<T>
+where
+    T::Payload: PartialEq,
+{
     fn eq(&self, other: &TypedArenaPtr<T>) -> bool {
         std::ptr::addr_eq(self.0.as_ptr(), other.0.as_ptr()) || **self == **other
     }
 }
 
-impl<T: ?Sized + PartialEq> Eq for TypedArenaPtr<T> {}
+impl<T: ?Sized + ArenaAllocated> Eq for TypedArenaPtr<T> where T::Payload: Eq {}
 
-impl<T: ?Sized + Ord> Ord for TypedArenaPtr<T> {
+impl<T: ?Sized + ArenaAllocated> Ord for TypedArenaPtr<T>
+where
+    T::Payload: Ord,
+{
     fn cmp(&self, other: &Self) -> std::cmp::Ordering {
         (**self).cmp(&**other)
     }
 }
 
-impl<T: ?Sized + Hash> Hash for TypedArenaPtr<T> {
+impl<T: ?Sized + ArenaAllocated> Hash for TypedArenaPtr<T>
+where
+    T::Payload: Hash,
+{
     #[inline(always)]
     fn hash<H: Hasher>(&self, hasher: &mut H) {
-        (self as &T).hash(hasher)
+        (self as &T::Payload).hash(hasher)
     }
 }
 
-impl<T: ?Sized> Clone for TypedArenaPtr<T> {
+impl<T: ?Sized + ArenaAllocated> Clone for TypedArenaPtr<T> {
     fn clone(&self) -> Self {
         *self
     }
 }
 
-impl<T: ?Sized> Copy for TypedArenaPtr<T> {}
+impl<T: ?Sized + ArenaAllocated> Copy for TypedArenaPtr<T> {}
 
-impl<T: ?Sized> Deref for TypedArenaPtr<T> {
-    type Target = T;
+impl<T: ?Sized + ArenaAllocated> Deref for TypedArenaPtr<T> {
+    type Target = T::Payload;
 
     fn deref(&self) -> &Self::Target {
         unsafe { self.0.as_ref() }
     }
 }
 
-impl<T: ?Sized> DerefMut for TypedArenaPtr<T> {
+impl<T: ?Sized + ArenaAllocated> DerefMut for TypedArenaPtr<T> {
     fn deref_mut(&mut self) -> &mut Self::Target {
         unsafe { self.0.as_mut() }
     }
 }
 
-impl<T: fmt::Display> fmt::Display for TypedArenaPtr<T> {
+impl<T: ArenaAllocated> fmt::Display for TypedArenaPtr<T>
+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<T: ?Sized + ArenaAllocated> TypedArenaPtr<T> {
     /// - 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<T: ?Sized + ArenaAllocated> TypedArenaPtr<T>
+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<T: ?Sized + ArenaAllocated> TypedArenaPtr<T> {
     }
 }
 
-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::<Self>()
     }
 
     /// #  Safety
     /// - the caller must guarantee that the pointee type of UntypedArenaPtr is Self
-    unsafe fn typed_ptr(ptr: UntypedArenaPtr) -> TypedArenaPtr<Self> {
+    unsafe fn typed_ptr(ptr: UntypedArenaPtr) -> TypedArenaPtr<Self>
+    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::<Self>()) }
+        unsafe { TypedArenaPtr::new(ptr.payload_offset().cast_mut().cast::<Self::Payload>()) }
     }
 
     #[allow(clippy::missing_safety_doc)]
-    fn alloc(arena: &mut Arena, value: Self) -> TypedArenaPtr<Self> {
+    fn alloc(arena: &mut Arena, value: Self::Payload) -> TypedArenaPtr<Self>
+    where
+        Self::Payload: Sized,
+    {
         let size = mem::size_of::<TypedAllocSlab<Self>>();
         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<Payload> {
+pub struct TypedAllocSlab<T: ?Sized + ArenaAllocated> {
     slab: AllocSlab,
-    payload: Payload,
+    payload: T::Payload,
 }
 
-impl<Payload: ArenaAllocated> TypedAllocSlab<Payload> {
+impl<T: ?Sized + ArenaAllocated> TypedAllocSlab<T> {
     /// # Safety
     /// - ptr points to a valid allocation of Self
     #[inline]
-    pub unsafe fn to_typed_arena_ptr(ptr: *mut Self) -> TypedArenaPtr<Payload> {
+    pub unsafe fn to_typed_arena_ptr(ptr: *mut Self) -> TypedArenaPtr<T> {
         // 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<AllocSlab>) {
             drop_typed_slab_in_place!(Rational, value);
         }
         ArenaHeaderTag::InputFileStream => {
-            drop_typed_slab_in_place!(StreamLayout<CharReader<InputFileStream>>, value);
+            drop_typed_slab_in_place!(InputFileStream, value);
         }
         ArenaHeaderTag::OutputFileStream => {
-            drop_typed_slab_in_place!(StreamLayout<OutputFileStream>, value);
+            drop_typed_slab_in_place!(OutputFileStream, value);
         }
         ArenaHeaderTag::NamedTcpStream => {
-            drop_typed_slab_in_place!(StreamLayout<CharReader<NamedTcpStream>>, value);
+            drop_typed_slab_in_place!(NamedTcpStream, value);
         }
         ArenaHeaderTag::NamedTlsStream => {
             #[cfg(feature = "tls")]
-            drop_typed_slab_in_place!(StreamLayout<CharReader<NamedTlsStream>>, value);
+            drop_typed_slab_in_place!(NamedTlsStream, value);
         }
         ArenaHeaderTag::HttpReadStream => {
             #[cfg(feature = "http")]
-            drop_typed_slab_in_place!(StreamLayout<CharReader<HttpReadStream>>, value);
+            drop_typed_slab_in_place!(HttpReadStream, value);
         }
         ArenaHeaderTag::HttpWriteStream => {
             #[cfg(feature = "http")]
-            drop_typed_slab_in_place!(StreamLayout<CharReader<HttpWriteStream>>, value);
+            drop_typed_slab_in_place!(HttpWriteStream, value);
         }
         ArenaHeaderTag::ReadlineStream => {
-            drop_typed_slab_in_place!(StreamLayout<ReadlineStream>, value);
+            drop_typed_slab_in_place!(ReadlineStream, value);
         }
         ArenaHeaderTag::StaticStringStream => {
-            drop_typed_slab_in_place!(StreamLayout<StaticStringStream>, value);
+            drop_typed_slab_in_place!(StaticStringStream, value);
         }
         ArenaHeaderTag::ByteStream => {
-            drop_typed_slab_in_place!(StreamLayout<CharReader<ByteStream>>, 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<AllocSlab>) {
             drop_typed_slab_in_place!(HttpResponse, value);
         }
         ArenaHeaderTag::StandardOutputStream => {
-            drop_typed_slab_in_place!(StreamLayout<StandardOutputStream>, value);
+            drop_typed_slab_in_place!(StandardOutputStream, value);
         }
         ArenaHeaderTag::StandardErrorStream => {
-            drop_typed_slab_in_place!(StreamLayout<StandardErrorStream>, value);
+            drop_typed_slab_in_place!(StandardErrorStream, value);
         }
         ArenaHeaderTag::NullStream
         | ArenaHeaderTag::IndexPtrUndefined
index cd4f419a23aa63b650acb56db927e63fe55d28bd..dd4f54bdc8a527884873ca7a813676462c9043de 100644 (file)
@@ -1757,7 +1757,7 @@ impl Machine {
 
     #[inline]
     pub(crate) fn push_load_state_payload(&mut self) {
-        let payload = arena_alloc!(
+        let payload: TypedArenaPtr<LiveLoadState> = arena_alloc!(
             LoadStatePayload::new(self.code.len(), LiveTermStream::new(ListingSource::User),),
             &mut self.machine_st.arena
         );
index aec6464ad063eeabbd361ce6dbdb521a88a9244a..ad09e8581e202b9ea91f86c67010ed386821c0fd 100644 (file)
@@ -451,7 +451,9 @@ impl<T> DerefMut for StreamLayout<T> {
 
 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<StreamLayout<CharReader<ByteStream>>>),
-    InputFile(TypedArenaPtr<StreamLayout<CharReader<InputFileStream>>>),
-    OutputFile(TypedArenaPtr<StreamLayout<OutputFileStream>>),
-    StaticString(TypedArenaPtr<StreamLayout<StaticStringStream>>),
-    NamedTcp(TypedArenaPtr<StreamLayout<CharReader<NamedTcpStream>>>),
+    Byte(TypedArenaPtr<ByteStream>),
+    InputFile(TypedArenaPtr<InputFileStream>),
+    OutputFile(TypedArenaPtr<OutputFileStream>),
+    StaticString(TypedArenaPtr<StaticStringStream>),
+    NamedTcp(TypedArenaPtr<NamedTcpStream>),
     #[cfg(feature = "tls")]
-    NamedTls(TypedArenaPtr<StreamLayout<CharReader<NamedTlsStream>>>),
+    NamedTls(TypedArenaPtr<NamedTlsStream>),
     #[cfg(feature = "http")]
-    HttpRead(TypedArenaPtr<StreamLayout<CharReader<HttpReadStream>>>),
+    HttpRead(TypedArenaPtr<HttpReadStream>),
     #[cfg(feature = "http")]
-    HttpWrite(TypedArenaPtr<StreamLayout<CharReader<HttpWriteStream>>>),
+    HttpWrite(TypedArenaPtr<HttpWriteStream>),
     Null(StreamOptions),
-    Readline(TypedArenaPtr<StreamLayout<ReadlineStream>>),
-    StandardOutput(TypedArenaPtr<StreamLayout<StandardOutputStream>>),
-    StandardError(TypedArenaPtr<StreamLayout<StandardErrorStream>>),
+    Readline(TypedArenaPtr<ReadlineStream>),
+    StandardOutput(TypedArenaPtr<StandardOutputStream>),
+    StandardError(TypedArenaPtr<StandardErrorStream>),
 }
 
-impl From<TypedArenaPtr<StreamLayout<ReadlineStream>>> for Stream {
+impl From<TypedArenaPtr<ReadlineStream>> for Stream {
     #[inline]
-    fn from(stream: TypedArenaPtr<StreamLayout<ReadlineStream>>) -> Stream {
+    fn from(stream: TypedArenaPtr<ReadlineStream>) -> Stream {
         Stream::Readline(stream)
     }
 }
index 80b579e7918ee0c2d14359f030e50cd7f3055c55..5cddb6445f93838047abd6282e35dec19038ca13 100644 (file)
@@ -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<HttpListener> =
+                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<HttpResponse> = 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<TcpListener>, _) =
+            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(
index 2872f5418384989775e7e171ec66180ae8cb9dc8..07328a07bed4f912d22d8bcca58ee2b67524b560 100644 (file)
@@ -300,7 +300,10 @@ impl fmt::Debug for HeapCellValue {
     }
 }
 
-impl<T: ArenaAllocated> From<TypedArenaPtr<T>> for HeapCellValue {
+impl<T: ArenaAllocated> From<TypedArenaPtr<T>> for HeapCellValue
+where
+    T::Payload: Sized,
+{
     #[inline]
     fn from(arena_ptr: TypedArenaPtr<T>) -> 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<T: ArenaAllocated>(self) -> TypedArenaPtr<T> {
+    pub unsafe fn as_typed_ptr<T: ?Sized + ArenaAllocated>(self) -> TypedArenaPtr<T>
+    where
+        T::Payload: Sized,
+    {
         T::typed_ptr(self)
     }