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