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;
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
460macro_rules! malloc_size_of_hash_set {
461    ($ty:ty) => {
462        impl<T, S> MallocShallowSizeOf for $ty
463        where
464            T: Eq + Hash,
465            S: BuildHasher,
466        {
467            fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
468                if ops.has_malloc_enclosing_size_of() {
469                    // The first value from the iterator gives us an interior pointer.
470                    // `ops.malloc_enclosing_size_of()` then gives us the storage size.
471                    // This assumes that the `HashSet`'s contents (values and hashes)
472                    // are all stored in a single contiguous heap allocation.
473                    self.iter()
474                        .next()
475                        .map_or(0, |t| unsafe { ops.malloc_enclosing_size_of(t) })
476                } else {
477                    // An estimate.
478                    self.capacity() * (size_of::<T>() + size_of::<usize>())
479                }
480            }
481        }
482
483        impl<T, S> MallocSizeOf for $ty
484        where
485            T: Eq + Hash + MallocSizeOf,
486            S: BuildHasher,
487        {
488            fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
489                let mut n = self.shallow_size_of(ops);
490                for t in self.iter() {
491                    n += t.size_of(ops);
492                }
493                n
494            }
495        }
496    };
497}
498
499malloc_size_of_hash_set!(std::collections::HashSet<T, S>);
500
501macro_rules! malloc_size_of_hash_map {
502    ($ty:ty) => {
503        impl<K, V, S> MallocShallowSizeOf for $ty
504        where
505            K: Eq + Hash,
506            S: BuildHasher,
507        {
508            fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
509                // See the implementation for std::collections::HashSet for details.
510                if ops.has_malloc_enclosing_size_of() {
511                    self.values()
512                        .next()
513                        .map_or(0, |v| unsafe { ops.malloc_enclosing_size_of(v) })
514                } else {
515                    self.capacity() * (size_of::<V>() + size_of::<K>() + size_of::<usize>())
516                }
517            }
518        }
519
520        impl<K, V, S> MallocSizeOf for $ty
521        where
522            K: Eq + Hash + MallocSizeOf,
523            V: MallocSizeOf,
524            S: BuildHasher,
525        {
526            fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
527                let mut n = self.shallow_size_of(ops);
528                for (k, v) in self.iter() {
529                    n += k.size_of(ops);
530                    n += v.size_of(ops);
531                }
532                n
533            }
534        }
535
536        impl<K, V, S> MallocConditionalSizeOf for $ty
537        where
538            K: Eq + Hash + MallocSizeOf,
539            V: MallocConditionalSizeOf,
540            S: BuildHasher,
541        {
542            fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
543                let mut n = self.shallow_size_of(ops);
544                for (k, v) in self.iter() {
545                    n += k.size_of(ops);
546                    n += v.conditional_size_of(ops);
547                }
548                n
549            }
550        }
551    };
552}
553
554malloc_size_of_hash_map!(std::collections::HashMap<K, V, S>);
555
556impl<K, V> MallocShallowSizeOf for std::collections::BTreeMap<K, V>
557where
558    K: Eq + Hash,
559{
560    fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
561        if ops.has_malloc_enclosing_size_of() {
562            self.values()
563                .next()
564                .map_or(0, |v| unsafe { ops.malloc_enclosing_size_of(v) })
565        } else {
566            self.len() * (size_of::<V>() + size_of::<K>() + size_of::<usize>())
567        }
568    }
569}
570
571impl<K, V> MallocSizeOf for std::collections::BTreeMap<K, V>
572where
573    K: Eq + Hash + MallocSizeOf,
574    V: MallocSizeOf,
575{
576    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
577        let mut n = self.shallow_size_of(ops);
578        for (k, v) in self.iter() {
579            n += k.size_of(ops);
580            n += v.size_of(ops);
581        }
582        n
583    }
584}
585
586// PhantomData is always 0.
587impl<T> MallocSizeOf for std::marker::PhantomData<T> {
588    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
589        0
590    }
591}
592
593impl<T: MallocSizeOf> MallocSizeOf for OnceCell<T> {
594    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
595        self.get()
596            .map(|interior| interior.size_of(ops))
597            .unwrap_or_default()
598    }
599}
600
601impl<T: MallocConditionalSizeOf> MallocConditionalSizeOf for OnceCell<T> {
602    fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
603        self.get()
604            .map(|interior| interior.conditional_size_of(ops))
605            .unwrap_or_default()
606    }
607}
608
609impl<T: MallocSizeOf> MallocSizeOf for OnceLock<T> {
610    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
611        self.get()
612            .map(|interior| interior.size_of(ops))
613            .unwrap_or_default()
614    }
615}
616
617impl<T: MallocConditionalSizeOf> MallocConditionalSizeOf for OnceLock<T> {
618    fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
619        self.get()
620            .map(|interior| interior.conditional_size_of(ops))
621            .unwrap_or_default()
622    }
623}
624
625// See https://github.com/rust-lang/rust/issues/68318:
626// We don't want MallocSizeOf to be defined for Rc and Arc. If negative trait bounds are
627// ever allowed, this code should be uncommented.  Instead, there is a compile-fail test for
628// this.
629// impl<T> !MallocSizeOf for Arc<T> { }
630// impl<T> !MallocShallowSizeOf for Arc<T> { }
631
632impl<T> MallocUnconditionalShallowSizeOf for servo_arc::Arc<T> {
633    fn unconditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
634        unsafe { ops.malloc_size_of(self.heap_ptr()) }
635    }
636}
637
638impl<T: MallocSizeOf> MallocUnconditionalSizeOf for servo_arc::Arc<T> {
639    fn unconditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
640        self.unconditional_shallow_size_of(ops) + (**self).size_of(ops)
641    }
642}
643
644impl<T> MallocConditionalShallowSizeOf for servo_arc::Arc<T> {
645    fn conditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
646        if ops.have_seen_ptr(self.heap_ptr()) {
647            0
648        } else {
649            self.unconditional_shallow_size_of(ops)
650        }
651    }
652}
653
654impl<T: MallocSizeOf> MallocConditionalSizeOf for servo_arc::Arc<T> {
655    fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
656        if ops.have_seen_ptr(self.heap_ptr()) {
657            0
658        } else {
659            self.unconditional_size_of(ops)
660        }
661    }
662}
663
664impl<T> MallocUnconditionalShallowSizeOf for Arc<T> {
665    fn unconditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
666        unsafe { ops.malloc_size_of(Arc::as_ptr(self)) }
667    }
668}
669
670impl<T: MallocSizeOf> MallocUnconditionalSizeOf for Arc<T> {
671    fn unconditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
672        self.unconditional_shallow_size_of(ops) + (**self).size_of(ops)
673    }
674}
675
676impl<T> MallocConditionalShallowSizeOf for Arc<T> {
677    fn conditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
678        if ops.have_seen_ptr(Arc::as_ptr(self)) {
679            0
680        } else {
681            self.unconditional_shallow_size_of(ops)
682        }
683    }
684}
685
686impl<T: MallocSizeOf> MallocConditionalSizeOf for Arc<T> {
687    fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
688        if ops.have_seen_ptr(Arc::as_ptr(self)) {
689            0
690        } else {
691            self.unconditional_size_of(ops)
692        }
693    }
694}
695
696impl<T> MallocUnconditionalShallowSizeOf for Rc<T> {
697    fn unconditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
698        unsafe { ops.malloc_size_of(Rc::as_ptr(self)) }
699    }
700}
701
702impl<T: MallocSizeOf> MallocUnconditionalSizeOf for Rc<T> {
703    fn unconditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
704        self.unconditional_shallow_size_of(ops) + (**self).size_of(ops)
705    }
706}
707
708impl<T: MallocSizeOf> MallocConditionalSizeOf for Rc<T> {
709    fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
710        if ops.have_seen_ptr(Rc::as_ptr(self)) {
711            0
712        } else {
713            self.unconditional_size_of(ops)
714        }
715    }
716}
717
718impl<T: MallocSizeOf> MallocSizeOf for std::sync::Weak<T> {
719    fn size_of(&self, _: &mut MallocSizeOfOps) -> usize {
720        // A weak reference to the data necessarily has another strong reference
721        // somewhere else where it can be measured or...it's been released and is zero.
722        0
723    }
724}
725
726/// If a mutex is stored directly as a member of a data type that is being measured,
727/// it is the unique owner of its contents and deserves to be measured.
728///
729/// If a mutex is stored inside of an Arc value as a member of a data type that is being measured,
730/// the Arc will not be automatically measured so there is no risk of overcounting the mutex's
731/// contents.
732impl<T: MallocSizeOf> MallocSizeOf for std::sync::Mutex<T> {
733    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
734        (*self.lock().unwrap()).size_of(ops)
735    }
736}
737
738impl<T: MallocSizeOf> MallocSizeOf for parking_lot::Mutex<T> {
739    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
740        (*self.lock()).size_of(ops)
741    }
742}
743
744impl<T: MallocSizeOf> MallocSizeOf for parking_lot::RwLock<T> {
745    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
746        (*self.read()).size_of(ops)
747    }
748}
749
750impl<T: MallocConditionalSizeOf> MallocConditionalSizeOf for parking_lot::RwLock<T> {
751    fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
752        (*self.read()).conditional_size_of(ops)
753    }
754}
755
756impl<T: MallocSizeOf, Unit> MallocSizeOf for euclid::Length<T, Unit> {
757    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
758        self.0.size_of(ops)
759    }
760}
761
762impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::Scale<T, Src, Dst> {
763    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
764        self.0.size_of(ops)
765    }
766}
767
768impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Point2D<T, U> {
769    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
770        self.x.size_of(ops) + self.y.size_of(ops)
771    }
772}
773
774impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Box2D<T, U> {
775    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
776        self.min.size_of(ops) + self.max.size_of(ops)
777    }
778}
779
780impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Vector3D<T, U> {
781    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
782        self.x.size_of(ops) + self.y.size_of(ops) + self.z.size_of(ops)
783    }
784}
785
786impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Rect<T, U> {
787    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
788        self.origin.size_of(ops) + self.size.size_of(ops)
789    }
790}
791
792impl<T: MallocSizeOf, U> MallocSizeOf for euclid::SideOffsets2D<T, U> {
793    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
794        self.top.size_of(ops) +
795            self.right.size_of(ops) +
796            self.bottom.size_of(ops) +
797            self.left.size_of(ops)
798    }
799}
800
801impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Size2D<T, U> {
802    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
803        self.width.size_of(ops) + self.height.size_of(ops)
804    }
805}
806
807impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::Transform2D<T, Src, Dst> {
808    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
809        self.m11.size_of(ops) +
810            self.m12.size_of(ops) +
811            self.m21.size_of(ops) +
812            self.m22.size_of(ops) +
813            self.m31.size_of(ops) +
814            self.m32.size_of(ops)
815    }
816}
817
818impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::Transform3D<T, Src, Dst> {
819    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
820        self.m11.size_of(ops) +
821            self.m12.size_of(ops) +
822            self.m13.size_of(ops) +
823            self.m14.size_of(ops) +
824            self.m21.size_of(ops) +
825            self.m22.size_of(ops) +
826            self.m23.size_of(ops) +
827            self.m24.size_of(ops) +
828            self.m31.size_of(ops) +
829            self.m32.size_of(ops) +
830            self.m33.size_of(ops) +
831            self.m34.size_of(ops) +
832            self.m41.size_of(ops) +
833            self.m42.size_of(ops) +
834            self.m43.size_of(ops) +
835            self.m44.size_of(ops)
836    }
837}
838
839impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::RigidTransform3D<T, Src, Dst> {
840    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
841        self.rotation.i.size_of(ops) +
842            self.rotation.j.size_of(ops) +
843            self.rotation.k.size_of(ops) +
844            self.rotation.r.size_of(ops) +
845            self.translation.x.size_of(ops) +
846            self.translation.y.size_of(ops) +
847            self.translation.z.size_of(ops)
848    }
849}
850
851impl MallocSizeOf for url::Host {
852    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
853        match *self {
854            url::Host::Domain(ref s) => s.size_of(ops),
855            _ => 0,
856        }
857    }
858}
859
860impl MallocSizeOf for url::Url {
861    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
862        // TODO: This is an estimate, but a real size should be calculated in `rust-url` once
863        // it has support for `malloc_size_of`.
864        self.to_string().size_of(ops)
865    }
866}
867
868impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Vector2D<T, U> {
869    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
870        self.x.size_of(ops) + self.y.size_of(ops)
871    }
872}
873
874impl<Static: string_cache::StaticAtomSet> MallocSizeOf for string_cache::Atom<Static> {
875    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
876        0
877    }
878}
879
880impl MallocSizeOf for usvg::Tree {
881    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
882        let root = self.root();
883        let linear_gradients = self.linear_gradients();
884        let radial_gradients = self.radial_gradients();
885        let patterns = self.patterns();
886        let clip_paths = self.clip_paths();
887        let masks = self.masks();
888        let filters = self.filters();
889        let fontdb = self.fontdb();
890
891        let mut sum = root.size_of(ops) +
892            linear_gradients.size_of(ops) +
893            radial_gradients.size_of(ops) +
894            patterns.size_of(ops) +
895            clip_paths.size_of(ops) +
896            masks.size_of(ops) +
897            filters.size_of(ops);
898
899        sum += fontdb.conditional_size_of(ops);
900
901        if ops.has_malloc_enclosing_size_of() {
902            unsafe {
903                sum += ops.malloc_enclosing_size_of(root);
904                if !linear_gradients.is_empty() {
905                    sum += ops.malloc_enclosing_size_of(linear_gradients.as_ptr());
906                }
907                if !radial_gradients.is_empty() {
908                    sum += ops.malloc_enclosing_size_of(radial_gradients.as_ptr());
909                }
910                if !patterns.is_empty() {
911                    sum += ops.malloc_enclosing_size_of(patterns.as_ptr());
912                }
913                if !clip_paths.is_empty() {
914                    sum += ops.malloc_enclosing_size_of(clip_paths.as_ptr());
915                }
916                if !masks.is_empty() {
917                    sum += ops.malloc_enclosing_size_of(masks.as_ptr());
918                }
919                if !filters.is_empty() {
920                    sum += ops.malloc_enclosing_size_of(filters.as_ptr());
921                }
922            }
923        }
924        sum
925    }
926}
927
928impl MallocSizeOf for usvg::Group {
929    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
930        let id = self.id();
931        let children = self.children();
932        let filters = self.filters();
933        let clip_path = self.clip_path();
934
935        let mut sum =
936            id.size_of(ops) + children.size_of(ops) + filters.size_of(ops) + clip_path.size_of(ops);
937
938        if ops.has_malloc_enclosing_size_of() {
939            unsafe {
940                if !id.is_empty() {
941                    sum += ops.malloc_enclosing_size_of(id.as_ptr());
942                }
943                if let Some(c) = clip_path {
944                    sum += ops.malloc_enclosing_size_of(c)
945                }
946                if !children.is_empty() {
947                    sum += ops.malloc_enclosing_size_of(children.as_ptr());
948                }
949                if !filters.is_empty() {
950                    sum += ops.malloc_enclosing_size_of(filters.as_ptr());
951                }
952            }
953        }
954        sum
955    }
956}
957
958impl MallocSizeOf for usvg::Node {
959    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
960        let id = self.id();
961
962        let mut sum = id.size_of(ops);
963        if ops.has_malloc_enclosing_size_of() {
964            unsafe {
965                if !id.is_empty() {
966                    sum += ops.malloc_enclosing_size_of(id.as_ptr())
967                }
968            }
969        }
970        match self {
971            usvg::Node::Group(group) => {
972                sum += group.size_of(ops);
973                if ops.has_malloc_enclosing_size_of() {
974                    unsafe { sum += ops.malloc_enclosing_size_of(group) }
975                }
976            },
977            usvg::Node::Path(path) => {
978                sum += path.size_of(ops);
979                if ops.has_malloc_enclosing_size_of() {
980                    unsafe { sum += ops.malloc_enclosing_size_of(path) }
981                }
982            },
983            usvg::Node::Image(image) => {
984                sum += image.size_of(ops);
985            },
986            usvg::Node::Text(text) => {
987                sum += text.size_of(ops);
988            },
989        };
990        sum
991    }
992}
993
994impl MallocSizeOf for usvg::Path {
995    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
996        let id = self.id();
997        let data = self.data();
998        let fill = self.fill();
999        let stroke = self.stroke();
1000
1001        let mut sum = id.size_of(ops) + data.size_of(ops) + fill.size_of(ops) + stroke.size_of(ops);
1002        if ops.has_malloc_enclosing_size_of() {
1003            unsafe {
1004                if !id.is_empty() {
1005                    sum += ops.malloc_enclosing_size_of(id.as_ptr());
1006                }
1007                sum += ops.malloc_enclosing_size_of(data);
1008                if let Some(f) = fill {
1009                    sum += ops.malloc_enclosing_size_of(f)
1010                }
1011                if let Some(s) = stroke {
1012                    sum += ops.malloc_enclosing_size_of(s)
1013                }
1014            }
1015        }
1016        sum
1017    }
1018}
1019impl MallocSizeOf for tiny_skia_path::Path {
1020    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1021        let verbs = self.verbs();
1022        let points = self.points();
1023
1024        let mut sum = verbs.size_of(ops) + points.size_of(ops);
1025        if ops.has_malloc_enclosing_size_of() {
1026            unsafe {
1027                if !points.is_empty() {
1028                    sum += ops.malloc_enclosing_size_of(points.as_ptr());
1029                }
1030                if !verbs.is_empty() {
1031                    sum += ops.malloc_enclosing_size_of(verbs.as_ptr());
1032                }
1033            }
1034        }
1035
1036        sum
1037    }
1038}
1039
1040impl MallocSizeOf for usvg::ClipPath {
1041    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1042        let id = self.id();
1043        let clip_path = self.clip_path();
1044        let root = self.root();
1045
1046        let mut sum = id.size_of(ops) + clip_path.size_of(ops) + root.size_of(ops);
1047        if ops.has_malloc_enclosing_size_of() {
1048            unsafe {
1049                sum += ops.malloc_enclosing_size_of(root);
1050                if !id.is_empty() {
1051                    sum += ops.malloc_enclosing_size_of(id.as_ptr());
1052                }
1053                if let Some(c) = clip_path {
1054                    sum += c.size_of(ops)
1055                }
1056            }
1057        }
1058        sum
1059    }
1060}
1061
1062// Placeholder for unique case where internals of Sender cannot be measured.
1063// malloc size of is 0 macro complains about type supplied!
1064impl<T> MallocSizeOf for crossbeam_channel::Sender<T> {
1065    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
1066        0
1067    }
1068}
1069
1070impl<T> MallocSizeOf for crossbeam_channel::Receiver<T> {
1071    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
1072        0
1073    }
1074}
1075
1076impl<T> MallocSizeOf for tokio::sync::mpsc::UnboundedSender<T> {
1077    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
1078        0
1079    }
1080}
1081
1082impl<T> MallocSizeOf for tokio::sync::oneshot::Sender<T> {
1083    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
1084        0
1085    }
1086}
1087
1088impl<T> MallocSizeOf for ipc_channel::ipc::IpcSender<T> {
1089    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
1090        0
1091    }
1092}
1093
1094impl<T> MallocSizeOf for ipc_channel::ipc::IpcReceiver<T> {
1095    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
1096        0
1097    }
1098}
1099
1100impl MallocSizeOf for ipc_channel::ipc::IpcSharedMemory {
1101    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
1102        self.len()
1103    }
1104}
1105
1106impl<T> MallocSizeOf for std::sync::mpsc::Sender<T> {
1107    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
1108        0
1109    }
1110}
1111
1112impl<T: MallocSizeOf> MallocSizeOf for accountable_refcell::RefCell<T> {
1113    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1114        self.borrow().size_of(ops)
1115    }
1116}
1117
1118impl MallocSizeOf for servo_arc::Arc<ComputedValues> {
1119    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1120        self.conditional_size_of(ops)
1121    }
1122}
1123
1124impl MallocSizeOf for http::HeaderMap {
1125    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1126        // The headermap in http is more complicated than a simple hashmap
1127        // However, this should give us a reasonable approximation.
1128        self.iter()
1129            .map(|entry| entry.0.size_of(ops) + entry.1.size_of(ops))
1130            .sum()
1131    }
1132}
1133
1134impl MallocSizeOf for data_url::mime::Mime {
1135    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1136        self.type_.size_of(ops) + self.parameters.size_of(ops) + self.subtype.size_of(ops)
1137    }
1138}
1139
1140malloc_size_of_hash_map!(indexmap::IndexMap<K, V, S>);
1141malloc_size_of_hash_set!(indexmap::IndexSet<T, S>);
1142
1143malloc_size_of_is_0!(bool, char, str);
1144malloc_size_of_is_0!(f32, f64);
1145malloc_size_of_is_0!(i8, i16, i32, i64, i128, isize);
1146malloc_size_of_is_0!(u8, u16, u32, u64, u128, usize);
1147
1148malloc_size_of_is_0!(uuid::Uuid);
1149malloc_size_of_is_0!(app_units::Au);
1150malloc_size_of_is_0!(content_security_policy::Destination);
1151malloc_size_of_is_0!(content_security_policy::sandboxing_directive::SandboxingFlagSet);
1152malloc_size_of_is_0!(encoding_rs::Decoder);
1153malloc_size_of_is_0!(http::StatusCode);
1154malloc_size_of_is_0!(http::Method);
1155malloc_size_of_is_0!(icu_locid::subtags::Language);
1156malloc_size_of_is_0!(keyboard_types::Code);
1157malloc_size_of_is_0!(keyboard_types::Modifiers);
1158malloc_size_of_is_0!(mime::Mime);
1159malloc_size_of_is_0!(resvg::usvg::fontdb::ID);
1160malloc_size_of_is_0!(resvg::usvg::fontdb::Style);
1161malloc_size_of_is_0!(resvg::usvg::fontdb::Weight);
1162malloc_size_of_is_0!(resvg::usvg::fontdb::Stretch);
1163malloc_size_of_is_0!(resvg::usvg::fontdb::Language);
1164malloc_size_of_is_0!(std::num::NonZeroU16);
1165malloc_size_of_is_0!(std::num::NonZeroU32);
1166malloc_size_of_is_0!(std::num::NonZeroU64);
1167malloc_size_of_is_0!(std::num::NonZeroUsize);
1168malloc_size_of_is_0!(std::sync::atomic::AtomicBool);
1169malloc_size_of_is_0!(std::sync::atomic::AtomicIsize);
1170malloc_size_of_is_0!(std::sync::atomic::AtomicUsize);
1171malloc_size_of_is_0!(std::sync::atomic::AtomicU32);
1172malloc_size_of_is_0!(std::time::Duration);
1173malloc_size_of_is_0!(std::time::Instant);
1174malloc_size_of_is_0!(std::time::SystemTime);
1175malloc_size_of_is_0!(style::data::ElementDataWrapper);
1176malloc_size_of_is_0!(style::font_face::SourceList);
1177malloc_size_of_is_0!(style::properties::ComputedValues);
1178malloc_size_of_is_0!(style::properties::declaration_block::PropertyDeclarationBlock);
1179malloc_size_of_is_0!(style::queries::values::PrefersColorScheme);
1180malloc_size_of_is_0!(style::stylesheets::Stylesheet);
1181malloc_size_of_is_0!(style::stylesheets::FontFaceRule);
1182malloc_size_of_is_0!(style::values::specified::source_size_list::SourceSizeList);
1183malloc_size_of_is_0!(taffy::Layout);
1184malloc_size_of_is_0!(time::Duration);
1185malloc_size_of_is_0!(unicode_bidi::Level);
1186malloc_size_of_is_0!(unicode_script::Script);
1187malloc_size_of_is_0!(std::net::TcpStream);
1188
1189impl MallocSizeOf for urlpattern::UrlPattern {
1190    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
1191        // This is an approximation
1192        self.protocol().len() +
1193            self.username().len() +
1194            self.password().len() +
1195            self.hostname().len() +
1196            self.port().len() +
1197            self.pathname().len() +
1198            self.search().len() +
1199            self.hash().len()
1200    }
1201}
1202
1203impl<S: tendril::TendrilSink<tendril::fmt::UTF8, A>, A: tendril::Atomicity> MallocSizeOf
1204    for tendril::stream::LossyDecoder<S, A>
1205{
1206    fn size_of(&self, _: &mut MallocSizeOfOps) -> usize {
1207        0
1208    }
1209}
1210
1211impl<F: tendril::Format> MallocSizeOf for tendril::SendTendril<F> {
1212    fn size_of(&self, _: &mut MallocSizeOfOps) -> usize {
1213        0
1214    }
1215}
1216
1217macro_rules! malloc_size_of_is_webrender_malloc_size_of(
1218    ($($ty:ty),+) => (
1219        $(
1220            impl MallocSizeOf for $ty {
1221                fn size_of(&self, _: &mut MallocSizeOfOps) -> usize {
1222                    let mut ops = wr_malloc_size_of::MallocSizeOfOps::new(servo_allocator::usable_size, None);
1223                    <$ty as wr_malloc_size_of::MallocSizeOf>::size_of(self, &mut ops)
1224                }
1225            }
1226        )+
1227    );
1228);
1229
1230malloc_size_of_is_webrender_malloc_size_of!(webrender::FastTransform<webrender_api::units::LayoutPixel, webrender_api::units::LayoutPixel>);
1231malloc_size_of_is_webrender_malloc_size_of!(webrender_api::BorderRadius);
1232malloc_size_of_is_webrender_malloc_size_of!(webrender_api::BorderStyle);
1233malloc_size_of_is_webrender_malloc_size_of!(webrender_api::BoxShadowClipMode);
1234malloc_size_of_is_webrender_malloc_size_of!(webrender_api::ColorF);
1235malloc_size_of_is_webrender_malloc_size_of!(webrender_api::Epoch);
1236malloc_size_of_is_webrender_malloc_size_of!(webrender_api::ExtendMode);
1237malloc_size_of_is_webrender_malloc_size_of!(webrender_api::ExternalScrollId);
1238malloc_size_of_is_webrender_malloc_size_of!(webrender_api::FontInstanceFlags);
1239malloc_size_of_is_webrender_malloc_size_of!(webrender_api::FontInstanceKey);
1240malloc_size_of_is_webrender_malloc_size_of!(webrender_api::FontKey);
1241malloc_size_of_is_webrender_malloc_size_of!(webrender_api::FontVariation);
1242malloc_size_of_is_webrender_malloc_size_of!(webrender_api::GlyphInstance);
1243malloc_size_of_is_webrender_malloc_size_of!(webrender_api::GradientStop);
1244malloc_size_of_is_webrender_malloc_size_of!(webrender_api::ImageKey);
1245malloc_size_of_is_webrender_malloc_size_of!(webrender_api::ImageRendering);
1246malloc_size_of_is_webrender_malloc_size_of!(webrender_api::LineStyle);
1247malloc_size_of_is_webrender_malloc_size_of!(webrender_api::MixBlendMode);
1248malloc_size_of_is_webrender_malloc_size_of!(webrender_api::NormalBorder);
1249malloc_size_of_is_webrender_malloc_size_of!(webrender_api::PipelineId);
1250malloc_size_of_is_webrender_malloc_size_of!(
1251    webrender_api::PropertyBindingKey<webrender_api::ColorF>
1252);
1253malloc_size_of_is_webrender_malloc_size_of!(webrender_api::ReferenceFrameKind);
1254malloc_size_of_is_webrender_malloc_size_of!(webrender_api::RepeatMode);
1255malloc_size_of_is_webrender_malloc_size_of!(webrender_api::SpatialId);
1256malloc_size_of_is_webrender_malloc_size_of!(webrender_api::StickyOffsetBounds);
1257malloc_size_of_is_webrender_malloc_size_of!(webrender_api::TransformStyle);
1258
1259macro_rules! malloc_size_of_is_stylo_malloc_size_of(
1260    ($($ty:ty),+) => (
1261        $(
1262            impl MallocSizeOf for $ty {
1263                fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1264                    <$ty as stylo_malloc_size_of::MallocSizeOf>::size_of(self, ops)
1265                }
1266            }
1267        )+
1268    );
1269);
1270
1271impl<S> MallocSizeOf for style::author_styles::GenericAuthorStyles<S>
1272where
1273    S: style::stylesheets::StylesheetInDocument
1274        + std::cmp::PartialEq
1275        + stylo_malloc_size_of::MallocSizeOf,
1276{
1277    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1278        <style::author_styles::GenericAuthorStyles<S> as stylo_malloc_size_of::MallocSizeOf>::size_of(self, ops)
1279    }
1280}
1281
1282impl<S> MallocSizeOf for style::stylesheet_set::DocumentStylesheetSet<S>
1283where
1284    S: style::stylesheets::StylesheetInDocument
1285        + std::cmp::PartialEq
1286        + stylo_malloc_size_of::MallocSizeOf,
1287{
1288    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1289        <style::stylesheet_set::DocumentStylesheetSet<S> as stylo_malloc_size_of::MallocSizeOf>::size_of(self, ops)
1290    }
1291}
1292
1293impl<T> MallocSizeOf for style::shared_lock::Locked<T> {
1294    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
1295        // TODO: fix this implementation when Locked derives MallocSizeOf.
1296        0
1297        // <style::shared_lock::Locked<T> as stylo_malloc_size_of::MallocSizeOf>::size_of(self, ops)
1298    }
1299}
1300
1301impl<T: MallocSizeOf> MallocSizeOf for atomic_refcell::AtomicRefCell<T> {
1302    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1303        self.borrow().size_of(ops)
1304    }
1305}
1306
1307malloc_size_of_is_stylo_malloc_size_of!(style::animation::DocumentAnimationSet);
1308malloc_size_of_is_stylo_malloc_size_of!(style::attr::AttrIdentifier);
1309malloc_size_of_is_stylo_malloc_size_of!(style::attr::AttrValue);
1310malloc_size_of_is_stylo_malloc_size_of!(style::color::AbsoluteColor);
1311malloc_size_of_is_stylo_malloc_size_of!(style::computed_values::font_variant_caps::T);
1312malloc_size_of_is_stylo_malloc_size_of!(style::computed_values::text_decoration_style::T);
1313malloc_size_of_is_stylo_malloc_size_of!(style::computed_values::text_rendering::T);
1314malloc_size_of_is_stylo_malloc_size_of!(style::dom::OpaqueNode);
1315malloc_size_of_is_stylo_malloc_size_of!(style::invalidation::element::restyle_hints::RestyleHint);
1316malloc_size_of_is_stylo_malloc_size_of!(style::logical_geometry::WritingMode);
1317malloc_size_of_is_stylo_malloc_size_of!(style::media_queries::MediaList);
1318malloc_size_of_is_stylo_malloc_size_of!(
1319    style::properties::longhands::align_items::computed_value::T
1320);
1321malloc_size_of_is_stylo_malloc_size_of!(
1322    style::properties::longhands::flex_direction::computed_value::T
1323);
1324malloc_size_of_is_stylo_malloc_size_of!(style::properties::longhands::flex_wrap::computed_value::T);
1325malloc_size_of_is_stylo_malloc_size_of!(style::properties::style_structs::Font);
1326malloc_size_of_is_stylo_malloc_size_of!(style::selector_parser::PseudoElement);
1327malloc_size_of_is_stylo_malloc_size_of!(style::selector_parser::RestyleDamage);
1328malloc_size_of_is_stylo_malloc_size_of!(style::selector_parser::Snapshot);
1329malloc_size_of_is_stylo_malloc_size_of!(style::shared_lock::SharedRwLock);
1330malloc_size_of_is_stylo_malloc_size_of!(style::stylesheets::DocumentStyleSheet);
1331malloc_size_of_is_stylo_malloc_size_of!(style::stylist::Stylist);
1332malloc_size_of_is_stylo_malloc_size_of!(style::values::computed::BorderStyle);
1333malloc_size_of_is_stylo_malloc_size_of!(style::values::computed::ContentDistribution);
1334malloc_size_of_is_stylo_malloc_size_of!(style::values::computed::FontStretch);
1335malloc_size_of_is_stylo_malloc_size_of!(style::values::computed::FontStyle);
1336malloc_size_of_is_stylo_malloc_size_of!(style::values::computed::FontWeight);
1337malloc_size_of_is_stylo_malloc_size_of!(style::values::computed::font::SingleFontFamily);
1338malloc_size_of_is_stylo_malloc_size_of!(style::values::specified::align::AlignFlags);
1339malloc_size_of_is_stylo_malloc_size_of!(style::values::specified::box_::Overflow);
1340malloc_size_of_is_stylo_malloc_size_of!(style::values::specified::font::FontSynthesis);
1341malloc_size_of_is_stylo_malloc_size_of!(style::values::specified::font::XLang);
1342malloc_size_of_is_stylo_malloc_size_of!(style::values::specified::TextDecorationLine);
1343malloc_size_of_is_stylo_malloc_size_of!(stylo_dom::ElementState);
1344malloc_size_of_is_stylo_malloc_size_of!(style::computed_values::font_optical_sizing::T);
1345
1346impl<T> MallocSizeOf for GenericLengthPercentageOrAuto<T>
1347where
1348    T: stylo_malloc_size_of::MallocSizeOf,
1349{
1350    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1351        <GenericLengthPercentageOrAuto<T> as stylo_malloc_size_of::MallocSizeOf>::size_of(self, ops)
1352    }
1353}
1354
1355impl MallocSizeOf for resvg::usvg::fontdb::Source {
1356    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1357        match self {
1358            Source::Binary(_) => 0,
1359            Source::File(path) => path.size_of(ops),
1360            Source::SharedFile(path, _) => path.size_of(ops),
1361        }
1362    }
1363}
1364
1365impl MallocSizeOf for resvg::usvg::fontdb::FaceInfo {
1366    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1367        self.id.size_of(ops) +
1368            self.source.size_of(ops) +
1369            self.families.size_of(ops) +
1370            self.post_script_name.size_of(ops) +
1371            self.style.size_of(ops) +
1372            self.weight.size_of(ops) +
1373            self.stretch.size_of(ops)
1374    }
1375}
1376
1377impl MallocSizeOf for resvg::usvg::fontdb::Database {
1378    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1379        self.faces().map(|face| face.size_of(ops)).sum()
1380    }
1381}