wasmtime/runtime/vm/instance/allocator/pooling/
gc_heap_pool.rs1use super::index_allocator::{SimpleIndexAllocator, SlotId};
2use super::GcHeapAllocationIndex;
3use crate::prelude::*;
4use crate::runtime::vm::{GcHeap, GcRuntime, PoolingInstanceAllocatorConfig, Result};
5use std::sync::Mutex;
6
7pub struct GcHeapPool {
9 max_gc_heaps: usize,
10 index_allocator: SimpleIndexAllocator,
11 heaps: Mutex<Vec<Option<Box<dyn GcHeap>>>>,
12}
13
14impl std::fmt::Debug for GcHeapPool {
15 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
16 f.debug_struct("GcHeapPool")
17 .field("max_gc_heaps", &self.max_gc_heaps)
18 .field("index_allocator", &self.index_allocator)
19 .field("heaps", &"..")
20 .finish()
21 }
22}
23
24impl GcHeapPool {
25 pub fn new(config: &PoolingInstanceAllocatorConfig) -> Result<Self> {
27 let index_allocator = SimpleIndexAllocator::new(config.limits.total_gc_heaps);
28 let max_gc_heaps = usize::try_from(config.limits.total_gc_heaps).unwrap();
29
30 let heaps = Mutex::new((0..max_gc_heaps).map(|_| None).collect());
33
34 Ok(Self {
35 max_gc_heaps,
36 index_allocator,
37 heaps,
38 })
39 }
40
41 #[allow(unused)] pub fn is_empty(&self) -> bool {
44 self.index_allocator.is_empty()
45 }
46
47 pub fn allocate(
49 &self,
50 gc_runtime: &dyn GcRuntime,
51 ) -> Result<(GcHeapAllocationIndex, Box<dyn GcHeap>)> {
52 let allocation_index = self
53 .index_allocator
54 .alloc()
55 .map(|slot| GcHeapAllocationIndex(slot.0))
56 .ok_or_else(|| {
57 anyhow!(
58 "maximum concurrent GC heap limit of {} reached",
59 self.max_gc_heaps
60 )
61 })?;
62 debug_assert_ne!(allocation_index, GcHeapAllocationIndex::default());
63
64 let heap = match {
65 let mut heaps = self.heaps.lock().unwrap();
66 heaps[allocation_index.index()].take()
67 } {
68 Some(heap) => heap,
70 None => gc_runtime.new_gc_heap()?,
73 };
74
75 Ok((allocation_index, heap))
76 }
77
78 pub fn deallocate(&self, allocation_index: GcHeapAllocationIndex, mut heap: Box<dyn GcHeap>) {
80 debug_assert_ne!(allocation_index, GcHeapAllocationIndex::default());
81 heap.reset();
82
83 {
88 let mut heaps = self.heaps.lock().unwrap();
89 let old_entry = std::mem::replace(&mut heaps[allocation_index.index()], Some(heap));
90 debug_assert!(old_entry.is_none());
91 }
92
93 self.index_allocator.free(SlotId(allocation_index.0));
94 }
95}