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            type_variant_ctor_ids: Vec::new(),
20            ctor_to_type_variant: Vec::new(),
21            symbol_entries: Vec::new(),
22        }
23    }
24
25    #[inline]
26    pub fn push(&mut self, entry: ArenaEntry) -> u32 {
27        match &entry {
28            ArenaEntry::Fn(_) | ArenaEntry::Builtin(_) | ArenaEntry::Namespace { .. } => {}
29            _ => {
30                return match self.alloc_space {
31                    AllocSpace::Young => {
32                        let idx = self.young_entries.len() as u32;
33                        self.young_entries.push(entry);
34                        self.note_peak_usage();
35                        Self::encode_index(HeapSpace::Young, idx)
36                    }
37                    AllocSpace::Yard => {
38                        let idx = self.yard_entries.len() as u32;
39                        self.yard_entries.push(entry);
40                        self.note_peak_usage();
41                        Self::encode_index(HeapSpace::Yard, idx)
42                    }
43                    AllocSpace::Handoff => {
44                        let idx = self.handoff_entries.len() as u32;
45                        self.handoff_entries.push(entry);
46                        self.note_peak_usage();
47                        Self::encode_index(HeapSpace::Handoff, idx)
48                    }
49                };
50            }
51        }
52        match entry {
53            ArenaEntry::Fn(f) => self.push_symbol(ArenaSymbol::Fn(f)),
54            ArenaEntry::Builtin(name) => self.push_symbol(ArenaSymbol::Builtin(name)),
55            ArenaEntry::Namespace { name, members } => {
56                self.push_symbol(ArenaSymbol::Namespace { name, members })
57            }
58            _ => unreachable!("non-symbol entry already returned above"),
59        }
60    }
61
62    #[inline]
63    pub fn push_symbol(&mut self, symbol: ArenaSymbol) -> u32 {
64        let idx = self.symbol_entries.len() as u32;
65        self.symbol_entries.push(symbol);
66        idx
67    }
68
69    #[inline]
70    pub fn get(&self, index: u32) -> &ArenaEntry {
71        let (space, raw_index) = Self::decode_index(index);
72        match space {
73            HeapSpace::Young => &self.young_entries[raw_index as usize],
74            HeapSpace::Yard => &self.yard_entries[raw_index as usize],
75            HeapSpace::Handoff => &self.handoff_entries[raw_index as usize],
76            HeapSpace::Stable => &self.stable_entries[raw_index as usize],
77        }
78    }
79
80    #[inline]
81    pub(super) fn encode_index(space: HeapSpace, index: u32) -> u32 {
82        ((space as u32) << HEAP_SPACE_SHIFT) | index
83    }
84
85    #[inline]
86    pub(super) fn encode_yard_index(index: u32) -> u32 {
87        Self::encode_index(HeapSpace::Yard, index)
88    }
89
90    #[inline]
91    pub(super) fn encode_stable_index(index: u32) -> u32 {
92        Self::encode_index(HeapSpace::Stable, index)
93    }
94
95    #[inline]
96    pub(super) fn encode_handoff_index(index: u32) -> u32 {
97        Self::encode_index(HeapSpace::Handoff, index)
98    }
99
100    #[inline]
101    pub(super) fn decode_index(index: u32) -> (HeapSpace, u32) {
102        let space = match (index & HEAP_SPACE_MASK_U32) >> HEAP_SPACE_SHIFT {
103            0 => HeapSpace::Young,
104            1 => HeapSpace::Yard,
105            2 => HeapSpace::Handoff,
106            3 => HeapSpace::Stable,
107            _ => unreachable!("invalid heap space bits"),
108        };
109        (space, index & HEAP_INDEX_MASK_U32)
110    }
111
112    #[inline]
113    pub fn is_stable_index(index: u32) -> bool {
114        matches!(Self::decode_index(index).0, HeapSpace::Stable)
115    }
116
117    #[inline]
118    pub fn is_yard_index_in_region(&self, index: u32, mark: u32) -> bool {
119        let (space, raw_index) = Self::decode_index(index);
120        matches!(space, HeapSpace::Yard)
121            && raw_index >= mark
122            && raw_index < self.yard_entries.len() as u32
123    }
124
125    #[inline]
126    pub fn is_handoff_index_in_region(&self, index: u32, mark: u32) -> bool {
127        let (space, raw_index) = Self::decode_index(index);
128        matches!(space, HeapSpace::Handoff)
129            && raw_index >= mark
130            && raw_index < self.handoff_entries.len() as u32
131    }
132
133    #[inline]
134    pub fn is_young_index_in_region(&self, index: u32, mark: u32) -> bool {
135        let (space, raw_index) = Self::decode_index(index);
136        matches!(space, HeapSpace::Young)
137            && raw_index >= mark
138            && raw_index < self.young_entries.len() as u32
139    }
140
141    #[inline]
142    pub fn young_len(&self) -> usize {
143        self.young_entries.len()
144    }
145
146    #[inline]
147    pub fn yard_len(&self) -> usize {
148        self.yard_entries.len()
149    }
150
151    #[inline]
152    pub fn handoff_len(&self) -> usize {
153        self.handoff_entries.len()
154    }
155
156    #[inline]
157    pub fn stable_len(&self) -> usize {
158        self.stable_entries.len()
159    }
160
161    #[inline]
162    pub fn usage(&self) -> ArenaUsage {
163        ArenaUsage {
164            young: self.young_entries.len(),
165            yard: self.yard_entries.len(),
166            handoff: self.handoff_entries.len(),
167            stable: self.stable_entries.len(),
168        }
169    }
170
171    #[inline]
172    pub fn peak_usage(&self) -> ArenaUsage {
173        self.peak_usage
174    }
175
176    #[inline]
177    pub(super) fn note_peak_usage(&mut self) {
178        let usage = self.usage();
179        self.peak_usage.young = self.peak_usage.young.max(usage.young);
180        self.peak_usage.yard = self.peak_usage.yard.max(usage.yard);
181        self.peak_usage.handoff = self.peak_usage.handoff.max(usage.handoff);
182        self.peak_usage.stable = self.peak_usage.stable.max(usage.stable);
183    }
184
185    #[inline]
186    pub(super) fn take_u32_scratch(slot: &mut Vec<u32>, len: usize) -> Vec<u32> {
187        let mut scratch = std::mem::take(slot);
188        scratch.clear();
189        scratch.resize(len, u32::MAX);
190        scratch
191    }
192
193    #[inline]
194    pub(super) fn recycle_u32_scratch(slot: &mut Vec<u32>, mut scratch: Vec<u32>) {
195        scratch.clear();
196        *slot = scratch;
197    }
198
199    #[inline]
200    pub fn is_frame_local_index(
201        &self,
202        index: u32,
203        arena_mark: u32,
204        yard_mark: u32,
205        handoff_mark: u32,
206    ) -> bool {
207        self.is_young_index_in_region(index, arena_mark)
208            || self.is_yard_index_in_region(index, yard_mark)
209            || self.is_handoff_index_in_region(index, handoff_mark)
210    }
211
212    pub fn with_alloc_space<T>(&mut self, space: AllocSpace, f: impl FnOnce(&mut Arena) -> T) -> T {
213        let prev = self.alloc_space;
214        self.alloc_space = space;
215        let out = f(self);
216        self.alloc_space = prev;
217        out
218    }
219
220    // -- Typed push helpers ------------------------------------------------
221
222    pub fn push_i64(&mut self, val: i64) -> u32 {
223        self.push(ArenaEntry::Int(val))
224    }
225    pub fn push_string(&mut self, s: &str) -> u32 {
226        self.push(ArenaEntry::String(Rc::from(s)))
227    }
228    pub fn push_boxed(&mut self, val: NanValue) -> u32 {
229        self.push(ArenaEntry::Boxed(val))
230    }
231    pub fn push_record(&mut self, type_id: u32, fields: Vec<NanValue>) -> u32 {
232        self.push(ArenaEntry::Record { type_id, fields })
233    }
234    pub fn push_variant(&mut self, type_id: u32, variant_id: u16, fields: Vec<NanValue>) -> u32 {
235        self.push(ArenaEntry::Variant {
236            type_id,
237            variant_id,
238            fields,
239        })
240    }
241    pub fn push_list(&mut self, items: Vec<NanValue>) -> u32 {
242        self.push(ArenaEntry::List(ArenaList::Flat {
243            items: Rc::new(items),
244            start: 0,
245        }))
246    }
247    pub fn push_map(&mut self, map: PersistentMap) -> u32 {
248        self.push(ArenaEntry::Map(map))
249    }
250    pub fn push_tuple(&mut self, items: Vec<NanValue>) -> u32 {
251        self.push(ArenaEntry::Tuple(items))
252    }
253    pub fn push_vector(&mut self, items: Vec<NanValue>) -> u32 {
254        self.push(ArenaEntry::Vector(items))
255    }
256    pub fn push_fn(&mut self, f: Rc<FunctionValue>) -> u32 {
257        self.push_symbol(ArenaSymbol::Fn(f))
258    }
259    pub fn push_builtin(&mut self, name: &str) -> u32 {
260        self.push_symbol(ArenaSymbol::Builtin(Rc::from(name)))
261    }
262    pub fn push_nullary_variant_symbol(&mut self, ctor_id: u32) -> u32 {
263        self.push_symbol(ArenaSymbol::NullaryVariant { ctor_id })
264    }
265
266    // -- Typed getters -----------------------------------------------------
267
268    pub fn get_i64(&self, index: u32) -> i64 {
269        match self.get(index) {
270            ArenaEntry::Int(i) => *i,
271            _ => panic!("Arena: expected Int at {}", index),
272        }
273    }
274    pub fn get_string(&self, index: u32) -> &str {
275        match self.get(index) {
276            ArenaEntry::String(s) => s,
277            other => panic!("Arena: expected String at {} but found {:?}", index, other),
278        }
279    }
280    pub fn get_string_value(&self, value: NanValue) -> NanString<'_> {
281        if let Some(s) = value.small_string() {
282            s
283        } else {
284            NanString::Borrowed(self.get_string(value.arena_index()))
285        }
286    }
287    pub fn get_boxed(&self, index: u32) -> NanValue {
288        match self.get(index) {
289            ArenaEntry::Boxed(v) => *v,
290            _ => panic!("Arena: expected Boxed at {}", index),
291        }
292    }
293    pub fn get_record(&self, index: u32) -> (u32, &[NanValue]) {
294        match self.get(index) {
295            ArenaEntry::Record { type_id, fields } => (*type_id, fields),
296            _ => panic!("Arena: expected Record at {}", index),
297        }
298    }
299    pub fn get_variant(&self, index: u32) -> (u32, u16, &[NanValue]) {
300        match self.get(index) {
301            ArenaEntry::Variant {
302                type_id,
303                variant_id,
304                fields,
305            } => (*type_id, *variant_id, fields),
306            other => panic!("Arena: expected Variant at {} but found {:?}", index, other),
307        }
308    }
309    pub fn get_list(&self, index: u32) -> &ArenaList {
310        match self.get(index) {
311            ArenaEntry::List(items) => items,
312            _ => panic!("Arena: expected List at {}", index),
313        }
314    }
315    pub fn get_tuple(&self, index: u32) -> &[NanValue] {
316        match self.get(index) {
317            ArenaEntry::Tuple(items) => items,
318            _ => panic!("Arena: expected Tuple at {}", index),
319        }
320    }
321    pub fn get_vector(&self, index: u32) -> &[NanValue] {
322        match self.get(index) {
323            ArenaEntry::Vector(items) => items,
324            _ => panic!("Arena: expected Vector at {}", index),
325        }
326    }
327    pub fn vector_ref_value(&self, value: NanValue) -> &[NanValue] {
328        if value.is_empty_vector_immediate() {
329            return &[];
330        }
331        self.get_vector(value.arena_index())
332    }
333    pub fn clone_vector_value(&self, value: NanValue) -> Vec<NanValue> {
334        if value.is_empty_vector_immediate() {
335            Vec::new()
336        } else {
337            self.get_vector(value.arena_index()).to_vec()
338        }
339    }
340    pub fn get_map(&self, index: u32) -> &PersistentMap {
341        match self.get(index) {
342            ArenaEntry::Map(map) => map,
343            _ => panic!("Arena: expected Map at {}", index),
344        }
345    }
346    pub fn map_ref_value(&self, map: NanValue) -> &PersistentMap {
347        thread_local! {
348            static EMPTY_MAP: PersistentMap = PersistentMap::new();
349        }
350        if map.is_empty_map_immediate() {
351            // SAFETY: thread_local guarantees single-thread; reference is valid
352            // for the lifetime of the thread (longer than any Arena borrow).
353            return EMPTY_MAP.with(|m| unsafe { &*(m as *const PersistentMap) });
354        }
355        self.get_map(map.arena_index())
356    }
357    pub fn clone_map_value(&self, map: NanValue) -> PersistentMap {
358        if map.is_empty_map_immediate() {
359            PersistentMap::new()
360        } else {
361            self.get_map(map.arena_index()).clone()
362        }
363    }
364    pub fn get_fn(&self, index: u32) -> &FunctionValue {
365        match &self.symbol_entries[index as usize] {
366            ArenaSymbol::Fn(f) => f,
367            _ => panic!("Arena: expected Fn symbol at {}", index),
368        }
369    }
370    pub fn get_fn_rc(&self, index: u32) -> &Rc<FunctionValue> {
371        match &self.symbol_entries[index as usize] {
372            ArenaSymbol::Fn(f) => f,
373            _ => panic!("Arena: expected Fn symbol at {}", index),
374        }
375    }
376    pub fn get_builtin(&self, index: u32) -> &str {
377        match &self.symbol_entries[index as usize] {
378            ArenaSymbol::Builtin(s) => s,
379            _ => panic!("Arena: expected Builtin symbol at {}", index),
380        }
381    }
382    pub fn get_namespace(&self, index: u32) -> (&str, &[(Rc<str>, NanValue)]) {
383        match &self.symbol_entries[index as usize] {
384            ArenaSymbol::Namespace { name, members } => (name, members),
385            _ => panic!("Arena: expected Namespace symbol at {}", index),
386        }
387    }
388    pub fn get_nullary_variant_ctor(&self, index: u32) -> u32 {
389        match &self.symbol_entries[index as usize] {
390            ArenaSymbol::NullaryVariant { ctor_id } => *ctor_id,
391            _ => panic!("Arena: expected NullaryVariant symbol at {}", index),
392        }
393    }
394
395    // -- Type registry -----------------------------------------------------
396
397    pub fn register_record_type(&mut self, name: &str, field_names: Vec<String>) -> u32 {
398        let id = self.type_names.len() as u32;
399        self.type_names.push(name.to_string());
400        self.type_field_names.push(field_names);
401        self.type_variant_names.push(Vec::new());
402        self.type_variant_ctor_ids.push(Vec::new());
403        id
404    }
405
406    pub fn register_sum_type(&mut self, name: &str, variant_names: Vec<String>) -> u32 {
407        let id = self.type_names.len() as u32;
408        self.type_names.push(name.to_string());
409        self.type_field_names.push(Vec::new());
410        let ctor_ids: Vec<u32> = (0..variant_names.len())
411            .map(|variant_idx| {
412                let ctor_id = self.ctor_to_type_variant.len() as u32;
413                self.ctor_to_type_variant.push((id, variant_idx as u16));
414                ctor_id
415            })
416            .collect();
417        self.type_variant_names.push(variant_names);
418        self.type_variant_ctor_ids.push(ctor_ids);
419        id
420    }
421
422    pub fn register_variant_name(&mut self, type_id: u32, variant_name: String) -> u16 {
423        let variants = &mut self.type_variant_names[type_id as usize];
424        let variant_id = variants.len() as u16;
425        variants.push(variant_name);
426
427        let ctor_id = self.ctor_to_type_variant.len() as u32;
428        self.ctor_to_type_variant.push((type_id, variant_id));
429        self.type_variant_ctor_ids[type_id as usize].push(ctor_id);
430
431        variant_id
432    }
433
434    pub fn get_type_name(&self, type_id: u32) -> &str {
435        &self.type_names[type_id as usize]
436    }
437    pub fn type_count(&self) -> u32 {
438        self.type_names.len() as u32
439    }
440    pub fn get_field_names(&self, type_id: u32) -> &[String] {
441        &self.type_field_names[type_id as usize]
442    }
443    pub fn get_variant_name(&self, type_id: u32, variant_id: u16) -> &str {
444        &self.type_variant_names[type_id as usize][variant_id as usize]
445    }
446    pub fn find_type_id(&self, name: &str) -> Option<u32> {
447        self.type_names
448            .iter()
449            .position(|n| n == name)
450            .map(|i| i as u32)
451    }
452    pub fn find_variant_id(&self, type_id: u32, variant_name: &str) -> Option<u16> {
453        self.type_variant_names
454            .get(type_id as usize)?
455            .iter()
456            .position(|n| n == variant_name)
457            .map(|i| i as u16)
458    }
459
460    pub fn find_ctor_id(&self, type_id: u32, variant_id: u16) -> Option<u32> {
461        self.type_variant_ctor_ids
462            .get(type_id as usize)?
463            .get(variant_id as usize)
464            .copied()
465    }
466
467    pub fn get_ctor_parts(&self, ctor_id: u32) -> (u32, u16) {
468        self.ctor_to_type_variant
469            .get(ctor_id as usize)
470            .copied()
471            .unwrap_or_else(|| panic!("Arena: expected ctor id {} to be registered", ctor_id))
472    }
473
474    pub fn len(&self) -> usize {
475        self.young_entries.len()
476            + self.yard_entries.len()
477            + self.handoff_entries.len()
478            + self.stable_entries.len()
479    }
480    pub fn is_empty(&self) -> bool {
481        self.young_entries.is_empty()
482            && self.yard_entries.is_empty()
483            && self.handoff_entries.is_empty()
484            && self.stable_entries.is_empty()
485    }
486}
487
488impl Default for Arena {
489    fn default() -> Self {
490        Self::new()
491    }
492}