mmtk/vm/
collection.rs

1use crate::util::alloc::AllocationError;
2use crate::util::heap::gc_trigger::GCTriggerPolicy;
3use crate::util::opaque_pointer::*;
4use crate::vm::VMBinding;
5use crate::{scheduler::*, Mutator};
6
7/// Thread context for the spawned GC thread.  It is used by `spawn_gc_thread`.
8/// Currently, `GCWorker` is the only kind of thread that mmtk-core will create.
9pub enum GCThreadContext<VM: VMBinding> {
10    /// The GC thread to spawn is a worker thread. There can be multiple worker threads.
11    Worker(Box<GCWorker<VM>>),
12}
13
14/// VM-specific methods for garbage collection.
15pub trait Collection<VM: VMBinding> {
16    /// Stop all the mutator threads. MMTk calls this method when it requires all the mutator to yield for a GC.
17    /// This method should not return until all the threads are yielded.
18    /// The actual thread synchronization mechanism is up to the VM, and MMTk does not make assumptions on that.
19    /// MMTk provides a callback function and expects the binding to use the callback for each mutator when it
20    /// is ready for stack scanning. Usually a stack can be scanned as soon as the thread stops in the yieldpoint.
21    ///
22    /// Arguments:
23    /// * `tls`: The thread pointer for the GC worker.
24    /// * `mutator_visitor`: A callback.  Call it with a mutator as argument to notify MMTk that the mutator is ready to be scanned.
25    fn stop_all_mutators<F>(tls: VMWorkerThread, mutator_visitor: F)
26    where
27        F: FnMut(&'static mut Mutator<VM>);
28
29    /// Resume all the mutator threads, the opposite of the above. When a GC is finished, MMTk calls this method.
30    ///
31    /// This method may not be called by the same GC thread that called `stop_all_mutators`.
32    ///
33    /// Arguments:
34    /// * `tls`: The thread pointer for the GC worker.
35    fn resume_mutators(tls: VMWorkerThread);
36
37    /// Block the current thread for GC. This is called when an allocation request cannot be fulfilled and a GC
38    /// is needed. MMTk calls this method to inform the VM that the current thread needs to be blocked as a GC
39    /// is going to happen. Then MMTk starts a GC. For a stop-the-world GC, MMTk will then call `stop_all_mutators()`
40    /// before the GC, and call `resume_mutators()` after the GC.
41    ///
42    /// Arguments:
43    /// * `tls`: The current thread pointer that should be blocked. The VM can optionally check if the current thread matches `tls`.
44    fn block_for_gc(tls: VMMutatorThread);
45
46    /// Ask the VM to spawn a GC thread for MMTk. A GC thread may later call into the VM through these VM traits. Some VMs
47    /// have assumptions that those calls needs to be within VM internal threads.
48    /// As a result, MMTk does not spawn GC threads itself to avoid breaking this kind of assumptions.
49    /// MMTk calls this method to spawn GC threads during [`crate::mmtk::MMTK::initialize_collection`]
50    /// and [`crate::mmtk::MMTK::after_fork`].
51    ///
52    /// Arguments:
53    /// * `tls`: The thread pointer for the parent thread that we spawn new threads from. This is the same `tls` when the VM
54    ///   calls `initialize_collection()` and passes as an argument.
55    /// * `ctx`: The context for the GC thread.
56    ///   * If [`GCThreadContext::Worker`] is passed, it means spawning a thread to run as a GC worker.
57    ///     The spawned thread shall call the entry point function `GCWorker::run`.
58    ///     Currently `Worker` is the only kind of thread which mmtk-core will create.
59    fn spawn_gc_thread(tls: VMThread, ctx: GCThreadContext<VM>);
60
61    /// Inform the VM of an out-of-memory error. The binding should hook into the VM's error
62    /// routine for OOM. Note that there are two different categories of OOM:
63    ///  * Critical OOM: This is the case where the OS is unable to mmap or acquire more memory.
64    ///    MMTk expects the VM to abort immediately if such an error is thrown.
65    ///  * Heap OOM: This is the case where the specified heap size is insufficient to execute the
66    ///    application. MMTk expects the binding to notify the VM about this OOM. MMTk makes no
67    ///    assumptions about whether the VM will continue executing or abort immediately.
68    ///
69    /// See [`AllocationError`] for more information.
70    ///
71    /// Arguments:
72    /// * `tls`: The thread pointer for the mutator which failed the allocation and triggered the OOM.
73    /// * `err_kind`: The type of OOM error that was encountered.
74    fn out_of_memory(_tls: VMThread, err_kind: AllocationError) {
75        panic!("Out of memory with {:?}!", err_kind);
76    }
77
78    /// Inform the VM to schedule finalization threads.
79    ///
80    /// Arguments:
81    /// * `tls`: The thread pointer for the current GC thread.
82    fn schedule_finalization(_tls: VMWorkerThread) {}
83
84    /// A hook for the VM to do work after forwarding objects.
85    ///
86    /// This function is called after all of the following have finished:
87    /// -   The life and death of objects are determined.  Objects determined to be live will not
88    ///     be reclaimed in this GC.
89    /// -   Live objects have been moved to their destinations. (copying GC only)
90    /// -   References in objects have been updated to point to new addresses. (copying GC only)
91    ///
92    /// And this function may run concurrently with the release work of GC, i.e. freeing the space
93    /// occupied by dead objects.
94    ///
95    /// It is safe for the VM to read and write object fields at this time, although GC has not
96    /// finished yet.  GC will be reclaiming spaces of dead objects, but will not damage live
97    /// objects.  However, the VM cannot allocate new objects at this time.
98    ///
99    /// One possible use of this hook is enqueuing `{Soft,Weak,Phantom}Reference` instances to
100    /// reference queues (for Java).  VMs (including JVM implementations) do not have to handle
101    /// weak references this way, but mmtk-core provides this opportunity.
102    ///
103    /// Arguments:
104    /// * `tls_worker`: The thread pointer for the worker thread performing this call.
105    fn post_forwarding(_tls: VMWorkerThread) {}
106
107    /// Return the amount of memory (in bytes) which the VM allocated outside the MMTk heap but
108    /// wants to include into the current MMTk heap size.  MMTk core will consider the reported
109    /// memory as part of MMTk heap for the purpose of heap size accounting.
110    ///
111    /// This amount should include memory that is kept alive by heap objects and can be released by
112    /// executing finalizers (or other language-specific cleaning-up routines) that are executed
113    /// when the heap objects are dead.  For example, if a language implementation allocates array
114    /// headers in the MMTk heap, but allocates their underlying buffers that hold the actual
115    /// elements using `malloc`, then those buffers should be included in this amount.  When the GC
116    /// finds such an array dead, its finalizer shall `free` the buffer and reduce this amount.
117    ///
118    /// If possible, the VM should account off-heap memory in pages.  That is, count the number of
119    /// pages occupied by off-heap objects, and report the number of bytes of those whole pages
120    /// instead of individual objects.  Because the underlying operating system manages memory at
121    /// page granularity, the occupied pages (instead of individual objects) determine the memory
122    /// footprint of a process, and how much memory MMTk spaces can obtain from the OS.
123    ///
124    /// However, if the VM is incapable of accounting off-heap memory in pages (for example, if the
125    /// VM uses `malloc` and the implementation of `malloc` is opaque to the VM), the VM binding
126    /// can simply return the total number of bytes of those off-heap objects as an approximation.
127    ///
128    /// # Performance note
129    ///
130    /// This function will be called when MMTk polls for GC.  It happens every time the MMTk
131    /// allocators have allocated a certain amount of memory, usually one or a few blocks.  Because
132    /// this function is called very frequently, its implementation must be efficient.  If it is
133    /// too expensive to compute the exact amount, an approximate value should be sufficient for
134    /// MMTk to trigger GC promptly in order to release off-heap memory, and keep the memory
135    /// footprint under control.
136    fn vm_live_bytes() -> usize {
137        // By default, MMTk assumes the amount of memory the VM allocates off-heap is negligible.
138        0
139    }
140
141    /// Callback function to ask the VM whether GC is enabled or disabled, allowing or disallowing MMTk
142    /// to trigger garbage collection. When collection is disabled, you can still allocate through MMTk,
143    /// but MMTk will not trigger a GC even if the heap is full. In such a case, the allocation will
144    /// exceed MMTk's heap size (the soft heap limit). However, there is no guarantee that the physical
145    /// allocation will succeed, and if it succeeds, there is no guarantee that further allocation will
146    /// keep succeeding. So if a VM disables collection, it needs to allocate with careful consideration
147    /// to make sure that the physical memory allows the amount of allocation. We highly recommend
148    /// to have GC always enabled (i.e. that this method always returns true). However, we support
149    /// this to accomodate some VMs that require this behavior. Note that
150    /// `handle_user_collection_request()` calls this function, too.  If this function returns
151    /// false, `handle_user_collection_request()` will not trigger GC, either. Note also that any synchronization
152    /// involving enabling and disabling collections by mutator threads should be implemented by the VM.
153    fn is_collection_enabled() -> bool {
154        // By default, MMTk assumes that collections are always enabled, and the binding should define
155        // this method if the VM supports disabling GC, or if the VM cannot safely trigger GC until some
156        // initialization is done, such as initializing class metadata for scanning objects.
157        true
158    }
159
160    /// Ask the binding to create a [`GCTriggerPolicy`] if the option `gc_trigger` is set to
161    /// `crate::util::options::GCTriggerSelector::Delegated`.
162    fn create_gc_trigger() -> Box<dyn GCTriggerPolicy<VM>> {
163        unimplemented!()
164    }
165}