Skip to main content

qanglang_core/memory/
closure_upvalue_reference.rs

1use crate::{arena::Index, memory::ClosureHandle};
2
3pub type UpvalueOverflowHandle = Index;
4
5const INLINE_UPVALUE_CAPACITY: usize = 4;
6
7#[derive(Debug, Clone)]
8pub struct OpenUpvalueTracker {
9    inline_entries: [(ClosureHandle, usize); INLINE_UPVALUE_CAPACITY],
10    count: usize,
11    overflow_handle: Option<UpvalueOverflowHandle>,
12}
13
14impl Default for OpenUpvalueTracker {
15    fn default() -> Self {
16        Self {
17            inline_entries: [(ClosureHandle::default(), 0); INLINE_UPVALUE_CAPACITY],
18            count: 0,
19            overflow_handle: None,
20        }
21    }
22}
23
24impl OpenUpvalueTracker {
25    pub fn new() -> Self {
26        Self::default()
27    }
28
29    pub fn add_closure(
30        &mut self,
31        closure_handle: ClosureHandle,
32        upvalue_index: usize,
33        overflow_arena: &mut crate::memory::UpvalueOverflowArena,
34    ) {
35        if self.count < INLINE_UPVALUE_CAPACITY {
36            self.inline_entries[self.count] = (closure_handle, upvalue_index);
37            self.count += 1;
38            return;
39        }
40
41        // Need overflow storage
42        if self.overflow_handle.is_none() {
43            let handle = overflow_arena.allocate_chunk();
44            self.overflow_handle = Some(handle);
45        }
46
47        // Find the last chunk in the chain
48        let mut current_handle = self.overflow_handle.unwrap();
49        loop {
50            {
51                let chunk = overflow_arena.get_chunk_mut(current_handle);
52                if chunk.count < crate::memory::upvalue_overflow_arena::OVERFLOW_CHUNK_SIZE {
53                    chunk.entries[chunk.count] = (closure_handle, upvalue_index);
54                    chunk.count += 1;
55                    return;
56                }
57            }
58
59            let next_handle = {
60                let chunk = overflow_arena.get_chunk(current_handle);
61                chunk.next
62            };
63
64            if let Some(next) = next_handle {
65                current_handle = next;
66            } else {
67                // Last chunk is full, create a new one
68                let new_handle = overflow_arena.allocate_chunk();
69                overflow_arena.get_chunk_mut(current_handle).next = Some(new_handle);
70                let new_chunk = overflow_arena.get_chunk_mut(new_handle);
71                new_chunk.entries[0] = (closure_handle, upvalue_index);
72                new_chunk.count = 1;
73                return;
74            }
75        }
76    }
77
78    pub fn iter(&self) -> impl Iterator<Item = (ClosureHandle, usize)> + '_ {
79        self.inline_entries[..self.count].iter().copied()
80    }
81
82    pub fn iter_all_entries<'a>(
83        &'a self,
84        overflow_arena: &'a crate::memory::UpvalueOverflowArena,
85    ) -> impl Iterator<Item = (ClosureHandle, usize)> + 'a {
86        UpvalueEntryIterator::new(self, overflow_arena)
87    }
88
89    pub fn overflow_handle(&self) -> Option<UpvalueOverflowHandle> {
90        self.overflow_handle
91    }
92
93    pub fn set_overflow_handle(&mut self, handle: UpvalueOverflowHandle) {
94        self.overflow_handle = Some(handle);
95    }
96
97    pub fn len(&self, overflow_arena: &crate::memory::UpvalueOverflowArena) -> usize {
98        let mut total = self.count;
99
100        if let Some(mut current_handle) = self.overflow_handle {
101            loop {
102                let chunk = overflow_arena.get_chunk(current_handle);
103                total += chunk.count;
104                if let Some(next_handle) = chunk.next {
105                    current_handle = next_handle;
106                } else {
107                    break;
108                }
109            }
110        }
111
112        total
113    }
114
115    pub fn is_empty(&self) -> bool {
116        self.count == 0
117    }
118
119    pub fn mark_overflow_chunks(&self, overflow_arena: &mut crate::memory::UpvalueOverflowArena) {
120        if let Some(mut current_handle) = self.overflow_handle {
121            loop {
122                overflow_arena.mark_chunk(current_handle);
123                let chunk = overflow_arena.get_chunk(current_handle);
124                if let Some(next_handle) = chunk.next {
125                    current_handle = next_handle;
126                } else {
127                    break;
128                }
129            }
130        }
131    }
132}
133
134struct UpvalueEntryIterator<'a> {
135    tracker: &'a OpenUpvalueTracker,
136    overflow_arena: &'a crate::memory::UpvalueOverflowArena,
137    inline_index: usize,
138    current_chunk: Option<UpvalueOverflowHandle>,
139    chunk_index: usize,
140}
141
142impl<'a> UpvalueEntryIterator<'a> {
143    fn new(
144        tracker: &'a OpenUpvalueTracker,
145        overflow_arena: &'a crate::memory::UpvalueOverflowArena,
146    ) -> Self {
147        Self {
148            tracker,
149            overflow_arena,
150            inline_index: 0,
151            current_chunk: tracker.overflow_handle,
152            chunk_index: 0,
153        }
154    }
155}
156
157impl<'a> Iterator for UpvalueEntryIterator<'a> {
158    type Item = (ClosureHandle, usize);
159
160    fn next(&mut self) -> Option<Self::Item> {
161        // First, iterate through inline entries
162        if self.inline_index < self.tracker.count {
163            let entry = self.tracker.inline_entries[self.inline_index];
164            self.inline_index += 1;
165            return Some(entry);
166        }
167
168        // Then iterate through overflow chunks
169        while let Some(chunk_handle) = self.current_chunk {
170            let chunk = self.overflow_arena.get_chunk(chunk_handle);
171
172            if self.chunk_index < chunk.count {
173                let entry = chunk.entries[self.chunk_index];
174                self.chunk_index += 1;
175                return Some(entry);
176            }
177
178            // Move to next chunk
179            self.current_chunk = chunk.next;
180            self.chunk_index = 0;
181        }
182
183        None
184    }
185}