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