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 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 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 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 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}