(&self, generation: usize, force: bool)
| 382 | } |
| 383 | |
| 384 | fn collect_inner(&self, generation: usize, force: bool) -> CollectResult { |
| 385 | if !force && !self.is_enabled() { |
| 386 | return CollectResult::default(); |
| 387 | } |
| 388 | |
| 389 | // Try to acquire the collecting lock |
| 390 | let Some(_guard) = self.collecting.try_lock() else { |
| 391 | return CollectResult::default(); |
| 392 | }; |
| 393 | |
| 394 | #[cfg(not(target_arch = "wasm32"))] |
| 395 | let start_time = std::time::Instant::now(); |
| 396 | #[cfg(target_arch = "wasm32")] |
| 397 | let start_time = (); |
| 398 | |
| 399 | // Memory barrier to ensure visibility of all reference count updates |
| 400 | // from other threads before we start analyzing the object graph. |
| 401 | core::sync::atomic::fence(Ordering::SeqCst); |
| 402 | |
| 403 | let generation = generation.min(2); |
| 404 | let debug = self.get_debug(); |
| 405 | |
| 406 | // Clear the method cache to release strong references that |
| 407 | // might prevent cycle collection (_PyType_ClearCache). |
| 408 | crate::builtins::type_::type_cache_clear(); |
| 409 | |
| 410 | // Step 1: Gather objects from generations 0..=generation |
| 411 | // Hold read locks for the entire scan to prevent concurrent modifications. |
| 412 | let gen_locks: Vec<_> = (0..=generation) |
| 413 | .map(|i| self.generation_lists[i].read()) |
| 414 | .collect(); |
| 415 | |
| 416 | let mut collecting: HashSet<GcPtr> = HashSet::new(); |
| 417 | for gen_list in &gen_locks { |
| 418 | for obj in gen_list.iter() { |
| 419 | if obj.strong_count() > 0 { |
| 420 | collecting.insert(GcPtr(NonNull::from(obj))); |
| 421 | } |
| 422 | } |
| 423 | } |
| 424 | |
| 425 | if collecting.is_empty() { |
| 426 | // Reset counts for generations whose objects were promoted away. |
| 427 | // For gen2 (oldest), survivors stay in-place so don't reset gen2 count. |
| 428 | let reset_end = if generation >= 2 { 2 } else { generation + 1 }; |
| 429 | for i in 0..reset_end { |
| 430 | self.generations[i].count.store(0, Ordering::SeqCst); |
| 431 | } |
| 432 | let duration = elapsed_secs(&start_time); |
| 433 | self.generations[generation].update_stats(0, 0, 0, duration); |
| 434 | return CollectResult { |
| 435 | collected: 0, |
| 436 | uncollectable: 0, |
| 437 | candidates: 0, |
| 438 | duration, |
| 439 | }; |
| 440 | } |
| 441 |
no test coverage detected