Skip to main content

gc_alloc/
vec.rs

1use std::{ffi::c_void, ptr::NonNull};
2
3use crate::gc;
4
5pub fn from_fn<T>(len: usize, mut f: impl FnMut(usize) -> T) -> &'static mut [T] {
6    let vec = VecInner::<T>::new(len);
7    for i in 0..len {
8        unsafe { vec.as_ptr().add(i).write(f(i)) };
9    }
10    vec.set_len(len);
11
12    register_finalizer(vec.as_ptr());
13
14    unsafe { std::slice::from_raw_parts_mut(vec.as_ptr(), len) }
15}
16
17pub fn repeat<T: Clone>(val: T, len: usize) -> &'static mut [T] {
18    from_fn(len, |_| val.clone())
19}
20
21pub fn from_iter<T, I: IntoIterator<Item = T>>(iter: I) -> &'static mut [T] {
22    let iter = iter.into_iter();
23    let (lower, _) = iter.size_hint();
24
25    let mut cap = lower.max(1);
26    let mut vec = VecInner::<T>::new(cap);
27    let mut len = 0;
28    for item in iter {
29        if len == cap {
30            cap = cap.checked_mul(2).expect("Capacity overflow");
31            let new_vec = VecInner::<T>::new(cap);
32            unsafe { std::ptr::copy_nonoverlapping(vec.as_ptr(), new_vec.as_ptr(), len) };
33            vec = new_vec;
34        }
35        unsafe { vec.as_ptr().add(len).write(item) };
36        len += 1;
37    }
38    vec.set_len(len);
39
40    register_finalizer(vec.as_ptr());
41
42    unsafe { std::slice::from_raw_parts_mut(vec.as_ptr(), len) }
43}
44
45fn register_finalizer<T>(ptr: *mut T) {
46    if std::mem::needs_drop::<T>() {
47        extern "C" fn finalizer<T>(obj: *mut c_void, _: *mut c_void) {
48            let vec = VecInner(unsafe { NonNull::new_unchecked(obj as *mut T) });
49            let len = vec.num_to_drop();
50            for i in 0..len {
51                unsafe { std::ptr::drop_in_place(vec.as_ptr().add(i)) };
52            }
53        }
54
55        unsafe {
56            gc::GC_register_finalizer(
57                ptr as *mut std::ffi::c_void,
58                Some(finalizer::<T>),
59                std::ptr::null_mut(),
60                std::ptr::null_mut(),
61                std::ptr::null_mut(),
62            );
63        }
64    }
65}
66
67struct VecInner<T>(NonNull<T>);
68
69impl<T> VecInner<T> {
70    fn new(cap: usize) -> Self {
71        if std::mem::needs_drop::<T>() {
72            let padding = usize::max(std::mem::size_of::<usize>(), std::mem::size_of::<T>());
73            let alignment = usize::max(std::mem::align_of::<usize>(), std::mem::align_of::<T>());
74
75            let ptr = unsafe {
76                gc::GC_memalign(
77                    std::mem::size_of::<T>().strict_mul(cap).strict_add(padding),
78                    alignment,
79                ) as *mut T
80            };
81            let ptr = unsafe {
82                NonNull::new(ptr)
83                    .expect("Allocation failed")
84                    .byte_add(padding)
85            };
86            VecInner(ptr)
87        } else {
88            let ptr = unsafe {
89                gc::GC_memalign(
90                    std::mem::size_of::<T>().strict_mul(cap),
91                    std::mem::align_of::<T>(),
92                ) as *mut T
93            };
94            let ptr = NonNull::new(ptr).expect("Allocation failed");
95            VecInner(ptr)
96        }
97    }
98
99    fn as_ptr(&self) -> *mut T {
100        self.0.as_ptr()
101    }
102
103    fn num_to_drop(&self) -> usize {
104        if std::mem::needs_drop::<T>() {
105            let p_len =
106                unsafe { self.0.as_ptr().byte_sub(std::mem::size_of::<usize>()) as *const usize };
107            unsafe { p_len.read() }
108        } else {
109            0
110        }
111    }
112
113    fn set_len(&self, len: usize) {
114        if std::mem::needs_drop::<T>() {
115            let p_len =
116                unsafe { self.0.as_ptr().byte_sub(std::mem::size_of::<usize>()) as *mut usize };
117            unsafe { p_len.write(len) };
118        }
119    }
120}