1use std::mem::size_of;
2
3use gc_info_table::GCInfo;
4use header::HeapObjectHeader;
5use large_space::PreciseAllocation;
6
7macro_rules! as_atomic {
8 ($value: expr;$t: ident) => {
9 unsafe { core::mem::transmute::<_, &'_ core::sync::atomic::$t>($value as *const _) }
10 };
11}
12
13macro_rules! logln_if {
14 ($cond: expr, $($t:tt)*) => {
15 if $cond {
16 println!($($t)*);
17 }
18 };
19}
20pub fn align(value: u32, align: u32) -> u32 {
23 if align == 0 {
24 return value;
25 }
26
27 ((value + align - 1) / align) * align
28}
29macro_rules! log_if {
30 ($cond: expr, $($t:tt)*) => {
31 if $cond {
32 print!($($t)*);
33 }
34 };
35}
36pub mod allocation_config;
37pub mod allocator;
38pub mod block;
39pub mod block_allocator;
40pub mod gc_info_table;
41pub mod gcref;
42pub mod global_allocator;
43pub mod globals;
44pub mod header;
45pub mod heap;
46pub mod internal;
47pub mod large_space;
48pub mod marking;
49pub mod mmap;
50pub mod task_scheduler;
51pub mod visitor;
52
53pub struct GCPlatform;
54
55impl GCPlatform {
56 pub fn initialize() {
58 #[cfg(target_family = "wasm")]
59 {
60 panic!("Invoke GCPlatform::initialize_wasm on WASM!");
61 }
62 unsafe {
63 gc_info_table::GCInfoTable::init(None);
64 }
65 }
66
67 pub unsafe fn initialize_wasm(
68 _gc_info_table_mem: &'static mut [u8; size_of::<GCInfo>() * (1 << 14)],
69 ) {
70 }
71}
72
73#[repr(C)]
75pub struct Config {
76 pub heap_growth_factor: f64,
78 pub heap_size: usize,
80 pub max_heap_size: usize,
82 pub max_eden_size: usize,
84 pub verbose: bool,
86 pub generational: bool,
88}
89
90impl Default for Config {
91 fn default() -> Self {
92 Self {
93 generational: false,
94 verbose: false,
95 max_eden_size: 64 * 1024,
96 max_heap_size: 256 * 1024,
97 heap_growth_factor: 1.5,
98 heap_size: 1 * 1024 * 1024 * 1024,
99 }
100 }
101}
102
103pub fn gc_size(ptr: *const HeapObjectHeader) -> usize {
105 unsafe {
106 let size = (*ptr).get_size();
107 if size == 0 {
108 (*PreciseAllocation::from_cell(ptr as _)).cell_size()
109 } else {
110 size
111 }
112 }
113}
114
115pub mod c_api {
116
117 use std::ptr::{null_mut, NonNull};
118
119 use crate::{
120 gc_info_table::{GCInfo, GC_TABLE},
121 gcref::{UntypedGcRef, WeakGcRef},
122 header::HeapObjectHeader,
123 heap::Heap,
124 internal::gc_info::GCInfoIndex,
125 visitor::Visitor,
126 Config, GCPlatform,
127 };
128
129 #[no_mangle]
130 pub extern "C" fn comet_gc_size(ptr: *const HeapObjectHeader) -> usize {
131 super::gc_size(ptr)
132 }
133 #[no_mangle]
134 pub extern "C" fn comet_default_config() -> Config {
135 Config::default()
136 }
137 #[no_mangle]
138 pub extern "C" fn comet_init() {
139 GCPlatform::initialize();
140 }
141 #[no_mangle]
142 pub extern "C" fn comet_heap_create(config: Config) -> *mut Heap {
143 Box::into_raw(Heap::new(config))
144 }
145 #[no_mangle]
147 pub extern "C" fn comet_heap_free(heap: *mut Heap) {
148 unsafe {
149 Box::from_raw(heap);
150 }
151 }
152
153 #[no_mangle]
156 pub extern "C" fn comet_heap_add_constraint(
157 heap: *mut Heap,
158 data: *mut u8,
159 callback: extern "C" fn(*mut u8, *mut Visitor),
160 ) {
161 unsafe {
162 (*heap).add_constraint(move |vis: &mut Visitor| {
163 let data = data;
164 callback(data, vis as *mut _);
165 });
166 }
167 }
168
169 #[no_mangle]
171 pub extern "C" fn comet_heap_add_core_constraints(heap: *mut Heap) {
172 unsafe {
173 (*heap).add_core_constraints();
174 }
175 }
176
177 #[no_mangle]
178 pub extern "C" fn comet_heap_collect(heap: *mut Heap) {
179 unsafe {
180 (*heap).collect_garbage();
181 }
182 }
183
184 #[no_mangle]
185 pub extern "C" fn comet_heap_collect_if_necessary_or_defer(heap: *mut Heap) {
186 unsafe {
187 (*heap).collect_if_necessary_or_defer();
188 }
189 }
190
191 #[no_mangle]
192 pub extern "C" fn comet_heap_allocate_weak(
193 heap: *mut Heap,
194 object: *mut HeapObjectHeader,
195 ) -> WeakGcRef {
196 unsafe {
197 (*heap).allocate_weak(UntypedGcRef {
198 header: NonNull::new_unchecked(object),
199 })
200 }
201 }
202
203 #[no_mangle]
205 pub extern "C" fn comet_heap_allocate(
206 heap: *mut Heap,
207 size: usize,
208 index: GCInfoIndex,
209 ) -> *mut HeapObjectHeader {
210 unsafe {
211 match (*heap).allocate_raw(size, index) {
212 Some(mem) => mem.header.as_ptr(),
213 None => null_mut(),
214 }
215 }
216 }
217
218 #[no_mangle]
220 pub extern "C" fn comet_heap_allocate_or_fail(
221 heap: *mut Heap,
222 size: usize,
223 index: GCInfoIndex,
224 ) -> *mut HeapObjectHeader {
225 unsafe { (*heap).allocate_raw_or_fail(size, index).header.as_ptr() }
226 }
227
228 #[no_mangle]
230 pub extern "C" fn comet_weak_upgrade(weak: WeakGcRef) -> *mut HeapObjectHeader {
231 match weak.upgrade() {
232 Some(ptr) => ptr.header.as_ptr(),
233 None => null_mut(),
234 }
235 }
236
237 #[no_mangle]
238 pub extern "C" fn comet_trace(vis: *mut Visitor, ptr: *mut HeapObjectHeader) {
239 if ptr.is_null() {
240 return;
241 }
242 unsafe {
243 (*vis).trace_untyped(UntypedGcRef {
244 header: NonNull::new_unchecked(ptr),
245 })
246 }
247 }
248
249 #[no_mangle]
250 pub extern "C" fn comet_trace_conservatively(
251 vis: *mut Visitor,
252 from: *const u8,
253 to: *const u8,
254 ) {
255 unsafe { (*vis).trace_conservatively(from, to) }
256 }
257
258 #[no_mangle]
259 pub extern "C" fn comet_add_gc_info(info: GCInfo) -> GCInfoIndex {
260 unsafe { GC_TABLE.add_gc_info(info) }
261 }
262
263 #[no_mangle]
264 pub extern "C" fn comet_get_gc_info(index: GCInfoIndex) -> *mut GCInfo {
265 unsafe { GC_TABLE.get_gc_info_mut(index) as *mut _ }
266 }
267}