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