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