Skip to main content

servo_malloc_size_of/
lib.rs

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