Skip to main content

servo_malloc_size_of/
lib.rs

1// Copyright 2016-2017 The Servo Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11//! A crate for measuring the heap usage of data structures in a way that
12//! integrates with Firefox's memory reporting, particularly the use of
13//! mozjemalloc and DMD. In particular, it has the following features.
14//! - It isn't bound to a particular heap allocator.
15//! - It provides traits for both "shallow" and "deep" measurement, which gives
16//!   flexibility in the cases where the traits can't be used.
17//! - It allows for measuring blocks even when only an interior pointer can be
18//!   obtained for heap allocations, e.g. `HashSet` and `HashMap`. (This relies
19//!   on the heap allocator having suitable support, which mozjemalloc has.)
20//! - It allows handling of types like `Rc` and `Arc` by providing traits that
21//!   are different to the ones for non-graph structures.
22//!
23//! Suggested uses are as follows.
24//! - When possible, use the `MallocSizeOf` trait. (Deriving support is
25//!   provided by the `malloc_size_of_derive` crate.)
26//! - If you need an additional synchronization argument, provide a function
27//!   that is like the standard trait method, but with the extra argument.
28//! - If you need multiple measurements for a type, provide a function named
29//!   `add_size_of` that takes a mutable reference to a struct that contains
30//!   the multiple measurement fields.
31//! - When deep measurement (via `MallocSizeOf`) cannot be implemented for a
32//!   type, shallow measurement (via `MallocShallowSizeOf`) in combination with
33//!   iteration can be a useful substitute.
34//! - `Rc` and `Arc` are always tricky, which is why `MallocSizeOf` is not (and
35//!   should not be) implemented for them.
36//! - If an `Rc` or `Arc` is known to be a "primary" reference and can always
37//!   be measured, it should be measured via the `MallocUnconditionalSizeOf`
38//!   trait.
39//! - If an `Rc` or `Arc` should be measured only if it hasn't been seen
40//!   before, it should be measured via the `MallocConditionalSizeOf` trait.
41//! - Using universal function call syntax is a good idea when measuring boxed
42//!   fields in structs, because it makes it clear that the Box is being
43//!   measured as well as the thing it points to. E.g.
44//!   `<Box<_> as MallocSizeOf>::size_of(field, ops)`.
45//!
46//!   Note: WebRender has a reduced fork of this crate, so that we can avoid
47//!   publishing this crate on crates.io.
48
49use std::cell::OnceCell;
50use std::collections::BinaryHeap;
51use std::ffi::CString;
52use std::hash::{BuildHasher, Hash};
53use std::ops::{Range, RangeInclusive};
54use std::rc::Rc;
55use std::sync::{Arc, OnceLock};
56
57use resvg::usvg::fontdb::Source;
58use resvg::usvg::{self, tiny_skia_path};
59use style::properties::ComputedValues;
60use style::values::generics::length::GenericLengthPercentageOrAuto;
61pub use stylo_malloc_size_of::MallocSizeOfOps;
62
63/// Trait for measuring the "deep" heap usage of a data structure. This is the
64/// most commonly-used of the traits.
65pub trait MallocSizeOf {
66    /// Measure the heap usage of all descendant heap-allocated structures, but
67    /// not the space taken up by the value itself.
68    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize;
69}
70
71/// Trait for measuring the "shallow" heap usage of a container.
72pub trait MallocShallowSizeOf {
73    /// Measure the heap usage of immediate heap-allocated descendant
74    /// structures, but not the space taken up by the value itself. Anything
75    /// beyond the immediate descendants must be measured separately, using
76    /// iteration.
77    fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize;
78}
79
80/// Like `MallocSizeOf`, but with a different name so it cannot be used
81/// accidentally with derive(MallocSizeOf). For use with types like `Rc` and
82/// `Arc` when appropriate (e.g. when measuring a "primary" reference).
83pub trait MallocUnconditionalSizeOf {
84    /// Measure the heap usage of all heap-allocated descendant structures, but
85    /// not the space taken up by the value itself.
86    fn unconditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize;
87}
88
89/// `MallocUnconditionalSizeOf` combined with `MallocShallowSizeOf`.
90pub trait MallocUnconditionalShallowSizeOf {
91    /// `unconditional_size_of` combined with `shallow_size_of`.
92    fn unconditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize;
93}
94
95/// Like `MallocSizeOf`, but only measures if the value hasn't already been
96/// measured. For use with types like `Rc` and `Arc` when appropriate (e.g.
97/// when there is no "primary" reference).
98pub trait MallocConditionalSizeOf {
99    /// Measure the heap usage of all heap-allocated descendant structures, but
100    /// not the space taken up by the value itself, and only if that heap usage
101    /// hasn't already been measured.
102    fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize;
103}
104
105/// `MallocConditionalSizeOf` combined with `MallocShallowSizeOf`.
106pub trait MallocConditionalShallowSizeOf {
107    /// `conditional_size_of` combined with `shallow_size_of`.
108    fn conditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize;
109}
110
111impl<T: MallocSizeOf> MallocSizeOf for [T] {
112    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
113        let mut n = 0;
114        for elem in self.iter() {
115            n += elem.size_of(ops);
116        }
117        n
118    }
119}
120
121impl<T: MallocConditionalSizeOf> MallocConditionalSizeOf for [T] {
122    fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
123        self.iter()
124            .map(|element| element.conditional_size_of(ops))
125            .sum()
126    }
127}
128
129/// For use on types where size_of() returns 0.
130#[macro_export]
131macro_rules! malloc_size_of_is_0(
132    ($($ty:ty),+) => (
133        $(
134            impl $crate::MallocSizeOf for $ty {
135                #[inline(always)]
136                fn size_of(&self, _: &mut $crate::MallocSizeOfOps) -> usize {
137                    0
138                }
139            }
140        )+
141    );
142    ($($ty:ident<$($gen:ident),+>),+) => (
143        $(
144            impl<$($gen: $crate::MallocSizeOf),+> $crate::MallocSizeOf for $ty<$($gen),+> {
145                #[inline(always)]
146                fn size_of(&self, _: &mut $crate::MallocSizeOfOps) -> usize {
147                    0
148                }
149            }
150        )+
151    );
152);
153
154impl MallocSizeOf for keyboard_types::Key {
155    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
156        match &self {
157            keyboard_types::Key::Character(string) => {
158                <String as MallocSizeOf>::size_of(string, ops)
159            },
160            _ => 0,
161        }
162    }
163}
164
165impl MallocSizeOf for markup5ever::QualName {
166    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
167        self.prefix.size_of(ops) + self.ns.size_of(ops) + self.local.size_of(ops)
168    }
169}
170
171impl MallocSizeOf for String {
172    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
173        unsafe { ops.malloc_size_of(self.as_ptr()) }
174    }
175}
176
177impl MallocSizeOf for CString {
178    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
179        unsafe { ops.malloc_size_of(self.as_ptr()) }
180    }
181}
182
183impl<T: ?Sized> MallocSizeOf for &'_ T {
184    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
185        // Zero makes sense for a non-owning reference.
186        0
187    }
188}
189
190impl<T: ?Sized> MallocShallowSizeOf for Box<T> {
191    fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
192        unsafe { ops.malloc_size_of(&**self) }
193    }
194}
195
196impl<T: MallocSizeOf + ?Sized> MallocSizeOf for Box<T> {
197    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
198        self.shallow_size_of(ops) + (**self).size_of(ops)
199    }
200}
201
202impl MallocSizeOf for () {
203    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
204        0
205    }
206}
207
208impl<T1, T2> MallocSizeOf for (T1, T2)
209where
210    T1: MallocSizeOf,
211    T2: MallocSizeOf,
212{
213    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
214        self.0.size_of(ops) + self.1.size_of(ops)
215    }
216}
217
218impl<T1, T2, T3> MallocSizeOf for (T1, T2, T3)
219where
220    T1: MallocSizeOf,
221    T2: MallocSizeOf,
222    T3: MallocSizeOf,
223{
224    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
225        self.0.size_of(ops) + self.1.size_of(ops) + self.2.size_of(ops)
226    }
227}
228
229impl<T1, T2, T3, T4> MallocSizeOf for (T1, T2, T3, T4)
230where
231    T1: MallocSizeOf,
232    T2: MallocSizeOf,
233    T3: MallocSizeOf,
234    T4: MallocSizeOf,
235{
236    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
237        self.0.size_of(ops) + self.1.size_of(ops) + self.2.size_of(ops) + self.3.size_of(ops)
238    }
239}
240
241impl<T: MallocConditionalSizeOf> MallocConditionalSizeOf for Option<T> {
242    fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
243        if let Some(val) = self.as_ref() {
244            val.conditional_size_of(ops)
245        } else {
246            0
247        }
248    }
249}
250
251impl<T: MallocConditionalSizeOf> MallocConditionalSizeOf for Vec<T> {
252    fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
253        let mut n = self.shallow_size_of(ops);
254        for elem in self.iter() {
255            n += elem.conditional_size_of(ops);
256        }
257        n
258    }
259}
260
261impl<T: MallocConditionalSizeOf> MallocConditionalSizeOf for std::collections::VecDeque<T> {
262    fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
263        let mut n = self.shallow_size_of(ops);
264        for elem in self.iter() {
265            n += elem.conditional_size_of(ops);
266        }
267        n
268    }
269}
270
271impl<T: MallocConditionalSizeOf> MallocConditionalSizeOf for std::cell::RefCell<T> {
272    fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
273        self.borrow().conditional_size_of(ops)
274    }
275}
276
277impl<T1, T2> MallocConditionalSizeOf for (T1, T2)
278where
279    T1: MallocConditionalSizeOf,
280    T2: MallocConditionalSizeOf,
281{
282    fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
283        self.0.conditional_size_of(ops) + self.1.conditional_size_of(ops)
284    }
285}
286
287impl<T: MallocConditionalSizeOf + ?Sized> MallocConditionalSizeOf for Box<T> {
288    fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
289        self.shallow_size_of(ops) + (**self).conditional_size_of(ops)
290    }
291}
292
293impl<T: MallocConditionalSizeOf, E: MallocSizeOf> MallocConditionalSizeOf for Result<T, E> {
294    fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
295        match *self {
296            Ok(ref x) => x.conditional_size_of(ops),
297            Err(ref e) => e.size_of(ops),
298        }
299    }
300}
301
302impl MallocConditionalSizeOf for () {
303    fn conditional_size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
304        0
305    }
306}
307
308impl<T: MallocSizeOf> MallocSizeOf for Option<T> {
309    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
310        if let Some(val) = self.as_ref() {
311            val.size_of(ops)
312        } else {
313            0
314        }
315    }
316}
317
318impl<T: MallocSizeOf, E: MallocSizeOf> MallocSizeOf for Result<T, E> {
319    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
320        match *self {
321            Ok(ref x) => x.size_of(ops),
322            Err(ref e) => e.size_of(ops),
323        }
324    }
325}
326
327impl<T: MallocSizeOf + Copy> MallocSizeOf for std::cell::Cell<T> {
328    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
329        self.get().size_of(ops)
330    }
331}
332
333impl<T: MallocSizeOf> MallocSizeOf for std::cell::RefCell<T> {
334    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
335        self.borrow().size_of(ops)
336    }
337}
338
339impl<B: ?Sized + ToOwned> MallocSizeOf for std::borrow::Cow<'_, B>
340where
341    B::Owned: MallocSizeOf,
342{
343    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
344        match *self {
345            std::borrow::Cow::Borrowed(_) => 0,
346            std::borrow::Cow::Owned(ref b) => b.size_of(ops),
347        }
348    }
349}
350
351impl<T> MallocShallowSizeOf for Vec<T> {
352    fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
353        unsafe { ops.malloc_size_of(self.as_ptr()) }
354    }
355}
356
357impl<T: MallocSizeOf> MallocSizeOf for Vec<T> {
358    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
359        let mut n = self.shallow_size_of(ops);
360        for elem in self.iter() {
361            n += elem.size_of(ops);
362        }
363        n
364    }
365}
366
367impl<T> MallocShallowSizeOf for std::collections::VecDeque<T> {
368    fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
369        if ops.has_malloc_enclosing_size_of() {
370            if let Some(front) = self.front() {
371                // The front element is an interior pointer.
372                unsafe { ops.malloc_enclosing_size_of(front) }
373            } else {
374                // This assumes that no memory is allocated when the VecDeque is empty.
375                0
376            }
377        } else {
378            // An estimate.
379            self.capacity() * size_of::<T>()
380        }
381    }
382}
383
384impl<T: MallocSizeOf> MallocSizeOf for std::collections::VecDeque<T> {
385    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
386        let mut n = self.shallow_size_of(ops);
387        for elem in self.iter() {
388            n += elem.size_of(ops);
389        }
390        n
391    }
392}
393
394impl MallocSizeOf for std::path::PathBuf {
395    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
396        // This should be an approximation of the actual size
397        self.as_os_str().as_encoded_bytes().len()
398    }
399}
400
401impl<A: smallvec::Array> MallocShallowSizeOf for smallvec::SmallVec<A> {
402    fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
403        if self.spilled() {
404            unsafe { ops.malloc_size_of(self.as_ptr()) }
405        } else {
406            0
407        }
408    }
409}
410
411impl<A> MallocSizeOf for smallvec::SmallVec<A>
412where
413    A: smallvec::Array,
414    A::Item: MallocSizeOf,
415{
416    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
417        let mut n = self.shallow_size_of(ops);
418        for elem in self.iter() {
419            n += elem.size_of(ops);
420        }
421        n
422    }
423}
424
425impl<A: MallocConditionalSizeOf> MallocConditionalSizeOf for smallvec::SmallVec<A>
426where
427    A: smallvec::Array,
428    A::Item: MallocConditionalSizeOf,
429{
430    fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
431        if !self.spilled() {
432            return 0;
433        }
434
435        self.shallow_size_of(ops) +
436            self.iter()
437                .map(|element| element.conditional_size_of(ops))
438                .sum::<usize>()
439    }
440}
441
442impl<T: MallocSizeOf> MallocSizeOf for BinaryHeap<T> {
443    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
444        self.iter().map(|element| element.size_of(ops)).sum()
445    }
446}
447
448impl<T: MallocSizeOf> MallocSizeOf for std::collections::BTreeSet<T> {
449    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
450        self.iter().map(|element| element.size_of(ops)).sum()
451    }
452}
453
454impl<T: MallocSizeOf> MallocSizeOf for Range<T> {
455    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
456        self.start.size_of(ops) + self.end.size_of(ops)
457    }
458}
459
460impl<T: MallocSizeOf> MallocSizeOf for RangeInclusive<T> {
461    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
462        self.start().size_of(ops) + self.end().size_of(ops)
463    }
464}
465
466macro_rules! malloc_size_of_hash_set {
467    ($ty:ty) => {
468        impl<T, S> MallocShallowSizeOf for $ty
469        where
470            T: Eq + Hash,
471            S: BuildHasher,
472        {
473            fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
474                if ops.has_malloc_enclosing_size_of() {
475                    // The first value from the iterator gives us an interior pointer.
476                    // `ops.malloc_enclosing_size_of()` then gives us the storage size.
477                    // This assumes that the `HashSet`'s contents (values and hashes)
478                    // are all stored in a single contiguous heap allocation.
479                    self.iter()
480                        .next()
481                        .map_or(0, |t| unsafe { ops.malloc_enclosing_size_of(t) })
482                } else {
483                    // An estimate.
484                    self.capacity() * (size_of::<T>() + size_of::<usize>())
485                }
486            }
487        }
488
489        impl<T, S> MallocSizeOf for $ty
490        where
491            T: Eq + Hash + MallocSizeOf,
492            S: BuildHasher,
493        {
494            fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
495                let mut n = self.shallow_size_of(ops);
496                for t in self.iter() {
497                    n += t.size_of(ops);
498                }
499                n
500            }
501        }
502    };
503}
504
505malloc_size_of_hash_set!(std::collections::HashSet<T, S>);
506
507macro_rules! malloc_size_of_hash_map {
508    ($ty:ty) => {
509        impl<K, V, S> MallocShallowSizeOf for $ty
510        where
511            K: Eq + Hash,
512            S: BuildHasher,
513        {
514            fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
515                // See the implementation for std::collections::HashSet for details.
516                if ops.has_malloc_enclosing_size_of() {
517                    self.values()
518                        .next()
519                        .map_or(0, |v| unsafe { ops.malloc_enclosing_size_of(v) })
520                } else {
521                    self.capacity() * (size_of::<V>() + size_of::<K>() + size_of::<usize>())
522                }
523            }
524        }
525
526        impl<K, V, S> MallocSizeOf for $ty
527        where
528            K: Eq + Hash + MallocSizeOf,
529            V: MallocSizeOf,
530            S: BuildHasher,
531        {
532            fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
533                let mut n = self.shallow_size_of(ops);
534                for (k, v) in self.iter() {
535                    n += k.size_of(ops);
536                    n += v.size_of(ops);
537                }
538                n
539            }
540        }
541
542        impl<K, V, S> MallocConditionalSizeOf for $ty
543        where
544            K: Eq + Hash + MallocSizeOf,
545            V: MallocConditionalSizeOf,
546            S: BuildHasher,
547        {
548            fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
549                let mut n = self.shallow_size_of(ops);
550                for (k, v) in self.iter() {
551                    n += k.size_of(ops);
552                    n += v.conditional_size_of(ops);
553                }
554                n
555            }
556        }
557    };
558}
559
560malloc_size_of_hash_map!(std::collections::HashMap<K, V, S>);
561
562impl<K, V> MallocShallowSizeOf for std::collections::BTreeMap<K, V>
563where
564    K: Eq + Hash,
565{
566    fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
567        if ops.has_malloc_enclosing_size_of() {
568            self.values()
569                .next()
570                .map_or(0, |v| unsafe { ops.malloc_enclosing_size_of(v) })
571        } else {
572            self.len() * (size_of::<V>() + size_of::<K>() + size_of::<usize>())
573        }
574    }
575}
576
577impl<K, V> MallocSizeOf for std::collections::BTreeMap<K, V>
578where
579    K: Eq + Hash + MallocSizeOf,
580    V: MallocSizeOf,
581{
582    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
583        let mut n = self.shallow_size_of(ops);
584        for (k, v) in self.iter() {
585            n += k.size_of(ops);
586            n += v.size_of(ops);
587        }
588        n
589    }
590}
591
592// PhantomData is always 0.
593impl<T> MallocSizeOf for std::marker::PhantomData<T> {
594    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
595        0
596    }
597}
598
599impl<T: MallocSizeOf> MallocSizeOf for OnceCell<T> {
600    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
601        self.get()
602            .map(|interior| interior.size_of(ops))
603            .unwrap_or_default()
604    }
605}
606
607impl<T: MallocConditionalSizeOf> MallocConditionalSizeOf for OnceCell<T> {
608    fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
609        self.get()
610            .map(|interior| interior.conditional_size_of(ops))
611            .unwrap_or_default()
612    }
613}
614
615impl<T: MallocSizeOf> MallocSizeOf for OnceLock<T> {
616    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
617        self.get()
618            .map(|interior| interior.size_of(ops))
619            .unwrap_or_default()
620    }
621}
622
623impl<T: MallocConditionalSizeOf> MallocConditionalSizeOf for OnceLock<T> {
624    fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
625        self.get()
626            .map(|interior| interior.conditional_size_of(ops))
627            .unwrap_or_default()
628    }
629}
630
631// See https://github.com/rust-lang/rust/issues/68318:
632// We don't want MallocSizeOf to be defined for Rc and Arc. If negative trait bounds are
633// ever allowed, this code should be uncommented.  Instead, there is a compile-fail test for
634// this.
635// impl<T> !MallocSizeOf for Arc<T> { }
636// impl<T> !MallocShallowSizeOf for Arc<T> { }
637
638impl<T> MallocUnconditionalShallowSizeOf for servo_arc::Arc<T> {
639    fn unconditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
640        unsafe { ops.malloc_size_of(self.heap_ptr()) }
641    }
642}
643
644impl<T: MallocSizeOf> MallocUnconditionalSizeOf for servo_arc::Arc<T> {
645    fn unconditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
646        self.unconditional_shallow_size_of(ops) + (**self).size_of(ops)
647    }
648}
649
650impl<T> MallocConditionalShallowSizeOf for servo_arc::Arc<T> {
651    fn conditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
652        if ops.have_seen_ptr(self.heap_ptr()) {
653            0
654        } else {
655            self.unconditional_shallow_size_of(ops)
656        }
657    }
658}
659
660impl<T: MallocSizeOf> MallocConditionalSizeOf for servo_arc::Arc<T> {
661    fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
662        if ops.have_seen_ptr(self.heap_ptr()) {
663            0
664        } else {
665            self.unconditional_size_of(ops)
666        }
667    }
668}
669
670impl<T> MallocUnconditionalShallowSizeOf for Arc<T> {
671    fn unconditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
672        unsafe { ops.malloc_size_of(Arc::as_ptr(self)) }
673    }
674}
675
676impl<T: MallocSizeOf> MallocUnconditionalSizeOf for Arc<T> {
677    fn unconditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
678        self.unconditional_shallow_size_of(ops) + (**self).size_of(ops)
679    }
680}
681
682impl<T> MallocConditionalShallowSizeOf for Arc<T> {
683    fn conditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
684        if ops.have_seen_ptr(Arc::as_ptr(self)) {
685            0
686        } else {
687            self.unconditional_shallow_size_of(ops)
688        }
689    }
690}
691
692impl<T: MallocSizeOf> MallocConditionalSizeOf for Arc<T> {
693    fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
694        if ops.have_seen_ptr(Arc::as_ptr(self)) {
695            0
696        } else {
697            self.unconditional_size_of(ops)
698        }
699    }
700}
701
702impl<T> MallocUnconditionalShallowSizeOf for Rc<T> {
703    fn unconditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
704        unsafe { ops.malloc_size_of(Rc::as_ptr(self)) }
705    }
706}
707
708impl<T: MallocSizeOf> MallocUnconditionalSizeOf for Rc<T> {
709    fn unconditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
710        self.unconditional_shallow_size_of(ops) + (**self).size_of(ops)
711    }
712}
713
714impl<T: MallocSizeOf> MallocConditionalSizeOf for Rc<T> {
715    fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
716        if ops.have_seen_ptr(Rc::as_ptr(self)) {
717            0
718        } else {
719            self.unconditional_size_of(ops)
720        }
721    }
722}
723
724impl<T: MallocSizeOf> MallocSizeOf for std::sync::Weak<T> {
725    fn size_of(&self, _: &mut MallocSizeOfOps) -> usize {
726        // A weak reference to the data necessarily has another strong reference
727        // somewhere else where it can be measured or...it's been released and is zero.
728        0
729    }
730}
731
732/// If a mutex is stored directly as a member of a data type that is being measured,
733/// it is the unique owner of its contents and deserves to be measured.
734///
735/// If a mutex is stored inside of an Arc value as a member of a data type that is being measured,
736/// the Arc will not be automatically measured so there is no risk of overcounting the mutex's
737/// contents.
738impl<T: MallocSizeOf> MallocSizeOf for std::sync::Mutex<T> {
739    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
740        (*self.lock().unwrap()).size_of(ops)
741    }
742}
743
744impl<T: MallocSizeOf> MallocSizeOf for std::sync::RwLock<T> {
745    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
746        (*self.read().unwrap()).size_of(ops)
747    }
748}
749
750impl<T: MallocSizeOf> MallocSizeOf for parking_lot::Mutex<T> {
751    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
752        (*self.lock()).size_of(ops)
753    }
754}
755
756impl<T: MallocSizeOf> MallocSizeOf for tokio::sync::Mutex<T> {
757    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
758        self.blocking_lock().size_of(ops)
759    }
760}
761
762impl<T: MallocSizeOf> MallocSizeOf for tokio::sync::RwLock<T> {
763    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
764        self.blocking_read().size_of(ops)
765    }
766}
767
768impl<T: MallocSizeOf> MallocSizeOf for parking_lot::RwLock<T> {
769    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
770        (*self.read()).size_of(ops)
771    }
772}
773
774impl<T: MallocConditionalSizeOf> MallocConditionalSizeOf for parking_lot::RwLock<T> {
775    fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
776        (*self.read()).conditional_size_of(ops)
777    }
778}
779
780impl<T: MallocSizeOf, Unit> MallocSizeOf for euclid::Length<T, Unit> {
781    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
782        self.0.size_of(ops)
783    }
784}
785
786impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::Scale<T, Src, Dst> {
787    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
788        self.0.size_of(ops)
789    }
790}
791
792impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Point2D<T, U> {
793    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
794        self.x.size_of(ops) + self.y.size_of(ops)
795    }
796}
797
798impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Box2D<T, U> {
799    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
800        self.min.size_of(ops) + self.max.size_of(ops)
801    }
802}
803
804impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Vector3D<T, U> {
805    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
806        self.x.size_of(ops) + self.y.size_of(ops) + self.z.size_of(ops)
807    }
808}
809
810impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Rect<T, U> {
811    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
812        self.origin.size_of(ops) + self.size.size_of(ops)
813    }
814}
815
816impl<T: MallocSizeOf, U> MallocSizeOf for euclid::SideOffsets2D<T, U> {
817    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
818        self.top.size_of(ops) +
819            self.right.size_of(ops) +
820            self.bottom.size_of(ops) +
821            self.left.size_of(ops)
822    }
823}
824
825impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Size2D<T, U> {
826    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
827        self.width.size_of(ops) + self.height.size_of(ops)
828    }
829}
830
831impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::Transform2D<T, Src, Dst> {
832    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
833        self.m11.size_of(ops) +
834            self.m12.size_of(ops) +
835            self.m21.size_of(ops) +
836            self.m22.size_of(ops) +
837            self.m31.size_of(ops) +
838            self.m32.size_of(ops)
839    }
840}
841
842impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::Transform3D<T, Src, Dst> {
843    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
844        self.m11.size_of(ops) +
845            self.m12.size_of(ops) +
846            self.m13.size_of(ops) +
847            self.m14.size_of(ops) +
848            self.m21.size_of(ops) +
849            self.m22.size_of(ops) +
850            self.m23.size_of(ops) +
851            self.m24.size_of(ops) +
852            self.m31.size_of(ops) +
853            self.m32.size_of(ops) +
854            self.m33.size_of(ops) +
855            self.m34.size_of(ops) +
856            self.m41.size_of(ops) +
857            self.m42.size_of(ops) +
858            self.m43.size_of(ops) +
859            self.m44.size_of(ops)
860    }
861}
862
863impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::RigidTransform3D<T, Src, Dst> {
864    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
865        self.rotation.i.size_of(ops) +
866            self.rotation.j.size_of(ops) +
867            self.rotation.k.size_of(ops) +
868            self.rotation.r.size_of(ops) +
869            self.translation.x.size_of(ops) +
870            self.translation.y.size_of(ops) +
871            self.translation.z.size_of(ops)
872    }
873}
874
875impl MallocSizeOf for url::Host {
876    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
877        match *self {
878            url::Host::Domain(ref s) => s.size_of(ops),
879            _ => 0,
880        }
881    }
882}
883
884impl MallocSizeOf for url::Url {
885    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
886        // TODO: This is an estimate, but a real size should be calculated in `rust-url` once
887        // it has support for `malloc_size_of`.
888        self.to_string().size_of(ops)
889    }
890}
891
892impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Vector2D<T, U> {
893    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
894        self.x.size_of(ops) + self.y.size_of(ops)
895    }
896}
897
898impl<Static: string_cache::StaticAtomSet> MallocSizeOf for string_cache::Atom<Static> {
899    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
900        0
901    }
902}
903
904impl MallocSizeOf for usvg::Tree {
905    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
906        let root = self.root();
907        let linear_gradients = self.linear_gradients();
908        let radial_gradients = self.radial_gradients();
909        let patterns = self.patterns();
910        let clip_paths = self.clip_paths();
911        let masks = self.masks();
912        let filters = self.filters();
913        let fontdb = self.fontdb();
914
915        let mut sum = root.size_of(ops) +
916            linear_gradients.size_of(ops) +
917            radial_gradients.size_of(ops) +
918            patterns.size_of(ops) +
919            clip_paths.size_of(ops) +
920            masks.size_of(ops) +
921            filters.size_of(ops);
922
923        sum += fontdb.conditional_size_of(ops);
924
925        if ops.has_malloc_enclosing_size_of() {
926            unsafe {
927                sum += ops.malloc_enclosing_size_of(root);
928                if !linear_gradients.is_empty() {
929                    sum += ops.malloc_enclosing_size_of(linear_gradients.as_ptr());
930                }
931                if !radial_gradients.is_empty() {
932                    sum += ops.malloc_enclosing_size_of(radial_gradients.as_ptr());
933                }
934                if !patterns.is_empty() {
935                    sum += ops.malloc_enclosing_size_of(patterns.as_ptr());
936                }
937                if !clip_paths.is_empty() {
938                    sum += ops.malloc_enclosing_size_of(clip_paths.as_ptr());
939                }
940                if !masks.is_empty() {
941                    sum += ops.malloc_enclosing_size_of(masks.as_ptr());
942                }
943                if !filters.is_empty() {
944                    sum += ops.malloc_enclosing_size_of(filters.as_ptr());
945                }
946            }
947        }
948        sum
949    }
950}
951
952impl MallocSizeOf for usvg::Group {
953    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
954        let id = self.id();
955        let children = self.children();
956        let filters = self.filters();
957        let clip_path = self.clip_path();
958
959        let mut sum =
960            id.size_of(ops) + children.size_of(ops) + filters.size_of(ops) + clip_path.size_of(ops);
961
962        if ops.has_malloc_enclosing_size_of() {
963            unsafe {
964                if !id.is_empty() {
965                    sum += ops.malloc_enclosing_size_of(id.as_ptr());
966                }
967                if let Some(c) = clip_path {
968                    sum += ops.malloc_enclosing_size_of(c)
969                }
970                if !children.is_empty() {
971                    sum += ops.malloc_enclosing_size_of(children.as_ptr());
972                }
973                if !filters.is_empty() {
974                    sum += ops.malloc_enclosing_size_of(filters.as_ptr());
975                }
976            }
977        }
978        sum
979    }
980}
981
982impl MallocSizeOf for usvg::Node {
983    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
984        let id = self.id();
985
986        let mut sum = id.size_of(ops);
987        if ops.has_malloc_enclosing_size_of() {
988            unsafe {
989                if !id.is_empty() {
990                    sum += ops.malloc_enclosing_size_of(id.as_ptr())
991                }
992            }
993        }
994        match self {
995            usvg::Node::Group(group) => {
996                sum += group.size_of(ops);
997                if ops.has_malloc_enclosing_size_of() {
998                    unsafe { sum += ops.malloc_enclosing_size_of(group) }
999                }
1000            },
1001            usvg::Node::Path(path) => {
1002                sum += path.size_of(ops);
1003                if ops.has_malloc_enclosing_size_of() {
1004                    unsafe { sum += ops.malloc_enclosing_size_of(path) }
1005                }
1006            },
1007            usvg::Node::Image(image) => {
1008                sum += image.size_of(ops);
1009            },
1010            usvg::Node::Text(text) => {
1011                sum += text.size_of(ops);
1012            },
1013        };
1014        sum
1015    }
1016}
1017
1018impl MallocSizeOf for usvg::Path {
1019    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1020        let id = self.id();
1021        let data = self.data();
1022        let fill = self.fill();
1023        let stroke = self.stroke();
1024
1025        let mut sum = id.size_of(ops) + data.size_of(ops) + fill.size_of(ops) + stroke.size_of(ops);
1026        if ops.has_malloc_enclosing_size_of() {
1027            unsafe {
1028                if !id.is_empty() {
1029                    sum += ops.malloc_enclosing_size_of(id.as_ptr());
1030                }
1031                sum += ops.malloc_enclosing_size_of(data);
1032                if let Some(f) = fill {
1033                    sum += ops.malloc_enclosing_size_of(f)
1034                }
1035                if let Some(s) = stroke {
1036                    sum += ops.malloc_enclosing_size_of(s)
1037                }
1038            }
1039        }
1040        sum
1041    }
1042}
1043impl MallocSizeOf for tiny_skia_path::Path {
1044    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1045        let verbs = self.verbs();
1046        let points = self.points();
1047
1048        let mut sum = verbs.size_of(ops) + points.size_of(ops);
1049        if ops.has_malloc_enclosing_size_of() {
1050            unsafe {
1051                if !points.is_empty() {
1052                    sum += ops.malloc_enclosing_size_of(points.as_ptr());
1053                }
1054                if !verbs.is_empty() {
1055                    sum += ops.malloc_enclosing_size_of(verbs.as_ptr());
1056                }
1057            }
1058        }
1059
1060        sum
1061    }
1062}
1063
1064impl MallocSizeOf for usvg::ClipPath {
1065    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1066        let id = self.id();
1067        let clip_path = self.clip_path();
1068        let root = self.root();
1069
1070        let mut sum = id.size_of(ops) + clip_path.size_of(ops) + root.size_of(ops);
1071        if ops.has_malloc_enclosing_size_of() {
1072            unsafe {
1073                sum += ops.malloc_enclosing_size_of(root);
1074                if !id.is_empty() {
1075                    sum += ops.malloc_enclosing_size_of(id.as_ptr());
1076                }
1077                if let Some(c) = clip_path {
1078                    sum += c.size_of(ops)
1079                }
1080            }
1081        }
1082        sum
1083    }
1084}
1085
1086impl<'a> MallocSizeOf for usvg::Options<'a> {
1087    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1088        self.font_family.size_of(ops) +
1089            self.languages.size_of(ops) +
1090            self.style_sheet.size_of(ops) +
1091            self.fontdb.conditional_shallow_size_of(ops) +
1092            self.resources_dir.size_of(ops)
1093    }
1094}
1095
1096// Placeholder for unique case where internals of Sender cannot be measured.
1097// malloc size of is 0 macro complains about type supplied!
1098impl<T> MallocSizeOf for crossbeam_channel::Sender<T> {
1099    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
1100        0
1101    }
1102}
1103
1104impl<T> MallocSizeOf for crossbeam_channel::Receiver<T> {
1105    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
1106        0
1107    }
1108}
1109
1110impl<T> MallocSizeOf for tokio::sync::mpsc::UnboundedSender<T> {
1111    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
1112        0
1113    }
1114}
1115
1116impl<T> MallocSizeOf for tokio::sync::oneshot::Sender<T> {
1117    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
1118        0
1119    }
1120}
1121
1122impl<T> MallocSizeOf for ipc_channel::ipc::IpcSender<T> {
1123    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
1124        0
1125    }
1126}
1127
1128impl<T> MallocSizeOf for ipc_channel::ipc::IpcReceiver<T> {
1129    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
1130        0
1131    }
1132}
1133
1134impl MallocSizeOf for ipc_channel::ipc::IpcSharedMemory {
1135    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
1136        self.len()
1137    }
1138}
1139
1140impl MallocSizeOf for vello_cpu::Pixmap {
1141    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1142        let data = self.data();
1143        if data.is_empty() {
1144            0
1145        } else {
1146            unsafe { ops.malloc_size_of(data.as_ptr()) }
1147        }
1148    }
1149}
1150
1151impl<T> MallocSizeOf for std::sync::mpsc::Sender<T> {
1152    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
1153        0
1154    }
1155}
1156
1157impl MallocSizeOf for servo_arc::Arc<ComputedValues> {
1158    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1159        self.conditional_size_of(ops)
1160    }
1161}
1162
1163impl MallocSizeOf for http::HeaderMap {
1164    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1165        // The headermap in http is more complicated than a simple hashmap
1166        // However, this should give us a reasonable approximation.
1167        self.iter()
1168            .map(|entry| entry.0.size_of(ops) + entry.1.size_of(ops))
1169            .sum()
1170    }
1171}
1172
1173impl MallocSizeOf for data_url::mime::Mime {
1174    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1175        self.type_.size_of(ops) + self.parameters.size_of(ops) + self.subtype.size_of(ops)
1176    }
1177}
1178
1179malloc_size_of_hash_map!(indexmap::IndexMap<K, V, S>);
1180malloc_size_of_hash_set!(indexmap::IndexSet<T, S>);
1181
1182malloc_size_of_is_0!(bool, char, str);
1183malloc_size_of_is_0!(f32, f64);
1184malloc_size_of_is_0!(i8, i16, i32, i64, i128, isize);
1185malloc_size_of_is_0!(u8, u16, u32, u64, u128, usize);
1186
1187malloc_size_of_is_0!(uuid::Uuid);
1188malloc_size_of_is_0!(app_units::Au);
1189malloc_size_of_is_0!(content_security_policy::Destination);
1190malloc_size_of_is_0!(content_security_policy::sandboxing_directive::SandboxingFlagSet);
1191malloc_size_of_is_0!(encoding_rs::Decoder);
1192malloc_size_of_is_0!(http::StatusCode);
1193malloc_size_of_is_0!(http::Method);
1194malloc_size_of_is_0!(icu_locid::subtags::Language);
1195malloc_size_of_is_0!(keyboard_types::Code);
1196malloc_size_of_is_0!(keyboard_types::Modifiers);
1197malloc_size_of_is_0!(mime::Mime);
1198malloc_size_of_is_0!(resvg::usvg::fontdb::ID);
1199malloc_size_of_is_0!(resvg::usvg::fontdb::Style);
1200malloc_size_of_is_0!(resvg::usvg::fontdb::Weight);
1201malloc_size_of_is_0!(resvg::usvg::fontdb::Stretch);
1202malloc_size_of_is_0!(resvg::usvg::fontdb::Language);
1203malloc_size_of_is_0!(std::num::NonZeroU16);
1204malloc_size_of_is_0!(std::num::NonZeroU32);
1205malloc_size_of_is_0!(std::num::NonZeroU64);
1206malloc_size_of_is_0!(std::num::NonZeroUsize);
1207malloc_size_of_is_0!(std::sync::atomic::AtomicBool);
1208malloc_size_of_is_0!(std::sync::atomic::AtomicI32);
1209malloc_size_of_is_0!(std::sync::atomic::AtomicIsize);
1210malloc_size_of_is_0!(std::sync::atomic::AtomicU32);
1211malloc_size_of_is_0!(std::sync::atomic::AtomicU8);
1212malloc_size_of_is_0!(std::sync::atomic::AtomicUsize);
1213malloc_size_of_is_0!(std::time::Duration);
1214malloc_size_of_is_0!(std::time::Instant);
1215malloc_size_of_is_0!(std::time::SystemTime);
1216malloc_size_of_is_0!(style::data::ElementDataWrapper);
1217malloc_size_of_is_0!(style::font_face::SourceList);
1218malloc_size_of_is_0!(style::properties::ComputedValues);
1219malloc_size_of_is_0!(style::properties::declaration_block::PropertyDeclarationBlock);
1220malloc_size_of_is_0!(style::queries::values::PrefersColorScheme);
1221malloc_size_of_is_0!(style::stylesheets::Stylesheet);
1222malloc_size_of_is_0!(style::stylesheets::FontFaceRule);
1223malloc_size_of_is_0!(style::values::specified::source_size_list::SourceSizeList);
1224malloc_size_of_is_0!(taffy::Layout);
1225malloc_size_of_is_0!(time::Duration);
1226malloc_size_of_is_0!(unicode_bidi::Level);
1227malloc_size_of_is_0!(unicode_script::Script);
1228malloc_size_of_is_0!(std::net::TcpStream);
1229
1230impl MallocSizeOf for urlpattern::UrlPattern {
1231    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
1232        // This is an approximation
1233        self.protocol().len() +
1234            self.username().len() +
1235            self.password().len() +
1236            self.hostname().len() +
1237            self.port().len() +
1238            self.pathname().len() +
1239            self.search().len() +
1240            self.hash().len()
1241    }
1242}
1243
1244impl<S: tendril::TendrilSink<tendril::fmt::UTF8, A>, A: tendril::Atomicity> MallocSizeOf
1245    for tendril::stream::LossyDecoder<S, A>
1246{
1247    fn size_of(&self, _: &mut MallocSizeOfOps) -> usize {
1248        0
1249    }
1250}
1251
1252impl<F: tendril::Format> MallocSizeOf for tendril::SendTendril<F> {
1253    fn size_of(&self, _: &mut MallocSizeOfOps) -> usize {
1254        0
1255    }
1256}
1257
1258macro_rules! malloc_size_of_is_webrender_malloc_size_of(
1259    ($($ty:ty),+) => (
1260        $(
1261            impl MallocSizeOf for $ty {
1262                fn size_of(&self, _: &mut MallocSizeOfOps) -> usize {
1263                    let mut ops = wr_malloc_size_of::MallocSizeOfOps::new(servo_allocator::usable_size, None);
1264                    <$ty as wr_malloc_size_of::MallocSizeOf>::size_of(self, &mut ops)
1265                }
1266            }
1267        )+
1268    );
1269);
1270
1271malloc_size_of_is_webrender_malloc_size_of!(webrender::FastTransform<webrender_api::units::LayoutPixel, webrender_api::units::LayoutPixel>);
1272malloc_size_of_is_webrender_malloc_size_of!(webrender_api::BorderRadius);
1273malloc_size_of_is_webrender_malloc_size_of!(webrender_api::BorderStyle);
1274malloc_size_of_is_webrender_malloc_size_of!(webrender_api::BoxShadowClipMode);
1275malloc_size_of_is_webrender_malloc_size_of!(webrender_api::ColorF);
1276malloc_size_of_is_webrender_malloc_size_of!(webrender_api::Epoch);
1277malloc_size_of_is_webrender_malloc_size_of!(webrender_api::ExtendMode);
1278malloc_size_of_is_webrender_malloc_size_of!(webrender_api::ExternalScrollId);
1279malloc_size_of_is_webrender_malloc_size_of!(webrender_api::FontInstanceFlags);
1280malloc_size_of_is_webrender_malloc_size_of!(webrender_api::FontInstanceKey);
1281malloc_size_of_is_webrender_malloc_size_of!(webrender_api::FontKey);
1282malloc_size_of_is_webrender_malloc_size_of!(webrender_api::FontVariation);
1283malloc_size_of_is_webrender_malloc_size_of!(webrender_api::GlyphInstance);
1284malloc_size_of_is_webrender_malloc_size_of!(webrender_api::GradientStop);
1285malloc_size_of_is_webrender_malloc_size_of!(webrender_api::ImageKey);
1286malloc_size_of_is_webrender_malloc_size_of!(webrender_api::ImageRendering);
1287malloc_size_of_is_webrender_malloc_size_of!(webrender_api::LineStyle);
1288malloc_size_of_is_webrender_malloc_size_of!(webrender_api::MixBlendMode);
1289malloc_size_of_is_webrender_malloc_size_of!(webrender_api::NormalBorder);
1290malloc_size_of_is_webrender_malloc_size_of!(webrender_api::PipelineId);
1291malloc_size_of_is_webrender_malloc_size_of!(
1292    webrender_api::PropertyBindingKey<webrender_api::ColorF>
1293);
1294malloc_size_of_is_webrender_malloc_size_of!(webrender_api::ReferenceFrameKind);
1295malloc_size_of_is_webrender_malloc_size_of!(webrender_api::RepeatMode);
1296malloc_size_of_is_webrender_malloc_size_of!(webrender_api::SpatialId);
1297malloc_size_of_is_webrender_malloc_size_of!(webrender_api::StickyOffsetBounds);
1298malloc_size_of_is_webrender_malloc_size_of!(webrender_api::TransformStyle);
1299
1300macro_rules! malloc_size_of_is_stylo_malloc_size_of(
1301    ($($ty:ty),+) => (
1302        $(
1303            impl MallocSizeOf for $ty {
1304                fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1305                    <$ty as stylo_malloc_size_of::MallocSizeOf>::size_of(self, ops)
1306                }
1307            }
1308        )+
1309    );
1310);
1311
1312impl<S> MallocSizeOf for style::author_styles::GenericAuthorStyles<S>
1313where
1314    S: style::stylesheets::StylesheetInDocument
1315        + std::cmp::PartialEq
1316        + stylo_malloc_size_of::MallocSizeOf,
1317{
1318    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1319        <style::author_styles::GenericAuthorStyles<S> as stylo_malloc_size_of::MallocSizeOf>::size_of(self, ops)
1320    }
1321}
1322
1323impl<S> MallocSizeOf for style::stylesheet_set::DocumentStylesheetSet<S>
1324where
1325    S: style::stylesheets::StylesheetInDocument
1326        + std::cmp::PartialEq
1327        + stylo_malloc_size_of::MallocSizeOf,
1328{
1329    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1330        <style::stylesheet_set::DocumentStylesheetSet<S> as stylo_malloc_size_of::MallocSizeOf>::size_of(self, ops)
1331    }
1332}
1333
1334impl<T> MallocSizeOf for style::shared_lock::Locked<T> {
1335    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
1336        // TODO: fix this implementation when Locked derives MallocSizeOf.
1337        0
1338        // <style::shared_lock::Locked<T> as stylo_malloc_size_of::MallocSizeOf>::size_of(self, ops)
1339    }
1340}
1341
1342impl<T: MallocSizeOf> MallocSizeOf for atomic_refcell::AtomicRefCell<T> {
1343    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1344        self.borrow().size_of(ops)
1345    }
1346}
1347
1348impl<T: stylo_malloc_size_of::MallocSizeOf, const FRACTION_BITS: u16> MallocSizeOf
1349    for style::values::computed::font::FixedPoint<T, FRACTION_BITS>
1350{
1351    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1352        <Self as stylo_malloc_size_of::MallocSizeOf>::size_of(self, ops)
1353    }
1354}
1355
1356impl<Integer, Number, LinearStops> MallocSizeOf
1357    for style::values::generics::easing::TimingFunction<Integer, Number, LinearStops>
1358where
1359    Integer: stylo_malloc_size_of::MallocSizeOf,
1360    Number: stylo_malloc_size_of::MallocSizeOf,
1361    LinearStops: stylo_malloc_size_of::MallocSizeOf,
1362{
1363    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1364        <Self as stylo_malloc_size_of::MallocSizeOf>::size_of(self, ops)
1365    }
1366}
1367
1368malloc_size_of_is_stylo_malloc_size_of!(style::properties::PropertyId);
1369malloc_size_of_is_stylo_malloc_size_of!(style::animation::DocumentAnimationSet);
1370malloc_size_of_is_stylo_malloc_size_of!(style::attr::AttrIdentifier);
1371malloc_size_of_is_stylo_malloc_size_of!(style::attr::AttrValue);
1372malloc_size_of_is_stylo_malloc_size_of!(style::color::AbsoluteColor);
1373malloc_size_of_is_stylo_malloc_size_of!(style::computed_values::font_variant_caps::T);
1374malloc_size_of_is_stylo_malloc_size_of!(style::computed_values::font_variant_position::T);
1375malloc_size_of_is_stylo_malloc_size_of!(style::computed_values::text_decoration_style::T);
1376malloc_size_of_is_stylo_malloc_size_of!(style::computed_values::text_decoration_thickness::T);
1377malloc_size_of_is_stylo_malloc_size_of!(style::computed_values::text_rendering::T);
1378malloc_size_of_is_stylo_malloc_size_of!(style::dom::OpaqueNode);
1379malloc_size_of_is_stylo_malloc_size_of!(style::font_face::ComputedFontStretchRange);
1380malloc_size_of_is_stylo_malloc_size_of!(style::font_face::ComputedFontStyleRange);
1381malloc_size_of_is_stylo_malloc_size_of!(style::font_face::ComputedFontWeightRange);
1382malloc_size_of_is_stylo_malloc_size_of!(style::font_face::Source);
1383malloc_size_of_is_stylo_malloc_size_of!(style::invalidation::element::restyle_hints::RestyleHint);
1384malloc_size_of_is_stylo_malloc_size_of!(style::logical_geometry::WritingMode);
1385malloc_size_of_is_stylo_malloc_size_of!(style::media_queries::MediaList);
1386malloc_size_of_is_stylo_malloc_size_of!(style::properties::generated::font_face::Descriptors);
1387malloc_size_of_is_stylo_malloc_size_of!(
1388    style::properties::longhands::align_items::computed_value::T
1389);
1390malloc_size_of_is_stylo_malloc_size_of!(
1391    style::properties::longhands::flex_direction::computed_value::T
1392);
1393malloc_size_of_is_stylo_malloc_size_of!(style::properties::longhands::flex_wrap::computed_value::T);
1394malloc_size_of_is_stylo_malloc_size_of!(style::properties::style_structs::Font);
1395malloc_size_of_is_stylo_malloc_size_of!(style::selector_parser::PseudoElement);
1396malloc_size_of_is_stylo_malloc_size_of!(style::selector_parser::RestyleDamage);
1397malloc_size_of_is_stylo_malloc_size_of!(style::selector_parser::Snapshot);
1398malloc_size_of_is_stylo_malloc_size_of!(style::shared_lock::SharedRwLock);
1399malloc_size_of_is_stylo_malloc_size_of!(style::stylesheets::DocumentStyleSheet);
1400malloc_size_of_is_stylo_malloc_size_of!(style::stylesheets::Origin);
1401malloc_size_of_is_stylo_malloc_size_of!(style::stylist::Stylist);
1402malloc_size_of_is_stylo_malloc_size_of!(style::values::computed::BorderStyle);
1403malloc_size_of_is_stylo_malloc_size_of!(style::values::computed::ContentDistribution);
1404malloc_size_of_is_stylo_malloc_size_of!(style::values::computed::FontFeatureSettings);
1405malloc_size_of_is_stylo_malloc_size_of!(style::values::computed::FontStretch);
1406malloc_size_of_is_stylo_malloc_size_of!(style::values::computed::FontStyle);
1407malloc_size_of_is_stylo_malloc_size_of!(style::values::computed::FontWeight);
1408malloc_size_of_is_stylo_malloc_size_of!(style::values::computed::FontVariantAlternates);
1409malloc_size_of_is_stylo_malloc_size_of!(style::values::computed::FontVariantLigatures);
1410malloc_size_of_is_stylo_malloc_size_of!(style::values::computed::FontVariantNumeric);
1411malloc_size_of_is_stylo_malloc_size_of!(style::values::computed::FontVariantEastAsian);
1412malloc_size_of_is_stylo_malloc_size_of!(style::values::computed::font::SingleFontFamily);
1413malloc_size_of_is_stylo_malloc_size_of!(style::values::specified::align::AlignFlags);
1414malloc_size_of_is_stylo_malloc_size_of!(style::values::specified::box_::Overflow);
1415malloc_size_of_is_stylo_malloc_size_of!(style::values::specified::font::FontSynthesis);
1416malloc_size_of_is_stylo_malloc_size_of!(style::values::specified::font::XLang);
1417malloc_size_of_is_stylo_malloc_size_of!(style::values::specified::TextDecorationLine);
1418malloc_size_of_is_stylo_malloc_size_of!(stylo_dom::ElementState);
1419malloc_size_of_is_stylo_malloc_size_of!(style::computed_values::font_optical_sizing::T);
1420malloc_size_of_is_stylo_malloc_size_of!(style::computed_values::font_kerning::T);
1421malloc_size_of_is_stylo_malloc_size_of!(style::stylesheets::font_feature_values_rule::SingleValue);
1422malloc_size_of_is_stylo_malloc_size_of!(style::stylesheets::font_feature_values_rule::PairValues);
1423malloc_size_of_is_stylo_malloc_size_of!(style::stylesheets::font_feature_values_rule::VectorValues);
1424malloc_size_of_is_stylo_malloc_size_of!(
1425    style::stylesheets::font_feature_values_rule::FontFeatureValuesRule
1426);
1427
1428impl<T> MallocSizeOf for GenericLengthPercentageOrAuto<T>
1429where
1430    T: stylo_malloc_size_of::MallocSizeOf,
1431{
1432    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1433        <GenericLengthPercentageOrAuto<T> as stylo_malloc_size_of::MallocSizeOf>::size_of(self, ops)
1434    }
1435}
1436
1437impl MallocSizeOf for resvg::usvg::fontdb::Source {
1438    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1439        match self {
1440            Source::Binary(_) => 0,
1441            Source::File(path) => path.size_of(ops),
1442            Source::SharedFile(path, _) => path.size_of(ops),
1443        }
1444    }
1445}
1446
1447impl MallocSizeOf for resvg::usvg::fontdb::FaceInfo {
1448    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1449        self.id.size_of(ops) +
1450            self.source.size_of(ops) +
1451            self.families.size_of(ops) +
1452            self.post_script_name.size_of(ops) +
1453            self.style.size_of(ops) +
1454            self.weight.size_of(ops) +
1455            self.stretch.size_of(ops)
1456    }
1457}
1458
1459impl MallocSizeOf for resvg::usvg::fontdb::Database {
1460    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1461        self.faces().map(|face| face.size_of(ops)).sum()
1462    }
1463}
1464
1465impl<T> MallocSizeOf for once_cell::race::OnceBox<T>
1466where
1467    T: MallocSizeOf,
1468{
1469    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1470        if let Some(value) = self.get() {
1471            (unsafe { ops.malloc_size_of::<T>(value) }) + value.size_of(ops)
1472        } else {
1473            0
1474        }
1475    }
1476}