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