qanglang_core/memory/
upvalue_overflow_arena.rs1use crate::arena::{Arena, Index};
2use crate::memory::ClosureHandle;
3
4pub const OVERFLOW_CHUNK_SIZE: usize = 8;
5
6pub type UpvalueOverflowHandle = Index;
7
8#[derive(Debug, Clone)]
9pub struct UpvalueOverflowChunk {
10 pub entries: [(ClosureHandle, usize); OVERFLOW_CHUNK_SIZE],
11 pub count: usize,
12 pub is_marked: bool,
13 pub next: Option<UpvalueOverflowHandle>,
14}
15
16impl Default for UpvalueOverflowChunk {
17 fn default() -> Self {
18 Self {
19 entries: [(ClosureHandle::default(), 0); OVERFLOW_CHUNK_SIZE],
20 count: 0,
21 is_marked: false,
22 next: None,
23 }
24 }
25}
26
27#[derive(Debug, Default, Clone)]
28pub struct UpvalueOverflowArena {
29 chunks: Arena<UpvalueOverflowChunk>,
30}
31
32impl UpvalueOverflowArena {
33 pub fn new() -> Self {
34 Self::with_capacity(32)
35 }
36
37 pub fn with_capacity(capacity: usize) -> Self {
38 Self {
39 chunks: Arena::with_capacity(capacity),
40 }
41 }
42
43 pub fn allocate_chunk(&mut self) -> UpvalueOverflowHandle {
44 self.chunks.insert(UpvalueOverflowChunk::default())
45 }
46
47 pub fn get_chunk(&self, handle: UpvalueOverflowHandle) -> &UpvalueOverflowChunk {
48 &self.chunks[handle]
49 }
50
51 pub fn get_chunk_mut(&mut self, handle: UpvalueOverflowHandle) -> &mut UpvalueOverflowChunk {
52 &mut self.chunks[handle]
53 }
54
55 pub fn mark_chunk(&mut self, handle: UpvalueOverflowHandle) {
56 if let Some(chunk) = self.chunks.get_mut(handle) {
57 chunk.is_marked = true;
58 }
59 }
60
61 pub fn collect_garbage(&mut self) {
62 let estimated_deletions = (self.chunks.len() / 4).max(8);
63 let mut handles_to_remove = Vec::with_capacity(estimated_deletions);
64
65 for (handle, chunk) in self.chunks.iter_mut() {
66 if chunk.is_marked {
67 chunk.is_marked = false;
68 } else {
69 handles_to_remove.push(handle);
70 }
71 }
72
73 for handle in handles_to_remove {
74 self.chunks.remove(handle);
75 }
76 }
77
78 pub fn get_allocated_bytes(&self) -> usize {
79 self.chunks.len() * std::mem::size_of::<UpvalueOverflowChunk>()
80 }
81}