Skip to main content

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