rune/core/gc/
trace.rs
1use std::cell::RefCell;
2
3use super::super::object::RawObj;
4use crate::core::object::{Gc, Object};
5use rune_core::hashmap::{HashMap, HashSet};
6
7pub(crate) trait Trace {
10 fn trace(&self, state: &mut GcState);
11}
12
13pub(crate) trait TracePtr {
19 fn trace_ptr(&self, state: &mut GcState);
20}
21
22pub(crate) struct GcState {
23 stack: Vec<RawObj>,
24 pub(in crate::core) to_space: bumpalo::Bump,
25}
26
27impl GcState {
28 pub fn new() -> Self {
29 GcState { stack: Vec::new(), to_space: bumpalo::Bump::new() }
30 }
31
32 pub fn push(&mut self, obj: Object) {
33 self.stack.push(Gc::into_raw(obj));
34 }
35
36 pub fn trace_stack(&mut self) {
37 while let Some(raw) = self.stack.pop() {
38 let obj = unsafe { Object::from_raw(raw) };
39 obj.trace_ptr(self);
40 }
41 }
42}
43
44impl<T: Trace> TracePtr for &T {
45 fn trace_ptr(&self, state: &mut GcState) {
46 (*self).trace(state);
47 }
48}
49
50impl Trace for usize {
51 fn trace(&self, _: &mut GcState) {}
52}
53
54impl Trace for u64 {
55 fn trace(&self, _: &mut GcState) {}
56}
57
58impl Trace for i64 {
59 fn trace(&self, _: &mut GcState) {}
60}
61
62impl<T: Trace, U: Trace> Trace for (T, U) {
63 fn trace(&self, state: &mut GcState) {
64 self.0.trace(state);
65 self.1.trace(state);
66 }
67}
68
69impl<T: Trace> Trace for [T] {
70 fn trace(&self, state: &mut GcState) {
71 for x in self {
72 x.trace(state);
73 }
74 }
75}
76
77impl<T: Trace, const N: usize> Trace for [T; N] {
78 fn trace(&self, state: &mut GcState) {
79 for x in self {
80 x.trace(state);
81 }
82 }
83}
84
85impl<T: Trace> Trace for Vec<T> {
86 fn trace(&self, state: &mut GcState) {
87 for x in self {
88 x.trace(state);
89 }
90 }
91}
92
93impl<T: Trace> Trace for RefCell<T> {
94 fn trace(&self, state: &mut GcState) {
95 self.borrow().trace(state);
96 }
97}
98
99impl<T: Trace> Trace for std::collections::VecDeque<T> {
100 fn trace(&self, state: &mut GcState) {
101 for x in self {
102 x.trace(state);
103 }
104 }
105}
106
107impl<K: Trace, V: Trace> Trace for HashMap<K, V> {
108 fn trace(&self, state: &mut GcState) {
109 for key in self.keys() {
110 key.trace(state);
111 }
112 for value in self.values() {
113 value.trace(state);
114 }
115 }
116}
117
118impl<T: Trace> Trace for HashSet<T> {
119 fn trace(&self, state: &mut GcState) {
120 for x in self {
121 x.trace(state);
122 }
123 }
124}
125
126impl<T: Trace> Trace for Option<T> {
127 fn trace(&self, state: &mut GcState) {
128 if let Some(x) = self.as_ref() {
129 x.trace(state);
130 }
131 }
132}
133
134#[cfg(test)]
135mod test {
136 use super::super::super::gc::{Context, RootSet};
137 use super::*;
138 use rune_core::macros::root;
139
140 #[derive(Default)]
141 struct Foo(u64);
142 impl Trace for Foo {
143 fn trace(&self, _state: &mut GcState) {
144 assert!(self.0 == 7);
145 }
146 }
147
148 #[test]
149 fn test_trace_root() {
150 let roots = &RootSet::default();
151 let cx = &mut Context::new(roots);
152 let foo = Foo(7);
153 assert_eq!(roots.roots.borrow().len(), 0);
154 {
155 root!(_root, init(foo), cx);
156 assert_eq!(roots.roots.borrow().len(), 1);
157 }
158 assert_eq!(roots.roots.borrow().len(), 0);
159 }
160}