Skip to main content

cgc_single_threaded/
api.rs

1use crate::mem::Address;
2use smallvec::SmallVec;
3pub unsafe trait Trace: Finalizer {
4    fn mark(&self);
5    fn unmark(&self);
6    fn references(&self) -> SmallVec<[*const dyn HeapTrait; 64]>;
7}
8
9#[derive(Default)]
10pub struct Tracer {
11    stack: SmallVec<[*const dyn HeapTrait; 64]>,
12}
13impl Tracer {
14    pub fn for_each(&mut self, mut f: impl FnMut(*const dyn HeapTrait)) {
15        while let Some(item) = self.stack.pop() {
16            f(item);
17        }
18        //self.stack.into_iter().for_each(|x| f(*x));
19    }
20
21    pub fn trace(&mut self, item: *const dyn HeapTrait) {
22        self.stack.push(item);
23    }
24}
25
26pub trait Traceable
27where
28    Self: Finalizer,
29{
30    fn trace_with(&self, _: &mut Tracer) {}
31}
32
33unsafe impl<T: Traceable> Trace for T {
34    fn mark(&self) {
35        let mut tracer = Tracer::default();
36        self.trace_with(&mut tracer);
37        tracer.for_each(|pointer| unsafe { (*pointer).mark() });
38    }
39    fn unmark(&self) {
40        let mut tracer = Tracer::default();
41        self.trace_with(&mut tracer);
42        tracer.for_each(|pointer| unsafe { (*pointer).unmark() });
43    }
44
45    fn references(&self) -> SmallVec<[*const dyn HeapTrait; 64]> {
46        let mut tracer = Tracer::default();
47        self.trace_with(&mut tracer);
48        tracer.stack
49    }
50}
51
52pub unsafe trait HeapTrait {
53    fn mark(&self);
54    fn unmark(&self);
55    fn slot(&self) -> Address;
56    fn get_fwd(&self) -> Address;
57    fn set_fwd(&self, _: Address);
58    fn copy_to(&self, addr: Address);
59    fn addr(&self) -> Address;
60    fn inner(&self) -> *mut crate::heap::HeapInner<dyn Trace>;
61
62    fn is_marked(&self) -> bool;
63}
64
65pub trait Finalizer {
66    fn finalize(&mut self) {}
67}
68
69macro_rules! simple {
70    ($($t: ty)*) => {
71        $(
72            impl Traceable for $t {}
73            impl Finalizer for $t {}
74        )*
75    };
76}
77
78simple!(
79    i8
80    i16
81    i32
82    i64
83    i128
84    u8
85    u16
86    u32
87    u64
88    u128
89    f64
90    f32
91    bool
92    String
93    isize
94    usize
95    std::fs::File
96    std::fs::FileType
97    std::fs::Metadata
98    std::fs::OpenOptions
99    std::io::Stdin
100    std::io::Stdout
101    std::io::Stderr
102    std::io::Error
103    std::net::TcpStream
104    std::net::TcpListener
105    std::net::UdpSocket
106    std::net::Ipv4Addr
107    std::net::Ipv6Addr
108    std::net::SocketAddrV4
109    std::net::SocketAddrV6
110    std::path::Path
111    std::path::PathBuf
112    std::process::Command
113    std::process::Child
114    std::process::ChildStdout
115    std::process::ChildStdin
116    std::process::ChildStderr
117    std::process::Output
118    std::process::ExitStatus
119    std::process::Stdio
120    std::sync::Barrier
121    std::sync::Condvar
122    std::sync::Once
123    std::ffi::CStr
124    std::ffi::CString
125    &'static str
126);
127
128impl<T: Traceable> Traceable for Option<T> {
129    fn trace_with(&self, tracer: &mut Tracer) {
130        if let Some(item) = self {
131            item.trace_with(tracer);
132        }
133    }
134}
135impl<T: Traceable> Finalizer for Option<T> {
136    fn finalize(&mut self) {
137        if let Some(item) = self {
138            item.finalize();
139        }
140    }
141}
142
143impl<T: Traceable> Traceable for Vec<T> {
144    fn trace_with(&self, tracer: &mut Tracer) {
145        for item in self.iter() {
146            item.trace_with(tracer);
147        }
148    }
149}
150
151impl<T: HeapTrait + Finalizer + 'static> Traceable for T {
152    fn trace_with(&self, tracer: &mut Tracer) {
153        tracer.trace(self as *const dyn HeapTrait);
154    }
155}
156
157impl<T: Finalizer> Finalizer for Vec<T> {
158    fn finalize(&mut self) {
159        for item in self.iter_mut() {
160            item.finalize();
161        }
162    }
163}
164
165pub trait RootedTrait
166where
167    Self: HeapTrait,
168{
169    fn is_rooted(&self) -> bool;
170    fn references(&self) -> SmallVec<[*const dyn HeapTrait; 64]>;
171}
172
173pub struct Rooted<T: Trace + ?Sized> {
174    pub(crate) inner: *mut RootedInner<T>,
175}
176
177impl<T: Trace + ?Sized> Rooted<T> {
178    fn inner(&self) -> &mut RootedInner<T> {
179        unsafe { &mut *self.inner }
180    }
181    pub fn to_heap(&self) -> Handle<T> {
182        Handle {
183            inner: self.inner().inner,
184        }
185    }
186    pub fn get(&self) -> &T {
187        unsafe { &(&*self.inner().inner).value }
188    }
189    pub fn get_mut(&self) -> &mut T {
190        unsafe { &mut (&mut *self.inner().inner).value }
191    }
192}
193
194pub(crate) struct RootedInner<T: Trace + ?Sized> {
195    pub(crate) counter: u32,
196    pub(crate) inner: *mut crate::heap::HeapInner<T>,
197}
198impl<T: Trace + ?Sized> Drop for Rooted<T> {
199    fn drop(&mut self) {
200        unsafe {
201            debug_assert!(!self.inner.is_null());
202            let inner = &mut *self.inner;
203            inner.counter = inner.counter.wrapping_sub(1);
204        }
205    }
206}
207
208impl<T: Trace + ?Sized> Clone for Rooted<T> {
209    fn clone(&self) -> Self {
210        unsafe {
211            let inner = &mut *self.inner;
212            inner.counter = inner.counter + 1;
213            Rooted {
214                inner: inner as *mut _,
215            }
216        }
217    }
218}
219
220unsafe impl<T: Trace + Sized + 'static> HeapTrait for RootedInner<T> {
221    fn mark(&self) {
222        unsafe {
223            (&mut *self.inner).mark(true);
224        }
225    }
226
227    fn unmark(&self) {
228        unsafe {
229            (&mut *self.inner).mark(false);
230        }
231    }
232    fn get_fwd(&self) -> Address {
233        unsafe { (&*self.inner).fwdptr() }
234    }
235
236    fn set_fwd(&self, fwd: Address) {
237        unsafe {
238            (&mut *self.inner).set_fwdptr(fwd);
239        }
240    }
241
242    fn copy_to(&self, addr: Address) {
243        debug_assert!(addr.is_non_null() && !self.inner.is_null());
244        unsafe {
245            std::ptr::copy(
246                self.inner as *const u8,
247                addr.to_mut_ptr(),
248                std::mem::size_of_val(&*self.inner),
249            )
250        }
251    }
252    fn slot(&self) -> Address {
253        debug_assert!(!self.inner.is_null());
254        let slot = &self.inner;
255        Address::from_ptr(slot)
256    }
257    fn addr(&self) -> Address {
258        Address::from_ptr(self.inner as *const u8)
259    }
260    fn is_marked(&self) -> bool {
261        unsafe { (&*self.inner).is_marked() }
262    }
263    fn inner(&self) -> *mut crate::heap::HeapInner<dyn Trace> {
264        self.inner
265    }
266}
267
268impl<T: Trace + Sized + 'static> RootedTrait for RootedInner<T> {
269    fn is_rooted(&self) -> bool {
270        self.counter >= 1
271    }
272    fn references(&self) -> SmallVec<[*const dyn HeapTrait; 64]> {
273        unsafe { (&*self.inner).value.references() }
274    }
275}
276
277/// Wraps GC heap pointer.
278///
279/// GC thing pointers on the heap must be wrapped in a `Handle<T>`
280pub struct Handle<T: Trace + ?Sized> {
281    pub(crate) inner: *mut crate::heap::HeapInner<T>,
282}
283impl<T: Trace + ?Sized> From<Rooted<T>> for Handle<T> {
284    fn from(x: Rooted<T>) -> Self {
285        unsafe {
286            Self {
287                inner: (*x.inner).inner,
288            }
289        }
290    }
291}
292
293impl<T: Trace + ?Sized> From<&Rooted<T>> for Handle<T> {
294    fn from(x: &Rooted<T>) -> Self {
295        unsafe {
296            Self {
297                inner: (*x.inner).inner,
298            }
299        }
300    }
301}
302
303impl<T: Trace + ?Sized> Handle<T> {
304    pub fn get(&self) -> &T {
305        unsafe {
306            debug_assert!(!self.inner.is_null());
307            let inner = &*self.inner;
308            &inner.value
309        }
310    }
311
312    /// Returns mutable reference to rooted value
313    ///
314    /// # Safety
315    /// Rust semantics doesn't allow two mutable references at the same time and this function is safe as long as you have only one mutable reference.
316    ///
317    /// If you want to be 100% sure that you don't have two or more mutable references at the same time please use `Heap<RefCell<T>>`
318    ///
319    ///
320    pub fn get_mut(&mut self) -> &mut T {
321        unsafe {
322            let inner = &mut *self.inner;
323            &mut inner.value
324        }
325    }
326}
327
328unsafe impl<T: Trace + Sized + 'static> HeapTrait for Handle<T> {
329    fn copy_to(&self, addr: Address) {
330        debug_assert!(addr.is_non_null() && !self.inner.is_null());
331        unsafe {
332            std::ptr::copy(
333                self.inner as *const u8,
334                addr.to_mut_ptr(),
335                std::mem::size_of_val(&*self.inner),
336            )
337        }
338    }
339    fn mark(&self) {
340        unsafe {
341            (&mut *self.inner).mark(true);
342        }
343    }
344    fn unmark(&self) {
345        unsafe {
346            (&mut *self.inner).mark(false);
347        }
348    }
349    fn get_fwd(&self) -> Address {
350        unsafe { (&*self.inner).fwdptr() }
351    }
352
353    fn set_fwd(&self, fwd: Address) {
354        unsafe {
355            (&mut *self.inner).set_fwdptr(fwd);
356        }
357    }
358    fn slot(&self) -> Address {
359        debug_assert!(!self.inner.is_null());
360        let slot = &self.inner;
361        Address::from_ptr(slot)
362    }
363    fn addr(&self) -> Address {
364        Address::from_ptr(self.inner as *const u8)
365    }
366    fn is_marked(&self) -> bool {
367        unsafe { (&*self.inner).is_marked() }
368    }
369    fn inner(&self) -> *mut crate::heap::HeapInner<dyn Trace> {
370        self.inner
371    }
372}
373impl<T: Trace> Copy for Handle<T> {}
374impl<T: Trace> Clone for Handle<T> {
375    fn clone(&self) -> Self {
376        *self
377    }
378}
379
380use std::cmp;
381
382impl<T: Trace + PartialOrd> PartialOrd for Handle<T> {
383    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
384        self.get().partial_cmp(other.get())
385    }
386}
387
388impl<T: Trace + Ord> Ord for Handle<T> {
389    fn cmp(&self, other: &Self) -> cmp::Ordering {
390        self.get().cmp(other.get())
391    }
392}
393
394impl<T: Trace + PartialEq> PartialEq for Handle<T> {
395    fn eq(&self, other: &Self) -> bool {
396        self.get().eq(other.get())
397    }
398}
399
400impl<T: Trace + Eq> Eq for Handle<T> {}
401
402use std::hash::{Hash, Hasher};
403
404impl<T: Trace + Hash> Hash for Handle<T> {
405    fn hash<H: Hasher>(&self, state: &mut H) {
406        self.get().hash(state);
407    }
408}
409
410use std::fmt;
411
412impl<T: Trace + fmt::Display> fmt::Display for Handle<T> {
413    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
414        self.get().fmt(f)
415    }
416}
417
418impl<T: Trace + fmt::Debug> fmt::Debug for Handle<T> {
419    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
420        self.get().fmt(f)
421    }
422}
423
424impl<T: Trace + PartialOrd> PartialOrd for Rooted<T> {
425    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
426        self.get().partial_cmp(other.get())
427    }
428}
429
430impl<T: Trace + Ord> Ord for Rooted<T> {
431    fn cmp(&self, other: &Self) -> cmp::Ordering {
432        self.get().cmp(other.get())
433    }
434}
435
436impl<T: Trace + PartialEq> PartialEq for Rooted<T> {
437    fn eq(&self, other: &Self) -> bool {
438        self.get().eq(other.get())
439    }
440}
441
442impl<T: Trace + Eq> Eq for Rooted<T> {}
443
444impl<T: Trace + Hash> Hash for Rooted<T> {
445    fn hash<H: Hasher>(&self, state: &mut H) {
446        self.get().hash(state);
447    }
448}
449
450impl<T: Trace + fmt::Display> fmt::Display for Rooted<T> {
451    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
452        self.get().fmt(f)
453    }
454}
455
456impl<T: Trace + fmt::Debug> fmt::Debug for Rooted<T> {
457    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
458        write!(f, "{:?}", self.get())
459    }
460}
461
462impl<T: Trace> Finalizer for Handle<T> {
463    fn finalize(&mut self) {}
464}
465
466impl<T: Traceable> Finalizer for Rooted<T> {
467    fn finalize(&mut self) {
468        self.get_mut().finalize();
469    }
470}
471
472use std::ops::{Deref, DerefMut};
473
474impl<T: Traceable> Deref for Rooted<T> {
475    type Target = T;
476    fn deref(&self) -> &T {
477        self.get()
478    }
479}
480
481impl<T: Traceable> DerefMut for Rooted<T> {
482    fn deref_mut(&mut self) -> &mut T {
483        self.get_mut()
484    }
485}
486
487impl<T: Traceable> Deref for Handle<T> {
488    type Target = T;
489    fn deref(&self) -> &T {
490        self.get()
491    }
492}
493
494impl<T: Traceable> DerefMut for Handle<T> {
495    fn deref_mut(&mut self) -> &mut T {
496        self.get_mut()
497    }
498}