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