Skip to main content

aver/nan_value/
arena.rs

1use super::*;
2
3impl Arena {
4    pub fn new() -> Self {
5        Arena {
6            young_entries: Vec::with_capacity(256),
7            yard_entries: Vec::with_capacity(64),
8            handoff_entries: Vec::with_capacity(64),
9            stable_entries: Vec::with_capacity(64),
10            scratch_young: Vec::new(),
11            scratch_yard: Vec::new(),
12            scratch_handoff: Vec::new(),
13            scratch_stable: Vec::new(),
14            peak_usage: ArenaUsage::default(),
15            alloc_space: AllocSpace::Young,
16            type_names: Vec::new(),
17            type_field_names: Vec::new(),
18            type_variant_names: Vec::new(),
19        }
20    }
21
22    #[inline]
23    pub fn push(&mut self, entry: ArenaEntry) -> u32 {
24        match self.alloc_space {
25            AllocSpace::Young => {
26                let idx = self.young_entries.len() as u32;
27                self.young_entries.push(entry);
28                self.note_peak_usage();
29                Self::encode_index(HeapSpace::Young, idx)
30            }
31            AllocSpace::Yard => {
32                let idx = self.yard_entries.len() as u32;
33                self.yard_entries.push(entry);
34                self.note_peak_usage();
35                Self::encode_index(HeapSpace::Yard, idx)
36            }
37            AllocSpace::Handoff => {
38                let idx = self.handoff_entries.len() as u32;
39                self.handoff_entries.push(entry);
40                self.note_peak_usage();
41                Self::encode_index(HeapSpace::Handoff, idx)
42            }
43        }
44    }
45
46    #[inline]
47    pub fn get(&self, index: u32) -> &ArenaEntry {
48        let (space, raw_index) = Self::decode_index(index);
49        match space {
50            HeapSpace::Young => &self.young_entries[raw_index as usize],
51            HeapSpace::Yard => &self.yard_entries[raw_index as usize],
52            HeapSpace::Handoff => &self.handoff_entries[raw_index as usize],
53            HeapSpace::Stable => &self.stable_entries[raw_index as usize],
54        }
55    }
56
57    #[inline]
58    pub(super) fn encode_index(space: HeapSpace, index: u32) -> u32 {
59        ((space as u32) << HEAP_SPACE_SHIFT) | index
60    }
61
62    #[inline]
63    pub(super) fn encode_yard_index(index: u32) -> u32 {
64        Self::encode_index(HeapSpace::Yard, index)
65    }
66
67    #[inline]
68    pub(super) fn encode_stable_index(index: u32) -> u32 {
69        Self::encode_index(HeapSpace::Stable, index)
70    }
71
72    #[inline]
73    pub(super) fn encode_handoff_index(index: u32) -> u32 {
74        Self::encode_index(HeapSpace::Handoff, index)
75    }
76
77    #[inline]
78    pub(super) fn decode_index(index: u32) -> (HeapSpace, u32) {
79        let space = match (index & HEAP_SPACE_MASK_U32) >> HEAP_SPACE_SHIFT {
80            0 => HeapSpace::Young,
81            1 => HeapSpace::Yard,
82            2 => HeapSpace::Handoff,
83            3 => HeapSpace::Stable,
84            _ => unreachable!("invalid heap space bits"),
85        };
86        (space, index & HEAP_INDEX_MASK_U32)
87    }
88
89    #[inline]
90    pub fn is_stable_index(index: u32) -> bool {
91        matches!(Self::decode_index(index).0, HeapSpace::Stable)
92    }
93
94    #[inline]
95    pub fn is_yard_index_in_region(&self, index: u32, mark: u32) -> bool {
96        let (space, raw_index) = Self::decode_index(index);
97        matches!(space, HeapSpace::Yard)
98            && raw_index >= mark
99            && raw_index < self.yard_entries.len() as u32
100    }
101
102    #[inline]
103    pub fn is_handoff_index_in_region(&self, index: u32, mark: u32) -> bool {
104        let (space, raw_index) = Self::decode_index(index);
105        matches!(space, HeapSpace::Handoff)
106            && raw_index >= mark
107            && raw_index < self.handoff_entries.len() as u32
108    }
109
110    #[inline]
111    pub fn is_young_index_in_region(&self, index: u32, mark: u32) -> bool {
112        let (space, raw_index) = Self::decode_index(index);
113        matches!(space, HeapSpace::Young)
114            && raw_index >= mark
115            && raw_index < self.young_entries.len() as u32
116    }
117
118    #[inline]
119    pub fn young_len(&self) -> usize {
120        self.young_entries.len()
121    }
122
123    #[inline]
124    pub fn yard_len(&self) -> usize {
125        self.yard_entries.len()
126    }
127
128    #[inline]
129    pub fn handoff_len(&self) -> usize {
130        self.handoff_entries.len()
131    }
132
133    #[inline]
134    pub fn stable_len(&self) -> usize {
135        self.stable_entries.len()
136    }
137
138    #[inline]
139    pub fn usage(&self) -> ArenaUsage {
140        ArenaUsage {
141            young: self.young_entries.len(),
142            yard: self.yard_entries.len(),
143            handoff: self.handoff_entries.len(),
144            stable: self.stable_entries.len(),
145        }
146    }
147
148    #[inline]
149    pub fn peak_usage(&self) -> ArenaUsage {
150        self.peak_usage
151    }
152
153    #[inline]
154    pub(super) fn note_peak_usage(&mut self) {
155        let usage = self.usage();
156        self.peak_usage.young = self.peak_usage.young.max(usage.young);
157        self.peak_usage.yard = self.peak_usage.yard.max(usage.yard);
158        self.peak_usage.handoff = self.peak_usage.handoff.max(usage.handoff);
159        self.peak_usage.stable = self.peak_usage.stable.max(usage.stable);
160    }
161
162    #[inline]
163    pub(super) fn take_u32_scratch(slot: &mut Vec<u32>, len: usize) -> Vec<u32> {
164        let mut scratch = std::mem::take(slot);
165        scratch.clear();
166        scratch.resize(len, u32::MAX);
167        scratch
168    }
169
170    #[inline]
171    pub(super) fn recycle_u32_scratch(slot: &mut Vec<u32>, mut scratch: Vec<u32>) {
172        scratch.clear();
173        *slot = scratch;
174    }
175
176    #[inline]
177    pub fn is_frame_local_index(
178        &self,
179        index: u32,
180        arena_mark: u32,
181        yard_mark: u32,
182        handoff_mark: u32,
183    ) -> bool {
184        self.is_young_index_in_region(index, arena_mark)
185            || self.is_yard_index_in_region(index, yard_mark)
186            || self.is_handoff_index_in_region(index, handoff_mark)
187    }
188
189    pub fn with_alloc_space<T>(&mut self, space: AllocSpace, f: impl FnOnce(&mut Arena) -> T) -> T {
190        let prev = self.alloc_space;
191        self.alloc_space = space;
192        let out = f(self);
193        self.alloc_space = prev;
194        out
195    }
196
197    // -- Typed push helpers ------------------------------------------------
198
199    pub fn push_i64(&mut self, val: i64) -> u32 {
200        self.push(ArenaEntry::Int(val))
201    }
202    pub fn push_string(&mut self, s: &str) -> u32 {
203        self.push(ArenaEntry::String(Rc::from(s)))
204    }
205    pub fn push_boxed(&mut self, val: NanValue) -> u32 {
206        self.push(ArenaEntry::Boxed(val))
207    }
208    pub fn push_record(&mut self, type_id: u32, fields: Vec<NanValue>) -> u32 {
209        self.push(ArenaEntry::Record { type_id, fields })
210    }
211    pub fn push_variant(&mut self, type_id: u32, variant_id: u16, fields: Vec<NanValue>) -> u32 {
212        self.push(ArenaEntry::Variant {
213            type_id,
214            variant_id,
215            fields,
216        })
217    }
218    pub fn push_list(&mut self, items: Vec<NanValue>) -> u32 {
219        self.push(ArenaEntry::List(ArenaList::Flat {
220            items: Rc::new(items),
221            start: 0,
222        }))
223    }
224    pub fn push_map(&mut self, map: PersistentMap) -> u32 {
225        self.push(ArenaEntry::Map(map))
226    }
227    pub fn push_tuple(&mut self, items: Vec<NanValue>) -> u32 {
228        self.push(ArenaEntry::Tuple(items))
229    }
230    pub fn push_fn(&mut self, f: Rc<FunctionValue>) -> u32 {
231        self.push(ArenaEntry::Fn(f))
232    }
233    pub fn push_builtin(&mut self, name: &str) -> u32 {
234        self.push(ArenaEntry::Builtin(Rc::from(name)))
235    }
236
237    // -- Typed getters -----------------------------------------------------
238
239    pub fn get_i64(&self, index: u32) -> i64 {
240        match self.get(index) {
241            ArenaEntry::Int(i) => *i,
242            _ => panic!("Arena: expected Int at {}", index),
243        }
244    }
245    pub fn get_string(&self, index: u32) -> &str {
246        match self.get(index) {
247            ArenaEntry::String(s) => s,
248            other => panic!("Arena: expected String at {} but found {:?}", index, other),
249        }
250    }
251    pub fn get_boxed(&self, index: u32) -> NanValue {
252        match self.get(index) {
253            ArenaEntry::Boxed(v) => *v,
254            _ => panic!("Arena: expected Boxed at {}", index),
255        }
256    }
257    pub fn get_record(&self, index: u32) -> (u32, &[NanValue]) {
258        match self.get(index) {
259            ArenaEntry::Record { type_id, fields } => (*type_id, fields),
260            _ => panic!("Arena: expected Record at {}", index),
261        }
262    }
263    pub fn get_variant(&self, index: u32) -> (u32, u16, &[NanValue]) {
264        match self.get(index) {
265            ArenaEntry::Variant {
266                type_id,
267                variant_id,
268                fields,
269            } => (*type_id, *variant_id, fields),
270            other => panic!("Arena: expected Variant at {} but found {:?}", index, other),
271        }
272    }
273    pub fn get_list(&self, index: u32) -> &ArenaList {
274        match self.get(index) {
275            ArenaEntry::List(items) => items,
276            _ => panic!("Arena: expected List at {}", index),
277        }
278    }
279    pub fn get_tuple(&self, index: u32) -> &[NanValue] {
280        match self.get(index) {
281            ArenaEntry::Tuple(items) => items,
282            _ => panic!("Arena: expected Tuple at {}", index),
283        }
284    }
285    pub fn get_map(&self, index: u32) -> &PersistentMap {
286        match self.get(index) {
287            ArenaEntry::Map(map) => map,
288            _ => panic!("Arena: expected Map at {}", index),
289        }
290    }
291    pub fn get_fn(&self, index: u32) -> &FunctionValue {
292        match self.get(index) {
293            ArenaEntry::Fn(f) => f,
294            _ => panic!("Arena: expected Fn at {}", index),
295        }
296    }
297    pub fn get_fn_rc(&self, index: u32) -> &Rc<FunctionValue> {
298        match self.get(index) {
299            ArenaEntry::Fn(f) => f,
300            _ => panic!("Arena: expected Fn at {}", index),
301        }
302    }
303    pub fn get_builtin(&self, index: u32) -> &str {
304        match self.get(index) {
305            ArenaEntry::Builtin(s) => s,
306            _ => panic!("Arena: expected Builtin at {}", index),
307        }
308    }
309    pub fn get_namespace(&self, index: u32) -> (&str, &[(Rc<str>, NanValue)]) {
310        match self.get(index) {
311            ArenaEntry::Namespace { name, members } => (name, members),
312            _ => panic!("Arena: expected Namespace at {}", index),
313        }
314    }
315
316    // -- Type registry -----------------------------------------------------
317
318    pub fn register_record_type(&mut self, name: &str, field_names: Vec<String>) -> u32 {
319        let id = self.type_names.len() as u32;
320        self.type_names.push(name.to_string());
321        self.type_field_names.push(field_names);
322        self.type_variant_names.push(Vec::new());
323        id
324    }
325
326    pub fn register_sum_type(&mut self, name: &str, variant_names: Vec<String>) -> u32 {
327        let id = self.type_names.len() as u32;
328        self.type_names.push(name.to_string());
329        self.type_field_names.push(Vec::new());
330        self.type_variant_names.push(variant_names);
331        id
332    }
333
334    pub fn get_type_name(&self, type_id: u32) -> &str {
335        &self.type_names[type_id as usize]
336    }
337    pub fn get_field_names(&self, type_id: u32) -> &[String] {
338        &self.type_field_names[type_id as usize]
339    }
340    pub fn get_variant_name(&self, type_id: u32, variant_id: u16) -> &str {
341        &self.type_variant_names[type_id as usize][variant_id as usize]
342    }
343    pub fn find_type_id(&self, name: &str) -> Option<u32> {
344        self.type_names
345            .iter()
346            .position(|n| n == name)
347            .map(|i| i as u32)
348    }
349    pub fn find_variant_id(&self, type_id: u32, variant_name: &str) -> Option<u16> {
350        self.type_variant_names
351            .get(type_id as usize)?
352            .iter()
353            .position(|n| n == variant_name)
354            .map(|i| i as u16)
355    }
356
357    pub fn len(&self) -> usize {
358        self.young_entries.len()
359            + self.yard_entries.len()
360            + self.handoff_entries.len()
361            + self.stable_entries.len()
362    }
363    pub fn is_empty(&self) -> bool {
364        self.young_entries.is_empty()
365            && self.yard_entries.is_empty()
366            && self.handoff_entries.is_empty()
367            && self.stable_entries.is_empty()
368    }
369}
370
371impl Default for Arena {
372    fn default() -> Self {
373        Self::new()
374    }
375}