Skip to main content

gc/
heap.rs

1use crate::header::{GcId, GcObjectType, GcPhase};
2use crate::malloc::MallocState;
3use crate::report::{GcPhaseStats, GcStatsBundle};
4use crate::runtime::{GcObject, GcRuntime, MarkFunc};
5
6/// Opaque handle to a GC-managed object.
7#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
8pub struct GcRef(pub GcId);
9
10/// High-level heap API wrapping QuickJS-style `GcRuntime`.
11pub struct GcHeap {
12    rt: GcRuntime,
13}
14
15impl GcHeap {
16    pub fn new() -> Self {
17        GcHeap {
18            rt: GcRuntime::new(),
19        }
20    }
21
22    pub fn malloc_state(&self) -> &MallocState {
23        self.rt.malloc_state()
24    }
25
26    pub fn malloc_state_mut(&mut self) -> &mut MallocState {
27        self.rt.malloc_state_mut()
28    }
29
30    pub fn gc_threshold(&self) -> usize {
31        self.rt.gc_threshold()
32    }
33
34    pub fn set_gc_threshold(&mut self, threshold: usize) {
35        self.rt.set_gc_threshold(threshold);
36    }
37
38    pub fn gc_phase(&self) -> GcPhase {
39        self.rt.gc_phase()
40    }
41
42    pub fn alloc<O: GcObject>(&mut self, object: O, ty: GcObjectType) -> GcRef {
43        self.trigger_gc(std::mem::size_of::<O>());
44        GcRef(self.rt.add_gc_object(Box::new(object), ty))
45    }
46
47    pub fn dup(&mut self, reference: GcRef) -> GcRef {
48        GcRef(self.rt.dup_gc(reference.0))
49    }
50
51    pub fn free(&mut self, reference: GcRef) {
52        self.rt.free_gc(reference.0);
53    }
54
55    pub fn run_gc(&mut self) {
56        self.rt.run_gc();
57    }
58
59    pub fn run_gc_with_stats(&mut self) -> GcPhaseStats {
60        self.rt.run_gc_with_stats()
61    }
62
63    pub fn run_gc_with_stats_bundle(&mut self) -> GcStatsBundle {
64        self.rt.run_gc_with_stats_bundle()
65    }
66
67    pub fn trigger_gc(&mut self, alloc_size: usize) {
68        self.rt.trigger_gc(alloc_size);
69    }
70
71    pub fn is_live(&self, reference: GcRef) -> bool {
72        self.rt.is_live_object(reference.0)
73    }
74
75    pub fn exists(&self, reference: GcRef) -> bool {
76        self.rt.object_exists(reference.0)
77    }
78
79    pub fn ref_count(&self, reference: GcRef) -> i32 {
80        self.rt.ref_count(reference.0)
81    }
82
83    pub fn mark_children(&mut self, reference: GcRef, mark_func: MarkFunc) {
84        self.rt.mark_children(reference.0, mark_func);
85    }
86
87    #[cfg(test)]
88    pub(crate) fn header_mut(&mut self, reference: GcRef) -> &mut crate::header::GcObjectHeader {
89        self.rt.header_mut(reference.0)
90    }
91
92    pub fn runtime(&self) -> &GcRuntime {
93        &self.rt
94    }
95
96    pub fn runtime_mut(&mut self) -> &mut GcRuntime {
97        &mut self.rt
98    }
99}
100
101impl Default for GcHeap {
102    fn default() -> Self {
103        Self::new()
104    }
105}