turbo_tasks/
trace.rs

1use std::{
2    borrow::Cow,
3    cell::RefCell,
4    collections::{BTreeMap, BTreeSet, HashMap, HashSet},
5    marker::PhantomData,
6    path::{Path, PathBuf},
7    sync::{Arc, Mutex, atomic::*},
8    time::Duration,
9};
10
11use auto_hash_map::{AutoMap, AutoSet};
12use either::Either;
13use indexmap::{IndexMap, IndexSet};
14use smallvec::SmallVec;
15use turbo_frozenmap::{FrozenMap, FrozenSet};
16use turbo_rcstr::RcStr;
17
18use crate::RawVc;
19
20pub struct TraceRawVcsContext {
21    list: Vec<RawVc>,
22}
23
24impl TraceRawVcsContext {
25    pub(crate) fn new() -> Self {
26        Self { list: Vec::new() }
27    }
28
29    pub(crate) fn into_vec(self) -> Vec<RawVc> {
30        self.list
31    }
32}
33
34/// Trait that allows to walk data to find all [RawVc]s contained.
35///
36/// This is important for Garbage Collection to mark all Cells and therefore
37/// Tasks that are still in use.
38///
39/// It can also be used to optimize transferring of Tasks, where knowning the
40/// referenced Cells/Tasks allows pushing them earlier.
41///
42/// `#[derive(TraceRawVcs)]` is available.
43/// `#[trace_ignore]` can be used on fields to skip tracing for them.
44pub trait TraceRawVcs {
45    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext);
46    fn get_raw_vcs(&self) -> Vec<RawVc> {
47        let mut trace_context = TraceRawVcsContext::new();
48        self.trace_raw_vcs(&mut trace_context);
49        trace_context.into_vec()
50    }
51}
52
53macro_rules! ignore {
54  ($ty:ty) => {
55    impl TraceRawVcs for $ty {
56      fn trace_raw_vcs(&self, _context: &mut TraceRawVcsContext) {}
57    }
58  };
59
60  ($ty:ty, $($tys:ty),+) => {
61    ignore!($ty);
62    ignore!($($tys),+);
63  }
64}
65
66ignore!(
67    i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, f32, f64, char, bool, isize, usize
68);
69ignore!(
70    AtomicI8,
71    AtomicU8,
72    AtomicI16,
73    AtomicU16,
74    AtomicI32,
75    AtomicU32,
76    AtomicI64,
77    AtomicU64,
78    AtomicBool,
79    AtomicUsize
80);
81ignore!((), str, String, Duration, anyhow::Error, RcStr);
82ignore!(Path, PathBuf);
83ignore!(serde_json::Value, serde_json::Map<String, serde_json::Value>);
84
85impl<T: ?Sized> TraceRawVcs for PhantomData<T> {
86    fn trace_raw_vcs(&self, _trace_context: &mut TraceRawVcsContext) {}
87}
88
89// based on stdlib's internal `tuple_impls!` macro
90macro_rules! impl_trace_tuple {
91    ($T:ident) => {
92        impl_trace_tuple!(@impl $T);
93    };
94    ($T:ident $( $U:ident )+) => {
95        impl_trace_tuple!($( $U )+);
96        impl_trace_tuple!(@impl $T $( $U )+);
97    };
98    (@impl $( $T:ident )+) => {
99        impl<$($T: TraceRawVcs),+> TraceRawVcs for ($($T,)+) {
100            #[allow(non_snake_case)]
101            fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
102                let ($($T,)+) = self;
103                $(
104                    TraceRawVcs::trace_raw_vcs($T, trace_context);
105                )+
106            }
107        }
108    };
109}
110
111impl_trace_tuple!(E D C B A Z Y X W V U T);
112
113/// Function pointers (the lowercase `fn` type, not `Fn`) don't contain any data, so it's not
114/// possible for them to contain a `Vc`.
115macro_rules! impl_trace_fn_ptr {
116    ($T:ident) => {
117        impl_trace_fn_ptr!(@impl $T);
118    };
119    ($T:ident $( $U:ident )+) => {
120        impl_trace_fn_ptr!($( $U )+);
121        impl_trace_fn_ptr!(@impl $T $( $U )+);
122    };
123    (@impl $( $T:ident )+) => {
124        impl<$($T,)+ Return> TraceRawVcs for fn($($T),+) -> Return {
125            fn trace_raw_vcs(&self, _trace_context: &mut TraceRawVcsContext) {}
126        }
127    };
128}
129
130impl_trace_fn_ptr!(E D C B A Z Y X W V U T);
131
132impl<T: TraceRawVcs> TraceRawVcs for Option<T> {
133    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
134        if let Some(item) = self {
135            TraceRawVcs::trace_raw_vcs(item, trace_context);
136        }
137    }
138}
139
140impl<T: TraceRawVcs> TraceRawVcs for Vec<T> {
141    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
142        for item in self.iter() {
143            TraceRawVcs::trace_raw_vcs(item, trace_context);
144        }
145    }
146}
147
148impl<T: TraceRawVcs> TraceRawVcs for Box<[T]> {
149    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
150        for item in self.iter() {
151            TraceRawVcs::trace_raw_vcs(item, trace_context);
152        }
153    }
154}
155
156impl<T: TraceRawVcs, const N: usize> TraceRawVcs for SmallVec<[T; N]> {
157    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
158        for item in self.iter() {
159            TraceRawVcs::trace_raw_vcs(item, trace_context);
160        }
161    }
162}
163
164impl<T: TraceRawVcs, const N: usize> TraceRawVcs for [T; N] {
165    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
166        for item in self.iter() {
167            TraceRawVcs::trace_raw_vcs(item, trace_context);
168        }
169    }
170}
171
172impl<T: TraceRawVcs, S> TraceRawVcs for HashSet<T, S> {
173    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
174        for item in self.iter() {
175            TraceRawVcs::trace_raw_vcs(item, trace_context);
176        }
177    }
178}
179
180impl<T: TraceRawVcs, S, const I: usize> TraceRawVcs for AutoSet<T, S, I> {
181    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
182        for item in self.iter() {
183            TraceRawVcs::trace_raw_vcs(item, trace_context);
184        }
185    }
186}
187
188impl<T: TraceRawVcs> TraceRawVcs for BTreeSet<T> {
189    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
190        for item in self.iter() {
191            TraceRawVcs::trace_raw_vcs(item, trace_context);
192        }
193    }
194}
195
196impl<T: TraceRawVcs, S> TraceRawVcs for IndexSet<T, S> {
197    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
198        for item in self.iter() {
199            TraceRawVcs::trace_raw_vcs(item, trace_context);
200        }
201    }
202}
203
204impl<T: TraceRawVcs> TraceRawVcs for FrozenSet<T> {
205    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
206        for item in self.iter() {
207            TraceRawVcs::trace_raw_vcs(item, trace_context);
208        }
209    }
210}
211
212impl<K: TraceRawVcs, V: TraceRawVcs, S> TraceRawVcs for HashMap<K, V, S> {
213    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
214        for (key, value) in self.iter() {
215            TraceRawVcs::trace_raw_vcs(key, trace_context);
216            TraceRawVcs::trace_raw_vcs(value, trace_context);
217        }
218    }
219}
220
221impl<K: TraceRawVcs, V: TraceRawVcs, S, const I: usize> TraceRawVcs for AutoMap<K, V, S, I> {
222    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
223        for (key, value) in self.iter() {
224            TraceRawVcs::trace_raw_vcs(key, trace_context);
225            TraceRawVcs::trace_raw_vcs(value, trace_context);
226        }
227    }
228}
229
230impl<K: TraceRawVcs, V: TraceRawVcs> TraceRawVcs for BTreeMap<K, V> {
231    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
232        for (key, value) in self.iter() {
233            TraceRawVcs::trace_raw_vcs(key, trace_context);
234            TraceRawVcs::trace_raw_vcs(value, trace_context);
235        }
236    }
237}
238
239impl<K: TraceRawVcs, V: TraceRawVcs, S> TraceRawVcs for IndexMap<K, V, S> {
240    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
241        for (key, value) in self.iter() {
242            TraceRawVcs::trace_raw_vcs(key, trace_context);
243            TraceRawVcs::trace_raw_vcs(value, trace_context);
244        }
245    }
246}
247
248impl<K: TraceRawVcs, V: TraceRawVcs> TraceRawVcs for FrozenMap<K, V> {
249    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
250        for (key, value) in self.iter() {
251            TraceRawVcs::trace_raw_vcs(key, trace_context);
252            TraceRawVcs::trace_raw_vcs(value, trace_context);
253        }
254    }
255}
256
257impl<T: TraceRawVcs + ?Sized> TraceRawVcs for Box<T> {
258    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
259        TraceRawVcs::trace_raw_vcs(&**self, trace_context);
260    }
261}
262
263impl<T: TraceRawVcs + ?Sized> TraceRawVcs for Arc<T> {
264    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
265        TraceRawVcs::trace_raw_vcs(&**self, trace_context);
266    }
267}
268
269impl<B: TraceRawVcs + ToOwned + ?Sized> TraceRawVcs for Cow<'_, B> {
270    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
271        TraceRawVcs::trace_raw_vcs(&**self, trace_context);
272    }
273}
274
275impl TraceRawVcs for RawVc {
276    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
277        trace_context.list.push(*self);
278    }
279}
280
281impl<T: TraceRawVcs, E: TraceRawVcs> TraceRawVcs for Result<T, E> {
282    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
283        match self {
284            Ok(o) => o.trace_raw_vcs(trace_context),
285            Err(e) => e.trace_raw_vcs(trace_context),
286        }
287    }
288}
289
290impl<T: TraceRawVcs + ?Sized> TraceRawVcs for Mutex<T> {
291    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
292        self.lock().unwrap().trace_raw_vcs(trace_context);
293    }
294}
295
296impl<T: TraceRawVcs + ?Sized> TraceRawVcs for RefCell<T> {
297    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
298        self.borrow().trace_raw_vcs(trace_context);
299    }
300}
301
302impl<T: TraceRawVcs + ?Sized> TraceRawVcs for &T {
303    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
304        (**self).trace_raw_vcs(trace_context);
305    }
306}
307impl<T: TraceRawVcs + ?Sized> TraceRawVcs for &mut T {
308    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
309        (**self).trace_raw_vcs(trace_context);
310    }
311}
312
313impl<L: TraceRawVcs, R: TraceRawVcs> TraceRawVcs for Either<L, R> {
314    fn trace_raw_vcs(&self, trace_context: &mut TraceRawVcsContext) {
315        match self {
316            Either::Left(l) => l.trace_raw_vcs(trace_context),
317            Either::Right(r) => r.trace_raw_vcs(trace_context),
318        }
319    }
320}
321
322pub use turbo_tasks_macros::TraceRawVcs;