diff --git a/ast/src/ast.rs b/ast/src/ast.rs index 2dee343d..ffde6e81 100644 --- a/ast/src/ast.rs +++ b/ast/src/ast.rs @@ -19,7 +19,7 @@ mod parser; use alloc::collections::BTreeMap; use crate::prelude::*; -use hvm64_util::{create_var, deref, maybe_grow, multi_iterator, ops::TypedOp as Op, var_to_num}; +use hvm64_util::{create_var, deref_to, maybe_grow, multi_iterator, ops::TypedOp as Op, var_to_num}; use ordered_float::OrderedFloat; @@ -34,7 +34,7 @@ pub struct Book { pub nets: BTreeMap, } -deref!(Book => self.nets: BTreeMap); +deref_to!(Book => self.nets: BTreeMap); /// An AST node representing an interaction net with one free port. /// diff --git a/host/src/host.rs b/host/src/host.rs index 6f89de15..20eae7ff 100644 --- a/host/src/host.rs +++ b/host/src/host.rs @@ -1,7 +1,6 @@ //! The runtime's host, which acts as a translation layer between the AST and //! the runtime. #![cfg_attr(not(feature = "std"), no_std)] -#![feature(inline_const)] include!("../../prelude.rs"); @@ -83,6 +82,6 @@ impl Host { /// Returns a mutable [`Def`] named `name`. pub fn get_mut(&mut self, name: &str) -> &mut Def { - self.defs.get_mut(name).unwrap().downcast_mut().unwrap() + Def::downcast_mut(self.defs.get_mut(name).unwrap()).unwrap() } } diff --git a/runtime/src/allocator.rs b/runtime/src/allocator.rs index 525aea02..04b00275 100644 --- a/runtime/src/allocator.rs +++ b/runtime/src/allocator.rs @@ -61,7 +61,7 @@ pub struct Allocator<'h> { pub(super) head: Addr, } -deref!({<'h>} Allocator<'h> => self.tracer: Tracer); +deref_to!({<'h>} Allocator<'h> => self.tracer: Tracer); impl<'h> Allocator<'h> { pub fn new(heap: &'h Heap) -> Self { @@ -73,24 +73,18 @@ impl<'h> Allocator<'h> { pub fn half_free(&mut self, addr: Addr) { trace!(self.tracer, addr); const FREE: u64 = Port::FREE.0; - if cfg!(feature = "_fuzz") { - if cfg!(not(feature = "_fuzz_no_free")) { - assert_ne!(addr.val().swap(FREE, Relaxed), FREE, "double free"); - } - } else { - addr.val().store(FREE, Relaxed); - if addr.other_half().val().load(Relaxed) == FREE { - trace!(self.tracer, "other free"); - let addr = addr.left_half(); - if addr.val().compare_exchange(FREE, self.head.0 as u64, Relaxed, Relaxed).is_ok() { - let old_head = &self.head; - let new_head = addr; - trace!(self.tracer, "appended", old_head, new_head); - self.head = new_head; - } else { - trace!(self.tracer, "too slow"); - }; - } + addr.val().store(FREE, Relaxed); + if addr.other_half().val().load(Relaxed) == FREE { + trace!(self.tracer, "other free"); + let addr = addr.left_half(); + if addr.val().compare_exchange(FREE, self.head.0 as u64, Relaxed, Relaxed).is_ok() { + let old_head = &self.head; + let new_head = addr; + trace!(self.tracer, "appended", old_head, new_head); + self.head = new_head; + } else { + trace!(self.tracer, "too slow"); + }; } } diff --git a/runtime/src/def.rs b/runtime/src/def.rs index 0849ac05..e272f01b 100644 --- a/runtime/src/def.rs +++ b/runtime/src/def.rs @@ -1,3 +1,5 @@ +use hvm64_util::new_uninit_slice; + use super::*; /// A bitset representing the set of labels used in a def. @@ -94,14 +96,10 @@ pub struct Def { pub type DynDef = dyn DerefMut + Send + Sync; -extern "C" { - /// An internal type used to mark dynamic `Def`s. - /// - /// Because this is an `extern type`, it is unsized, but has zero metadata. - /// This is essentially a workaround for the lack of custom DSTs. - #[doc(hidden)] - pub type Dynamic; -} +/// An internal type used to mark dynamic `Def`s. +/// +/// This should be unsized, but there is no stable way to do this at the moment. +pub struct Dynamic(()); unsafe impl Send for Dynamic {} unsafe impl Sync for Dynamic {} @@ -111,7 +109,7 @@ pub trait AsDef: Any + Send + Sync { } impl Def { - pub const fn new(labs: LabSet, data: T) -> Self + pub fn new(labs: LabSet, data: T) -> Self where T: AsDef, { @@ -132,11 +130,11 @@ impl Def { impl Def { #[inline(always)] pub unsafe fn downcast_ptr(slf: *const Def) -> Option<*const Def> { - if (*slf).ty == TypeId::of::() { Some(slf.cast()) } else { None } + if (*slf).ty == TypeId::of::() { Some(slf as *const Def) } else { None } } #[inline(always)] pub unsafe fn downcast_mut_ptr(slf: *mut Def) -> Option<*mut Def> { - if (*slf).ty == TypeId::of::() { Some(slf.cast()) } else { None } + if (*slf).ty == TypeId::of::() { Some(slf as *mut Def) } else { None } } #[inline(always)] pub fn downcast_ref(&self) -> Option<&Def> { @@ -156,14 +154,14 @@ impl Deref for Def { type Target = Def; #[inline(always)] fn deref(&self) -> &Self::Target { - self.upcast() + Def::upcast(self) } } impl DerefMut for Def { #[inline(always)] fn deref_mut(&mut self) -> &mut Self::Target { - self.upcast_mut() + Def::upcast_mut(self) } } @@ -222,7 +220,7 @@ impl AsDef for InterpretedDef { let instructions = &def.instr; if def.trgs >= net.trgs.len() { - net.trgs = Box::new_uninit_slice(def.trgs); + net.trgs = new_uninit_slice(def.trgs); } let mut trgs = Trgs(&mut net.trgs[..] as *mut _ as *mut _); diff --git a/runtime/src/linker.rs b/runtime/src/linker.rs index 93823518..eac681d9 100644 --- a/runtime/src/linker.rs +++ b/runtime/src/linker.rs @@ -13,7 +13,7 @@ pub struct Linker<'h> { pub redexes: RedexQueue, } -deref!({<'h, >} Linker<'h> => self.allocator: Allocator<'h>); +deref_to!({<'h, >} Linker<'h> => self.allocator: Allocator<'h>); impl<'h> Linker<'h> { pub fn new(heap: &'h Heap) -> Self { diff --git a/runtime/src/net.rs b/runtime/src/net.rs index 8ca66e34..04cb4d4b 100644 --- a/runtime/src/net.rs +++ b/runtime/src/net.rs @@ -1,5 +1,6 @@ use super::*; +use hvm64_util::new_uninit_slice; use mem::MaybeUninit; /// An interaction combinator net. @@ -11,7 +12,7 @@ pub struct Net<'a> { pub root: Wire, } -deref!({<'a, >} Net<'a> => self.linker: Linker<'a>); +deref_to!({<'a, >} Net<'a> => self.linker: Linker<'a>); impl<'h> Net<'h> { /// Creates an empty net with a given heap. @@ -22,7 +23,7 @@ impl<'h> Net<'h> { } pub(super) fn new_with_root(heap: &'h Heap, root: Wire) -> Self { - Net { linker: Linker::new(heap), tid: 0, tids: 1, trgs: Box::new_uninit_slice(1 << 16), root } + Net { linker: Linker::new(heap), tid: 0, tids: 1, trgs: new_uninit_slice(1 << 16), root } } /// Boots a net from a Def. diff --git a/runtime/src/parallel.rs b/runtime/src/parallel.rs index 5517b489..b272f6dc 100644 --- a/runtime/src/parallel.rs +++ b/runtime/src/parallel.rs @@ -18,7 +18,7 @@ impl<'h> Net<'h> { (0 .. tids).map(move |tid| { let heap_size = (heap.0.len() / tids) & !63; // round down to needed alignment let heap_start = heap_size * tid; - let area = unsafe { mem::transmute(&heap.0[heap_start .. heap_start + heap_size]) }; + let area = unsafe { mem::transmute::<&[Node], &Heap>(&heap.0[heap_start .. heap_start + heap_size]) }; let mut net = Net::new_with_root(area, root.clone()); net.next = next.saturating_sub(heap_start); net.head = if tid == 0 { net.head } else { Addr::NULL }; diff --git a/runtime/src/runtime.rs b/runtime/src/runtime.rs index 9a14ee34..353eb7c8 100644 --- a/runtime/src/runtime.rs +++ b/runtime/src/runtime.rs @@ -17,7 +17,6 @@ //! the *auxiliary ports* of the net (as managed by the linker); the target of //! the principal port is left implicit //! - active pairs are thus stored in a dedicated vector, `net.redexes` -#![feature(const_type_id, extern_types, inline_const, new_uninit)] #![cfg_attr(feature = "trace", feature(const_type_name))] #![cfg_attr(not(feature = "std"), no_std)] @@ -27,7 +26,7 @@ use crate::prelude::*; pub use hvm64_util::ops; -use hvm64_util::{bi_enum, deref, pretty_num}; +use hvm64_util::{bi_enum, deref_to, pretty_num}; use self::trace::Tracer; use alloc::borrow::Cow; diff --git a/runtime/src/trace.rs b/runtime/src/trace.rs index 0d41f2c8..8728545e 100644 --- a/runtime/src/trace.rs +++ b/runtime/src/trace.rs @@ -216,9 +216,6 @@ impl TraceWriter { self.lock.locked.store(false, Ordering::Release); } fn trace(&mut self, args: A) { - if cfg!(feature = "_fuzz") { - self.sync(); - } let meta: &'static _ = &TraceMetadata { source: S::SOURCE, arg_fmts: A::FMTS }; self.acquire(|data| { let nonce = self.nonce; diff --git a/runtime/src/wire.rs b/runtime/src/wire.rs index 7a79cd94..b4a7891d 100644 --- a/runtime/src/wire.rs +++ b/runtime/src/wire.rs @@ -37,19 +37,12 @@ impl Wire { #[inline(always)] fn target<'a>(&self) -> &'a AtomicU64 { - if cfg!(feature = "_fuzz") { - assert_ne!(self.0 as usize, 0xfffffffffff0u64 as usize); - assert_ne!(self.0 as usize, 0); - } unsafe { &*self.0 } } #[inline(always)] pub fn load_target(&self) -> Port { let port = Port(self.target().load(Relaxed)); - if cfg!(feature = "_fuzz") { - assert_ne!(port, Port::FREE); - } port } @@ -66,9 +59,6 @@ impl Wire { #[inline(always)] pub fn swap_target(&self, value: Port) -> Port { let port = Port(self.target().swap(value.0, Relaxed)); - if cfg!(feature = "_fuzz") { - assert_ne!(port, Port::FREE); - } port } @@ -77,9 +67,6 @@ impl Wire { pub fn lock_target(&self) -> Port { loop { let got = self.swap_target(Port::LOCK); - if cfg!(feature = "_fuzz") { - assert_ne!(got, Port::FREE); - } if got != Port::LOCK { return got; } diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 2e4d1842..923d1c25 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] profile = "minimal" -channel = "nightly-2024-01-27" +channel = "nightly-2024-05-28" components = ["rustfmt", "clippy"] diff --git a/src/compile.rs b/src/compile.rs index 8d44f6a3..8d8bff27 100644 --- a/src/compile.rs +++ b/src/compile.rs @@ -33,7 +33,7 @@ fn _compile_host(host: &Host) -> Result { let mut def_infos: BTreeMap<&str, DefInfo<'_>> = BTreeMap::new(); for (hvm64_name, def) in &host.defs { - if let Some(def) = def.downcast_ref::() { + if let Some(def) = Def::downcast_ref::(def) { def_infos.insert(hvm64_name, DefInfo { rust_name: sanitize_name(hvm64_name), refs: refs(host, def.data.instructions()), diff --git a/src/compile/include_files.rs b/src/compile/include_files.rs index 43942a50..b4174578 100644 --- a/src/compile/include_files.rs +++ b/src/compile/include_files.rs @@ -79,6 +79,7 @@ hvm64-runtime = { path = "../runtime", default-features = false } bi_enum create_var deref + new_uninit_slice maybe_grow multi_iterator ops { diff --git a/util/src/deref.rs b/util/src/deref.rs index 70731a1f..f79a8a5a 100644 --- a/util/src/deref.rs +++ b/util/src/deref.rs @@ -1,5 +1,5 @@ #[macro_export] -macro_rules! deref { +macro_rules! deref_to { ($({$($gen:tt)*})? $ty:ty => self.$field:ident: $trg:ty) => { impl $($($gen)*)? core::ops::Deref for $ty { type Target = $trg; diff --git a/util/src/lib.rs b/util/src/lib.rs index d080f897..15308183 100644 --- a/util/src/lib.rs +++ b/util/src/lib.rs @@ -10,10 +10,12 @@ mod multi_iterator; mod create_var; mod maybe_grow; +mod new_uninit_slice; mod parse_abbrev_number; mod pretty_num; pub use create_var::*; pub use maybe_grow::*; +pub use new_uninit_slice::*; pub use parse_abbrev_number::*; pub use pretty_num::*; diff --git a/util/src/new_uninit_slice.rs b/util/src/new_uninit_slice.rs new file mode 100644 index 00000000..e032724b --- /dev/null +++ b/util/src/new_uninit_slice.rs @@ -0,0 +1,10 @@ +use alloc::alloc::alloc; +use core::{alloc::Layout, mem::MaybeUninit, slice}; + +use crate::prelude::*; + +// TODO: use `Box::new_uninit_slice` once stabilized +// https://github.com/rust-lang/rust/issues/63291 +pub fn new_uninit_slice(len: usize) -> Box<[MaybeUninit]> { + unsafe { Box::from_raw(slice::from_raw_parts_mut(alloc(Layout::array::(len).unwrap()).cast(), len)) } +}