Mark all reachable roots then sweep; non-heap Vals are no-op to mark. */
(&mut self, current_slots: &[Val])
| 5 | |
| 6 | /* Mark all reachable roots then sweep; non-heap Vals are no-op to mark. */ |
| 7 | pub(crate) fn collect(&mut self, current_slots: &[Val]) { |
| 8 | for &v in &self.stack { self.heap.mark(v); } |
| 9 | for &v in &self.with_stack { self.heap.mark(v); } |
| 10 | for &v in &self.temp_roots { self.heap.mark(v); } |
| 11 | for &v in &self.yields { self.heap.mark(v); } |
| 12 | for &v in &self.event_queue { self.heap.mark(v); } |
| 13 | // The handled exception and any pending finally return value outlive their stack slots. |
| 14 | if let Some(v) = self.pending.exc_val { self.heap.mark(v); } |
| 15 | self.heap.mark(self.yield_from_value); |
| 16 | if let Some(v) = self.handling_exc { self.heap.mark(v); } |
| 17 | for u in &self.unwind_stack { if let Unwind::Return(v) = u { self.heap.mark(*v); } } |
| 18 | // Scheduler holds parked coroutines (and their `WaitingForChildren` task lists) across `top_loop` resumes; mark them so the saved state isn't swept under us. |
| 19 | for handle in &self.scheduler { |
| 20 | self.heap.mark(handle.coro); |
| 21 | if let CoroState::WaitingForChildren { tasks, kind } = &handle.state { |
| 22 | for &t in tasks { self.heap.mark(t); } |
| 23 | match kind { |
| 24 | WaitKind::Run(t) => self.heap.mark(*t), |
| 25 | WaitKind::Timeout { target, .. } => self.heap.mark(*target), |
| 26 | WaitKind::Gather => {} |
| 27 | } |
| 28 | } |
| 29 | } |
| 30 | for &v in current_slots { self.heap.mark(v); } |
| 31 | for &v in &self.live_slots { self.heap.mark(v); } |
| 32 | // Closure cells live on the active call frames until the closures that capture them are built. |
| 33 | for frame in &self.call_stack { for &(_, c) in &frame.cells { self.heap.mark(c); } } |
| 34 | for tpl in &self.slot_templates { |
| 35 | for &v in tpl { self.heap.mark(v); } |
| 36 | } |
| 37 | for &v in self.globals.values() { self.heap.mark(v); } |
| 38 | for &v in self.module_state.values() { self.heap.mark(v); } |
| 39 | let heap = &mut self.heap; // split borrow: lets closures take &mut heap while iterating other fields |
| 40 | for frame in &self.iter_stack { frame.for_each_val(&mut |v| heap.mark(v)); } |
| 41 | for sf in &self.pending_sync_frames { sf.for_each_val(&mut |v| heap.mark(v)); } |
| 42 | for cache in self.opcode_caches.values() { |
| 43 | if let Some(consts) = cache.const_vals_opt() { |
| 44 | for &v in consts { self.heap.mark(v); } |
| 45 | } |
| 46 | // keep the IC's cached class + method Vals alive so a promoted slot can't reference a swept-and-reused slot. |
| 47 | for v in cache.inst_roots() { self.heap.mark(v); } |
| 48 | } |
| 49 | // SAFETY: each ptr is live for its exec() frame and the Vec's alloc is move-stable. |
| 50 | for i in 0..self.active_const_pools.len() { |
| 51 | let consts: &[Val] = unsafe { &*self.active_const_pools[i] }; |
| 52 | for &v in consts { self.heap.mark(v); } |
| 53 | } |
| 54 | self.templates.mark_all(&mut self.heap); |
| 55 | self.heap.sweep(); |
| 56 | } |
| 57 | } |