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
699impl<T: MallocSizeOf> MallocSizeOf for std::sync::Weak<T> {
700    fn size_of(&self, _: &mut MallocSizeOfOps) -> usize {
701        // A weak reference to the data necessarily has another strong reference
702        // somewhere else where it can be measured or...it's been released and is zero.
703        0
704    }
705}
706
707/// If a mutex is stored directly as a member of a data type that is being measured,
708/// it is the unique owner of its contents and deserves to be measured.
709///
710/// If a mutex is stored inside of an Arc value as a member of a data type that is being measured,
711/// the Arc will not be automatically measured so there is no risk of overcounting the mutex's
712/// contents.
713impl<T: MallocSizeOf> MallocSizeOf for std::sync::Mutex<T> {
714    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
715        (*self.lock().unwrap()).size_of(ops)
716    }
717}
718
719impl<T: MallocSizeOf> MallocSizeOf for parking_lot::Mutex<T> {
720    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
721        (*self.lock()).size_of(ops)
722    }
723}
724
725impl<T: MallocSizeOf> MallocSizeOf for parking_lot::RwLock<T> {
726    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
727        (*self.read()).size_of(ops)
728    }
729}
730
731impl<T: MallocConditionalSizeOf> MallocConditionalSizeOf for parking_lot::RwLock<T> {
732    fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
733        (*self.read()).conditional_size_of(ops)
734    }
735}
736
737impl<T: MallocSizeOf, Unit> MallocSizeOf for euclid::Length<T, Unit> {
738    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
739        self.0.size_of(ops)
740    }
741}
742
743impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::Scale<T, Src, Dst> {
744    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
745        self.0.size_of(ops)
746    }
747}
748
749impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Point2D<T, U> {
750    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
751        self.x.size_of(ops) + self.y.size_of(ops)
752    }
753}
754
755impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Box2D<T, U> {
756    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
757        self.min.size_of(ops) + self.max.size_of(ops)
758    }
759}
760
761impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Rect<T, U> {
762    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
763        self.origin.size_of(ops) + self.size.size_of(ops)
764    }
765}
766
767impl<T: MallocSizeOf, U> MallocSizeOf for euclid::SideOffsets2D<T, U> {
768    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
769        self.top.size_of(ops) +
770            self.right.size_of(ops) +
771            self.bottom.size_of(ops) +
772            self.left.size_of(ops)
773    }
774}
775
776impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Size2D<T, U> {
777    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
778        self.width.size_of(ops) + self.height.size_of(ops)
779    }
780}
781
782impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::Transform2D<T, Src, Dst> {
783    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
784        self.m11.size_of(ops) +
785            self.m12.size_of(ops) +
786            self.m21.size_of(ops) +
787            self.m22.size_of(ops) +
788            self.m31.size_of(ops) +
789            self.m32.size_of(ops)
790    }
791}
792
793impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::Transform3D<T, Src, Dst> {
794    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
795        self.m11.size_of(ops) +
796            self.m12.size_of(ops) +
797            self.m13.size_of(ops) +
798            self.m14.size_of(ops) +
799            self.m21.size_of(ops) +
800            self.m22.size_of(ops) +
801            self.m23.size_of(ops) +
802            self.m24.size_of(ops) +
803            self.m31.size_of(ops) +
804            self.m32.size_of(ops) +
805            self.m33.size_of(ops) +
806            self.m34.size_of(ops) +
807            self.m41.size_of(ops) +
808            self.m42.size_of(ops) +
809            self.m43.size_of(ops) +
810            self.m44.size_of(ops)
811    }
812}
813
814impl MallocSizeOf for url::Host {
815    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
816        match *self {
817            url::Host::Domain(ref s) => s.size_of(ops),
818            _ => 0,
819        }
820    }
821}
822
823impl MallocSizeOf for url::Url {
824    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
825        // TODO: This is an estimate, but a real size should be calculated in `rust-url` once
826        // it has support for `malloc_size_of`.
827        self.to_string().size_of(ops)
828    }
829}
830
831impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Vector2D<T, U> {
832    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
833        self.x.size_of(ops) + self.y.size_of(ops)
834    }
835}
836
837impl<Static: string_cache::StaticAtomSet> MallocSizeOf for string_cache::Atom<Static> {
838    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
839        0
840    }
841}
842
843impl MallocSizeOf for usvg::Tree {
844    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
845        let root = self.root();
846        let linear_gradients = self.linear_gradients();
847        let radial_gradients = self.radial_gradients();
848        let patterns = self.patterns();
849        let clip_paths = self.clip_paths();
850        let masks = self.masks();
851        let filters = self.filters();
852        let fontdb = self.fontdb();
853
854        let mut sum = root.size_of(ops) +
855            linear_gradients.size_of(ops) +
856            radial_gradients.size_of(ops) +
857            patterns.size_of(ops) +
858            clip_paths.size_of(ops) +
859            masks.size_of(ops) +
860            filters.size_of(ops);
861
862        sum += fontdb.conditional_size_of(ops);
863
864        if ops.has_malloc_enclosing_size_of() {
865            unsafe {
866                sum += ops.malloc_enclosing_size_of(root);
867                if !linear_gradients.is_empty() {
868                    sum += ops.malloc_enclosing_size_of(linear_gradients.as_ptr());
869                }
870                if !radial_gradients.is_empty() {
871                    sum += ops.malloc_enclosing_size_of(radial_gradients.as_ptr());
872                }
873                if !patterns.is_empty() {
874                    sum += ops.malloc_enclosing_size_of(patterns.as_ptr());
875                }
876                if !clip_paths.is_empty() {
877                    sum += ops.malloc_enclosing_size_of(clip_paths.as_ptr());
878                }
879                if !masks.is_empty() {
880                    sum += ops.malloc_enclosing_size_of(masks.as_ptr());
881                }
882                if !filters.is_empty() {
883                    sum += ops.malloc_enclosing_size_of(filters.as_ptr());
884                }
885            }
886        }
887        sum
888    }
889}
890
891impl MallocSizeOf for usvg::Group {
892    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
893        let id = self.id();
894        let children = self.children();
895        let filters = self.filters();
896        let clip_path = self.clip_path();
897
898        let mut sum =
899            id.size_of(ops) + children.size_of(ops) + filters.size_of(ops) + clip_path.size_of(ops);
900
901        if ops.has_malloc_enclosing_size_of() {
902            unsafe {
903                if !id.is_empty() {
904                    sum += ops.malloc_enclosing_size_of(id.as_ptr());
905                }
906                if let Some(c) = clip_path {
907                    sum += ops.malloc_enclosing_size_of(c)
908                }
909                if !children.is_empty() {
910                    sum += ops.malloc_enclosing_size_of(children.as_ptr());
911                }
912                if !filters.is_empty() {
913                    sum += ops.malloc_enclosing_size_of(filters.as_ptr());
914                }
915            }
916        }
917        sum
918    }
919}
920
921impl MallocSizeOf for usvg::Node {
922    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
923        let id = self.id();
924
925        let mut sum = id.size_of(ops);
926        if ops.has_malloc_enclosing_size_of() {
927            unsafe {
928                if !id.is_empty() {
929                    sum += ops.malloc_enclosing_size_of(id.as_ptr())
930                }
931            }
932        }
933        match self {
934            usvg::Node::Group(group) => {
935                sum += group.size_of(ops);
936                if ops.has_malloc_enclosing_size_of() {
937                    unsafe { sum += ops.malloc_enclosing_size_of(group) }
938                }
939            },
940            usvg::Node::Path(path) => {
941                sum += path.size_of(ops);
942                if ops.has_malloc_enclosing_size_of() {
943                    unsafe { sum += ops.malloc_enclosing_size_of(path) }
944                }
945            },
946            usvg::Node::Image(image) => {
947                sum += image.size_of(ops);
948            },
949            usvg::Node::Text(text) => {
950                sum += text.size_of(ops);
951            },
952        };
953        sum
954    }
955}
956
957impl MallocSizeOf for usvg::Path {
958    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
959        let id = self.id();
960        let data = self.data();
961        let fill = self.fill();
962        let stroke = self.stroke();
963
964        let mut sum = id.size_of(ops) + data.size_of(ops) + fill.size_of(ops) + stroke.size_of(ops);
965        if ops.has_malloc_enclosing_size_of() {
966            unsafe {
967                if !id.is_empty() {
968                    sum += ops.malloc_enclosing_size_of(id.as_ptr());
969                }
970                sum += ops.malloc_enclosing_size_of(data);
971                if let Some(f) = fill {
972                    sum += ops.malloc_enclosing_size_of(f)
973                }
974                if let Some(s) = stroke {
975                    sum += ops.malloc_enclosing_size_of(s)
976                }
977            }
978        }
979        sum
980    }
981}
982impl MallocSizeOf for tiny_skia_path::Path {
983    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
984        let verbs = self.verbs();
985        let points = self.points();
986
987        let mut sum = verbs.size_of(ops) + points.size_of(ops);
988        if ops.has_malloc_enclosing_size_of() {
989            unsafe {
990                if !points.is_empty() {
991                    sum += ops.malloc_enclosing_size_of(points.as_ptr());
992                }
993                if !verbs.is_empty() {
994                    sum += ops.malloc_enclosing_size_of(verbs.as_ptr());
995                }
996            }
997        }
998
999        sum
1000    }
1001}
1002
1003impl MallocSizeOf for usvg::ClipPath {
1004    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1005        let id = self.id();
1006        let clip_path = self.clip_path();
1007        let root = self.root();
1008
1009        let mut sum = id.size_of(ops) + clip_path.size_of(ops) + root.size_of(ops);
1010        if ops.has_malloc_enclosing_size_of() {
1011            unsafe {
1012                sum += ops.malloc_enclosing_size_of(root);
1013                if !id.is_empty() {
1014                    sum += ops.malloc_enclosing_size_of(id.as_ptr());
1015                }
1016                if let Some(c) = clip_path {
1017                    sum += c.size_of(ops)
1018                }
1019            }
1020        }
1021        sum
1022    }
1023}
1024
1025// Placeholder for unique case where internals of Sender cannot be measured.
1026// malloc size of is 0 macro complains about type supplied!
1027impl<T> MallocSizeOf for crossbeam_channel::Sender<T> {
1028    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
1029        0
1030    }
1031}
1032
1033impl<T> MallocSizeOf for crossbeam_channel::Receiver<T> {
1034    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
1035        0
1036    }
1037}
1038
1039impl<T> MallocSizeOf for tokio::sync::mpsc::UnboundedSender<T> {
1040    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
1041        0
1042    }
1043}
1044
1045impl<T> MallocSizeOf for ipc_channel::ipc::IpcSender<T> {
1046    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
1047        0
1048    }
1049}
1050
1051impl<T> MallocSizeOf for ipc_channel::ipc::IpcReceiver<T> {
1052    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
1053        0
1054    }
1055}
1056
1057impl MallocSizeOf for ipc_channel::ipc::IpcSharedMemory {
1058    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
1059        self.len()
1060    }
1061}
1062
1063impl<T: MallocSizeOf> MallocSizeOf for accountable_refcell::RefCell<T> {
1064    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1065        self.borrow().size_of(ops)
1066    }
1067}
1068
1069impl MallocSizeOf for servo_arc::Arc<ComputedValues> {
1070    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1071        self.conditional_size_of(ops)
1072    }
1073}
1074
1075malloc_size_of_hash_map!(indexmap::IndexMap<K, V, S>);
1076malloc_size_of_hash_set!(indexmap::IndexSet<T, S>);
1077
1078malloc_size_of_is_0!(bool, char, str);
1079malloc_size_of_is_0!(f32, f64);
1080malloc_size_of_is_0!(i8, i16, i32, i64, i128, isize);
1081malloc_size_of_is_0!(u8, u16, u32, u64, u128, usize);
1082
1083malloc_size_of_is_0!(Uuid);
1084malloc_size_of_is_0!(app_units::Au);
1085malloc_size_of_is_0!(content_security_policy::Destination);
1086malloc_size_of_is_0!(content_security_policy::sandboxing_directive::SandboxingFlagSet);
1087malloc_size_of_is_0!(http::StatusCode);
1088malloc_size_of_is_0!(keyboard_types::Modifiers);
1089malloc_size_of_is_0!(mime::Mime);
1090malloc_size_of_is_0!(resvg::usvg::fontdb::ID);
1091malloc_size_of_is_0!(resvg::usvg::fontdb::Style);
1092malloc_size_of_is_0!(resvg::usvg::fontdb::Weight);
1093malloc_size_of_is_0!(resvg::usvg::fontdb::Stretch);
1094malloc_size_of_is_0!(resvg::usvg::fontdb::Language);
1095malloc_size_of_is_0!(std::num::NonZeroU16);
1096malloc_size_of_is_0!(std::num::NonZeroU64);
1097malloc_size_of_is_0!(std::num::NonZeroUsize);
1098malloc_size_of_is_0!(std::sync::atomic::AtomicBool);
1099malloc_size_of_is_0!(std::sync::atomic::AtomicIsize);
1100malloc_size_of_is_0!(std::sync::atomic::AtomicUsize);
1101malloc_size_of_is_0!(std::time::Duration);
1102malloc_size_of_is_0!(std::time::Instant);
1103malloc_size_of_is_0!(std::time::SystemTime);
1104malloc_size_of_is_0!(style::data::ElementData);
1105malloc_size_of_is_0!(style::font_face::SourceList);
1106malloc_size_of_is_0!(style::properties::ComputedValues);
1107malloc_size_of_is_0!(style::properties::declaration_block::PropertyDeclarationBlock);
1108malloc_size_of_is_0!(style::queries::values::PrefersColorScheme);
1109malloc_size_of_is_0!(style::stylesheets::Stylesheet);
1110malloc_size_of_is_0!(style::stylesheets::FontFaceRule);
1111malloc_size_of_is_0!(style::values::specified::source_size_list::SourceSizeList);
1112malloc_size_of_is_0!(taffy::Layout);
1113malloc_size_of_is_0!(unicode_bidi::Level);
1114malloc_size_of_is_0!(unicode_script::Script);
1115malloc_size_of_is_0!(urlpattern::UrlPattern);
1116malloc_size_of_is_0!(utf8::Incomplete);
1117
1118impl<S: tendril::TendrilSink<tendril::fmt::UTF8, A>, A: tendril::Atomicity> MallocSizeOf
1119    for tendril::stream::LossyDecoder<S, A>
1120{
1121    fn size_of(&self, _: &mut MallocSizeOfOps) -> usize {
1122        0
1123    }
1124}
1125
1126impl<F: tendril::Format> MallocSizeOf for tendril::SendTendril<F> {
1127    fn size_of(&self, _: &mut MallocSizeOfOps) -> usize {
1128        0
1129    }
1130}
1131
1132macro_rules! malloc_size_of_is_webrender_malloc_size_of(
1133    ($($ty:ty),+) => (
1134        $(
1135            impl MallocSizeOf for $ty {
1136                fn size_of(&self, _: &mut MallocSizeOfOps) -> usize {
1137                    let mut ops = wr_malloc_size_of::MallocSizeOfOps::new(servo_allocator::usable_size, None);
1138                    <$ty as wr_malloc_size_of::MallocSizeOf>::size_of(self, &mut ops)
1139                }
1140            }
1141        )+
1142    );
1143);
1144
1145malloc_size_of_is_webrender_malloc_size_of!(webrender_api::BorderRadius);
1146malloc_size_of_is_webrender_malloc_size_of!(webrender_api::BorderStyle);
1147malloc_size_of_is_webrender_malloc_size_of!(webrender_api::BoxShadowClipMode);
1148malloc_size_of_is_webrender_malloc_size_of!(webrender_api::ColorF);
1149malloc_size_of_is_webrender_malloc_size_of!(webrender_api::Epoch);
1150malloc_size_of_is_webrender_malloc_size_of!(webrender_api::ExtendMode);
1151malloc_size_of_is_webrender_malloc_size_of!(webrender_api::ExternalScrollId);
1152malloc_size_of_is_webrender_malloc_size_of!(webrender_api::FontKey);
1153malloc_size_of_is_webrender_malloc_size_of!(webrender_api::FontInstanceFlags);
1154malloc_size_of_is_webrender_malloc_size_of!(webrender_api::FontInstanceKey);
1155malloc_size_of_is_webrender_malloc_size_of!(webrender_api::GlyphInstance);
1156malloc_size_of_is_webrender_malloc_size_of!(webrender_api::GradientStop);
1157malloc_size_of_is_webrender_malloc_size_of!(webrender_api::ImageKey);
1158malloc_size_of_is_webrender_malloc_size_of!(webrender_api::ImageRendering);
1159malloc_size_of_is_webrender_malloc_size_of!(webrender_api::LineStyle);
1160malloc_size_of_is_webrender_malloc_size_of!(webrender_api::MixBlendMode);
1161malloc_size_of_is_webrender_malloc_size_of!(webrender_api::NormalBorder);
1162malloc_size_of_is_webrender_malloc_size_of!(webrender_api::PipelineId);
1163malloc_size_of_is_webrender_malloc_size_of!(webrender_api::ReferenceFrameKind);
1164malloc_size_of_is_webrender_malloc_size_of!(webrender_api::RepeatMode);
1165malloc_size_of_is_webrender_malloc_size_of!(webrender_api::FontVariation);
1166malloc_size_of_is_webrender_malloc_size_of!(webrender_api::SpatialId);
1167malloc_size_of_is_webrender_malloc_size_of!(webrender_api::StickyOffsetBounds);
1168malloc_size_of_is_webrender_malloc_size_of!(webrender_api::TransformStyle);
1169malloc_size_of_is_webrender_malloc_size_of!(webrender::FastTransform<webrender_api::units::LayoutPixel,webrender_api::units::LayoutPixel>);
1170
1171macro_rules! malloc_size_of_is_stylo_malloc_size_of(
1172    ($($ty:ty),+) => (
1173        $(
1174            impl MallocSizeOf for $ty {
1175                fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1176                    <$ty as stylo_malloc_size_of::MallocSizeOf>::size_of(self, ops)
1177                }
1178            }
1179        )+
1180    );
1181);
1182
1183impl<S> MallocSizeOf for style::author_styles::GenericAuthorStyles<S>
1184where
1185    S: style::stylesheets::StylesheetInDocument
1186        + std::cmp::PartialEq
1187        + stylo_malloc_size_of::MallocSizeOf,
1188{
1189    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1190        <style::author_styles::GenericAuthorStyles<S> as stylo_malloc_size_of::MallocSizeOf>::size_of(self, ops)
1191    }
1192}
1193
1194impl<S> MallocSizeOf for style::stylesheet_set::DocumentStylesheetSet<S>
1195where
1196    S: style::stylesheets::StylesheetInDocument
1197        + std::cmp::PartialEq
1198        + stylo_malloc_size_of::MallocSizeOf,
1199{
1200    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1201        <style::stylesheet_set::DocumentStylesheetSet<S> as stylo_malloc_size_of::MallocSizeOf>::size_of(self, ops)
1202    }
1203}
1204
1205impl<T> MallocSizeOf for style::shared_lock::Locked<T> {
1206    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
1207        // TODO: fix this implementation when Locked derives MallocSizeOf.
1208        0
1209        // <style::shared_lock::Locked<T> as stylo_malloc_size_of::MallocSizeOf>::size_of(self, ops)
1210    }
1211}
1212
1213impl<T: MallocSizeOf> MallocSizeOf for atomic_refcell::AtomicRefCell<T> {
1214    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1215        self.borrow().size_of(ops)
1216    }
1217}
1218
1219malloc_size_of_is_stylo_malloc_size_of!(style::animation::DocumentAnimationSet);
1220malloc_size_of_is_stylo_malloc_size_of!(style::attr::AttrIdentifier);
1221malloc_size_of_is_stylo_malloc_size_of!(style::attr::AttrValue);
1222malloc_size_of_is_stylo_malloc_size_of!(style::color::AbsoluteColor);
1223malloc_size_of_is_stylo_malloc_size_of!(style::computed_values::font_variant_caps::T);
1224malloc_size_of_is_stylo_malloc_size_of!(style::computed_values::text_decoration_style::T);
1225malloc_size_of_is_stylo_malloc_size_of!(style::dom::OpaqueNode);
1226malloc_size_of_is_stylo_malloc_size_of!(style::invalidation::element::restyle_hints::RestyleHint);
1227malloc_size_of_is_stylo_malloc_size_of!(style::logical_geometry::WritingMode);
1228malloc_size_of_is_stylo_malloc_size_of!(style::media_queries::MediaList);
1229malloc_size_of_is_stylo_malloc_size_of!(
1230    style::properties::longhands::align_items::computed_value::T
1231);
1232malloc_size_of_is_stylo_malloc_size_of!(
1233    style::properties::longhands::flex_direction::computed_value::T
1234);
1235malloc_size_of_is_stylo_malloc_size_of!(style::properties::longhands::flex_wrap::computed_value::T);
1236malloc_size_of_is_stylo_malloc_size_of!(style::properties::style_structs::Font);
1237malloc_size_of_is_stylo_malloc_size_of!(style::selector_parser::PseudoElement);
1238malloc_size_of_is_stylo_malloc_size_of!(style::selector_parser::RestyleDamage);
1239malloc_size_of_is_stylo_malloc_size_of!(style::selector_parser::Snapshot);
1240malloc_size_of_is_stylo_malloc_size_of!(style::shared_lock::SharedRwLock);
1241malloc_size_of_is_stylo_malloc_size_of!(style::stylesheets::DocumentStyleSheet);
1242malloc_size_of_is_stylo_malloc_size_of!(style::stylist::Stylist);
1243malloc_size_of_is_stylo_malloc_size_of!(style::values::computed::BorderStyle);
1244malloc_size_of_is_stylo_malloc_size_of!(style::values::computed::ContentDistribution);
1245malloc_size_of_is_stylo_malloc_size_of!(style::values::computed::FontStretch);
1246malloc_size_of_is_stylo_malloc_size_of!(style::values::computed::FontStyle);
1247malloc_size_of_is_stylo_malloc_size_of!(style::values::computed::FontWeight);
1248malloc_size_of_is_stylo_malloc_size_of!(style::values::computed::font::SingleFontFamily);
1249malloc_size_of_is_stylo_malloc_size_of!(style::values::specified::align::AlignFlags);
1250malloc_size_of_is_stylo_malloc_size_of!(style::values::specified::box_::Overflow);
1251malloc_size_of_is_stylo_malloc_size_of!(style::values::specified::font::FontSynthesis);
1252malloc_size_of_is_stylo_malloc_size_of!(style::values::specified::TextDecorationLine);
1253malloc_size_of_is_stylo_malloc_size_of!(stylo_dom::ElementState);
1254malloc_size_of_is_stylo_malloc_size_of!(style::computed_values::font_optical_sizing::T);
1255
1256impl<T> MallocSizeOf for GenericLengthPercentageOrAuto<T>
1257where
1258    T: stylo_malloc_size_of::MallocSizeOf,
1259{
1260    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1261        <GenericLengthPercentageOrAuto<T> as stylo_malloc_size_of::MallocSizeOf>::size_of(self, ops)
1262    }
1263}
1264
1265impl MallocSizeOf for resvg::usvg::fontdb::Source {
1266    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1267        match self {
1268            Source::Binary(_) => 0,
1269            Source::File(path) => path.size_of(ops),
1270            Source::SharedFile(path, _) => path.size_of(ops),
1271        }
1272    }
1273}
1274
1275impl MallocSizeOf for resvg::usvg::fontdb::FaceInfo {
1276    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1277        self.id.size_of(ops) +
1278            self.source.size_of(ops) +
1279            self.families.size_of(ops) +
1280            self.post_script_name.size_of(ops) +
1281            self.style.size_of(ops) +
1282            self.weight.size_of(ops) +
1283            self.stretch.size_of(ops)
1284    }
1285}
1286
1287impl MallocSizeOf for resvg::usvg::fontdb::Database {
1288    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
1289        self.faces().map(|face| face.size_of(ops)).sum()
1290    }
1291}