MCPcopy Index your code
hub / github.com/aiscriptdev/aiscript / do_collection_inner

Method do_collection_inner

aiscript-arena/src/context.rs:277–433  ·  view source on GitHub ↗
(
        &self,
        root: &R,
        mut target_debt: f64,
        early_stop: Option<EarlyStop>,
    )

Source from the content-addressed store, hash-verified

275 }
276
277 fn do_collection_inner<R: Collect + ?Sized>(
278 &self,
279 root: &R,
280 mut target_debt: f64,
281 early_stop: Option<EarlyStop>,
282 ) {
283 let mut entered = PhaseGuard::enter(self, None);
284
285 if !(self.metrics.allocation_debt() > target_debt) {
286 entered.log_progress("GC: paused");
287 return;
288 }
289
290 loop {
291 match self.phase.get() {
292 Phase::Sleep => {
293 // Immediately enter the mark phase; no need to update metrics here.
294 entered.switch(Phase::Mark);
295 continue;
296 }
297 Phase::Mark => {
298 // We look for an object first in the normal gray queue, then the "gray again"
299 // queue. Objects from the normal gray queue count as regular work, but objects
300 // which are gray a second time have already been counted as work, so we don't
301 // double count them. Processing "gray again" objects later also gives them more
302 // time to be mutated again without triggering another write barrier.
303 let next_gray = if let Some(gc_box) = self.gray.borrow_mut().pop() {
304 self.metrics.mark_gc_traced(gc_box.header().size_of_box());
305 Some(gc_box)
306 } else {
307 self.gray_again.borrow_mut().pop()
308 };
309
310 if let Some(gc_box) = next_gray {
311 // If we have an object in the gray queue, take one, trace it, and turn it
312 // black.
313
314 // Our `Collect::trace` call may panic, and if it does the object will be
315 // lost from the gray queue but potentially incompletely traced. By catching
316 // a panic during `Arena::collect()`, this could lead to memory unsafety.
317 //
318 // So, if the `Collect::trace` call panics, we need to add the popped object
319 // back to the `gray_again` queue. If the panic is caught, this will maybe
320 // give it some time to not panic before attempting to collect it again, and
321 // also this doesn't invalidate the collection debt math.
322 struct DropGuard<'a> {
323 cx: &'a Context,
324 gc_box: GcBox,
325 }
326
327 impl Drop for DropGuard<'_> {
328 fn drop(&mut self) {
329 self.cx.gray_again.borrow_mut().push(self.gc_box);
330 }
331 }
332
333 let guard = DropGuard { cx: self, gc_box };
334 debug_assert!(gc_box.header().is_live());

Callers 1

do_collectionMethod · 0.80

Calls 15

free_gc_boxFunction · 0.85
allocation_debtMethod · 0.80
log_progressMethod · 0.80
switchMethod · 0.80
mark_gc_tracedMethod · 0.80
size_of_boxMethod · 0.80
headerMethod · 0.80
trace_valueMethod · 0.80
collection_contextMethod · 0.80
set_colorMethod · 0.80
colorMethod · 0.80
set_nextMethod · 0.80

Tested by

no test coverage detected