use std::mem::size_of;
use gc_info_table::GCInfo;
use header::HeapObjectHeader;
use large_space::PreciseAllocation;
macro_rules! as_atomic {
($value: expr;$t: ident) => {
unsafe { core::mem::transmute::<_, &'_ core::sync::atomic::$t>($value as *const _) }
};
}
macro_rules! logln_if {
($cond: expr, $($t:tt)*) => {
if $cond {
println!($($t)*);
}
};
}
pub fn align(value: u32, align: u32) -> u32 {
if align == 0 {
return value;
}
((value + align - 1) / align) * align
}
macro_rules! log_if {
($cond: expr, $($t:tt)*) => {
if $cond {
print!($($t)*);
}
};
}
pub mod allocation_config;
pub mod allocator;
pub mod block;
pub mod block_allocator;
pub mod gc_info_table;
pub mod gcref;
pub mod global_allocator;
pub mod globals;
pub mod header;
pub mod heap;
pub mod internal;
pub mod large_space;
pub mod marking;
pub mod mmap;
pub mod task_scheduler;
pub mod visitor;
pub struct GCPlatform;
impl GCPlatform {
pub fn initialize() {
#[cfg(target_family = "wasm")]
{
panic!("Invoke GCPlatform::initialize_wasm on WASM!");
}
unsafe {
gc_info_table::GCInfoTable::init(None);
}
}
pub unsafe fn initialize_wasm(
_gc_info_table_mem: &'static mut [u8; size_of::<GCInfo>() * (1 << 14)],
) {
}
}
#[repr(C)]
pub struct Config {
pub heap_growth_factor: f64,
pub heap_size: usize,
pub max_heap_size: usize,
pub max_eden_size: usize,
pub verbose: bool,
pub generational: bool,
}
impl Default for Config {
fn default() -> Self {
Self {
generational: false,
verbose: false,
max_eden_size: 64 * 1024,
max_heap_size: 256 * 1024,
heap_growth_factor: 1.5,
heap_size: 1 * 1024 * 1024 * 1024,
}
}
}
pub fn gc_size(ptr: *const HeapObjectHeader) -> usize {
unsafe {
let size = (*ptr).get_size();
if size == 0 {
(*PreciseAllocation::from_cell(ptr as _)).cell_size()
} else {
size
}
}
}
pub mod c_api {
use std::ptr::{null_mut, NonNull};
use crate::{
gc_info_table::{GCInfo, GC_TABLE},
gcref::{UntypedGcRef, WeakGcRef},
header::HeapObjectHeader,
heap::Heap,
internal::gc_info::GCInfoIndex,
visitor::Visitor,
Config, GCPlatform,
};
#[no_mangle]
pub extern "C" fn comet_gc_size(ptr: *const HeapObjectHeader) -> usize {
super::gc_size(ptr)
}
#[no_mangle]
pub extern "C" fn comet_default_config() -> Config {
Config::default()
}
#[no_mangle]
pub extern "C" fn comet_init() {
GCPlatform::initialize();
}
#[no_mangle]
pub extern "C" fn comet_heap_create(config: Config) -> *mut Heap {
Box::into_raw(Heap::new(config))
}
#[no_mangle]
pub extern "C" fn comet_heap_free(heap: *mut Heap) {
unsafe {
Box::from_raw(heap);
}
}
#[no_mangle]
pub extern "C" fn comet_heap_add_constraint(
heap: *mut Heap,
data: *mut u8,
callback: extern "C" fn(*mut u8, *mut Visitor),
) {
unsafe {
(*heap).add_constraint(move |vis: &mut Visitor| {
let data = data;
callback(data, vis as *mut _);
});
}
}
#[no_mangle]
pub extern "C" fn comet_heap_add_core_constraints(heap: *mut Heap) {
unsafe {
(*heap).add_core_constraints();
}
}
#[no_mangle]
pub extern "C" fn comet_heap_collect(heap: *mut Heap) {
unsafe {
(*heap).collect_garbage();
}
}
#[no_mangle]
pub extern "C" fn comet_heap_collect_if_necessary_or_defer(heap: *mut Heap) {
unsafe {
(*heap).collect_if_necessary_or_defer();
}
}
#[no_mangle]
pub extern "C" fn comet_heap_allocate_weak(
heap: *mut Heap,
object: *mut HeapObjectHeader,
) -> WeakGcRef {
unsafe {
(*heap).allocate_weak(UntypedGcRef {
header: NonNull::new_unchecked(object),
})
}
}
#[no_mangle]
pub extern "C" fn comet_heap_allocate(
heap: *mut Heap,
size: usize,
index: GCInfoIndex,
) -> *mut HeapObjectHeader {
unsafe {
match (*heap).allocate_raw(size, index) {
Some(mem) => mem.header.as_ptr(),
None => null_mut(),
}
}
}
#[no_mangle]
pub extern "C" fn comet_heap_allocate_or_fail(
heap: *mut Heap,
size: usize,
index: GCInfoIndex,
) -> *mut HeapObjectHeader {
unsafe { (*heap).allocate_raw_or_fail(size, index).header.as_ptr() }
}
#[no_mangle]
pub extern "C" fn comet_weak_upgrade(weak: WeakGcRef) -> *mut HeapObjectHeader {
match weak.upgrade() {
Some(ptr) => ptr.header.as_ptr(),
None => null_mut(),
}
}
#[no_mangle]
pub extern "C" fn comet_trace(vis: *mut Visitor, ptr: *mut HeapObjectHeader) {
if ptr.is_null() {
return;
}
unsafe {
(*vis).trace_untyped(UntypedGcRef {
header: NonNull::new_unchecked(ptr),
})
}
}
#[no_mangle]
pub extern "C" fn comet_trace_conservatively(
vis: *mut Visitor,
from: *const u8,
to: *const u8,
) {
unsafe { (*vis).trace_conservatively(from, to) }
}
#[no_mangle]
pub extern "C" fn comet_add_gc_info(info: GCInfo) -> GCInfoIndex {
unsafe { GC_TABLE.add_gc_info(info) }
}
#[no_mangle]
pub extern "C" fn comet_get_gc_info(index: GCInfoIndex) -> *mut GCInfo {
unsafe { GC_TABLE.get_gc_info_mut(index) as *mut _ }
}
}