servo_malloc_size_of/
lib.rs

1// Copyright 2016-2017 The Servo Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11//! A crate for measuring the heap usage of data structures in a way that
12//! integrates with Firefox's memory reporting, particularly the use of
13//! mozjemalloc and DMD. In particular, it has the following features.
14//! - It isn't bound to a particular heap allocator.
15//! - It provides traits for both "shallow" and "deep" measurement, which gives
16//!   flexibility in the cases where the traits can't be used.
17//! - It allows for measuring blocks even when only an interior pointer can be
18//!   obtained for heap allocations, e.g. `HashSet` and `HashMap`. (This relies
19//!   on the heap allocator having suitable support, which mozjemalloc has.)
20//! - It allows handling of types like `Rc` and `Arc` by providing traits that
21//!   are different to the ones for non-graph structures.
22//!
23//! Suggested uses are as follows.
24//! - When possible, use the `MallocSizeOf` trait. (Deriving support is
25//!   provided by the `malloc_size_of_derive` crate.)
26//! - If you need an additional synchronization argument, provide a function
27//!   that is like the standard trait method, but with the extra argument.
28//! - If you need multiple measurements for a type, provide a function named
29//!   `add_size_of` that takes a mutable reference to a struct that contains
30//!   the multiple measurement fields.
31//! - When deep measurement (via `MallocSizeOf`) cannot be implemented for a
32//!   type, shallow measurement (via `MallocShallowSizeOf`) in combination with
33//!   iteration can be a useful substitute.
34//! - `Rc` and `Arc` are always tricky, which is why `MallocSizeOf` is not (and
35//!   should not be) implemented for them.
36//! - If an `Rc` or `Arc` is known to be a "primary" reference and can always
37//!   be measured, it should be measured via the `MallocUnconditionalSizeOf`
38//!   trait.
39//! - If an `Rc` or `Arc` should be measured only if it hasn't been seen
40//!   before, it should be measured via the `MallocConditionalSizeOf` trait.
41//! - Using universal function call syntax is a good idea when measuring boxed
42//!   fields in structs, because it makes it clear that the Box is being
43//!   measured as well as the thing it points to. E.g.
44//!   `<Box<_> as MallocSizeOf>::size_of(field, ops)`.
45//!
46//!   Note: WebRender has a reduced fork of this crate, so that we can avoid
47//!   publishing this crate on crates.io.
48
49use std::cell::OnceCell;
50use std::collections::BinaryHeap;
51use std::hash::{BuildHasher, Hash};
52use std::ops::Range;
53use std::rc::Rc;
54use std::sync::Arc;
55
56use style::properties::ComputedValues;
57use style::values::generics::length::GenericLengthPercentageOrAuto;
58pub use stylo_malloc_size_of::MallocSizeOfOps;
59use uuid::Uuid;
60
61/// Trait for measuring the "deep" heap usage of a data structure. This is the
62/// most commonly-used of the traits.
63pub trait MallocSizeOf {
64    /// Measure the heap usage of all descendant heap-allocated structures, but
65    /// not the space taken up by the value itself.
66    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize;
67}
68
69/// Trait for measuring the "shallow" heap usage of a container.
70pub trait MallocShallowSizeOf {
71    /// Measure the heap usage of immediate heap-allocated descendant
72    /// structures, but not the space taken up by the value itself. Anything
73    /// beyond the immediate descendants must be measured separately, using
74    /// iteration.
75    fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize;
76}
77
78/// Like `MallocSizeOf`, but with a different name so it cannot be used
79/// accidentally with derive(MallocSizeOf). For use with types like `Rc` and
80/// `Arc` when appropriate (e.g. when measuring a "primary" reference).
81pub trait MallocUnconditionalSizeOf {
82    /// Measure the heap usage of all heap-allocated descendant structures, but
83    /// not the space taken up by the value itself.
84    fn unconditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize;
85}
86
87/// `MallocUnconditionalSizeOf` combined with `MallocShallowSizeOf`.
88pub trait MallocUnconditionalShallowSizeOf {
89    /// `unconditional_size_of` combined with `shallow_size_of`.
90    fn unconditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize;
91}
92
93/// Like `MallocSizeOf`, but only measures if the value hasn't already been
94/// measured. For use with types like `Rc` and `Arc` when appropriate (e.g.
95/// when there is no "primary" reference).
96pub trait MallocConditionalSizeOf {
97    /// Measure the heap usage of all heap-allocated descendant structures, but
98    /// not the space taken up by the value itself, and only if that heap usage
99    /// hasn't already been measured.
100    fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize;
101}
102
103/// `MallocConditionalSizeOf` combined with `MallocShallowSizeOf`.
104pub trait MallocConditionalShallowSizeOf {
105    /// `conditional_size_of` combined with `shallow_size_of`.
106    fn conditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize;
107}
108
109impl<T: MallocSizeOf> MallocSizeOf for [T] {
110    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
111        let mut n = 0;
112        for elem in self.iter() {
113            n += elem.size_of(ops);
114        }
115        n
116    }
117}
118
119impl<T: MallocConditionalSizeOf> MallocConditionalSizeOf for [T] {
120    fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
121        self.iter()
122            .map(|element| element.conditional_size_of(ops))
123            .sum()
124    }
125}
126
127/// For use on types where size_of() returns 0.
128#[macro_export]
129macro_rules! malloc_size_of_is_0(
130    ($($ty:ty),+) => (
131        $(
132            impl $crate::MallocSizeOf for $ty {
133                #[inline(always)]
134                fn size_of(&self, _: &mut $crate::MallocSizeOfOps) -> usize {
135                    0
136                }
137            }
138        )+
139    );
140    ($($ty:ident<$($gen:ident),+>),+) => (
141        $(
142            impl<$($gen: $crate::MallocSizeOf),+> $crate::MallocSizeOf for $ty<$($gen),+> {
143                #[inline(always)]
144                fn size_of(&self, _: &mut $crate::MallocSizeOfOps) -> usize {
145                    0
146                }
147            }
148        )+
149    );
150);
151
152impl MallocSizeOf for keyboard_types::Key {
153    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
154        match &self {
155            keyboard_types::Key::Character(string) => {
156                <String as MallocSizeOf>::size_of(string, ops)
157            },
158            _ => 0,
159        }
160    }
161}
162
163impl MallocSizeOf for markup5ever::QualName {
164    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
165        self.prefix.size_of(ops) + self.ns.size_of(ops) + self.local.size_of(ops)
166    }
167}
168
169impl MallocSizeOf for String {
170    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
171        unsafe { ops.malloc_size_of(self.as_ptr()) }
172    }
173}
174
175impl<T: ?Sized> MallocSizeOf for &'_ T {
176    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
177        // Zero makes sense for a non-owning reference.
178        0
179    }
180}
181
182impl<T: ?Sized> MallocShallowSizeOf for Box<T> {
183    fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
184        unsafe { ops.malloc_size_of(&**self) }
185    }
186}
187
188impl<T: MallocSizeOf + ?Sized> MallocSizeOf for Box<T> {
189    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
190        self.shallow_size_of(ops) + (**self).size_of(ops)
191    }
192}
193
194impl MallocSizeOf for () {
195    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
196        0
197    }
198}
199
200impl<T1, T2> MallocSizeOf for (T1, T2)
201where
202    T1: MallocSizeOf,
203    T2: MallocSizeOf,
204{
205    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
206        self.0.size_of(ops) + self.1.size_of(ops)
207    }
208}
209
210impl<T1, T2, T3> MallocSizeOf for (T1, T2, T3)
211where
212    T1: MallocSizeOf,
213    T2: MallocSizeOf,
214    T3: MallocSizeOf,
215{
216    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
217        self.0.size_of(ops) + self.1.size_of(ops) + self.2.size_of(ops)
218    }
219}
220
221impl<T1, T2, T3, T4> MallocSizeOf for (T1, T2, T3, T4)
222where
223    T1: MallocSizeOf,
224    T2: MallocSizeOf,
225    T3: MallocSizeOf,
226    T4: MallocSizeOf,
227{
228    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
229        self.0.size_of(ops) + self.1.size_of(ops) + self.2.size_of(ops) + self.3.size_of(ops)
230    }
231}
232
233impl<T: MallocConditionalSizeOf> MallocConditionalSizeOf for Option<T> {
234    fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
235        if let Some(val) = self.as_ref() {
236            val.conditional_size_of(ops)
237        } else {
238            0
239        }
240    }
241}
242
243impl<T: MallocConditionalSizeOf> MallocConditionalSizeOf for Vec<T> {
244    fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
245        let mut n = self.shallow_size_of(ops);
246        for elem in self.iter() {
247            n += elem.conditional_size_of(ops);
248        }
249        n
250    }
251}
252
253impl<T: MallocSizeOf> MallocSizeOf for Option<T> {
254    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
255        if let Some(val) = self.as_ref() {
256            val.size_of(ops)
257        } else {
258            0
259        }
260    }
261}
262
263impl<T: MallocSizeOf, E: MallocSizeOf> MallocSizeOf for Result<T, E> {
264    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
265        match *self {
266            Ok(ref x) => x.size_of(ops),
267            Err(ref e) => e.size_of(ops),
268        }
269    }
270}
271
272impl<T: MallocSizeOf + Copy> MallocSizeOf for std::cell::Cell<T> {
273    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
274        self.get().size_of(ops)
275    }
276}
277
278impl<T: MallocSizeOf> MallocSizeOf for std::cell::RefCell<T> {
279    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
280        self.borrow().size_of(ops)
281    }
282}
283
284impl<B: ?Sized + ToOwned> MallocSizeOf for std::borrow::Cow<'_, B>
285where
286    B::Owned: MallocSizeOf,
287{
288    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
289        match *self {
290            std::borrow::Cow::Borrowed(_) => 0,
291            std::borrow::Cow::Owned(ref b) => b.size_of(ops),
292        }
293    }
294}
295
296impl<T> MallocShallowSizeOf for Vec<T> {
297    fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
298        unsafe { ops.malloc_size_of(self.as_ptr()) }
299    }
300}
301
302impl<T: MallocSizeOf> MallocSizeOf for Vec<T> {
303    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
304        let mut n = self.shallow_size_of(ops);
305        for elem in self.iter() {
306            n += elem.size_of(ops);
307        }
308        n
309    }
310}
311
312impl<T> MallocShallowSizeOf for std::collections::VecDeque<T> {
313    fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
314        if ops.has_malloc_enclosing_size_of() {
315            if let Some(front) = self.front() {
316                // The front element is an interior pointer.
317                unsafe { ops.malloc_enclosing_size_of(front) }
318            } else {
319                // This assumes that no memory is allocated when the VecDeque is empty.
320                0
321            }
322        } else {
323            // An estimate.
324            self.capacity() * size_of::<T>()
325        }
326    }
327}
328
329impl<T: MallocSizeOf> MallocSizeOf for std::collections::VecDeque<T> {
330    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
331        let mut n = self.shallow_size_of(ops);
332        for elem in self.iter() {
333            n += elem.size_of(ops);
334        }
335        n
336    }
337}
338
339impl<A: smallvec::Array> MallocShallowSizeOf for smallvec::SmallVec<A> {
340    fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
341        if self.spilled() {
342            unsafe { ops.malloc_size_of(self.as_ptr()) }
343        } else {
344            0
345        }
346    }
347}
348
349impl<A> MallocSizeOf for smallvec::SmallVec<A>
350where
351    A: smallvec::Array,
352    A::Item: MallocSizeOf,
353{
354    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
355        let mut n = self.shallow_size_of(ops);
356        for elem in self.iter() {
357            n += elem.size_of(ops);
358        }
359        n
360    }
361}
362
363impl<A: MallocConditionalSizeOf> MallocConditionalSizeOf for smallvec::SmallVec<A>
364where
365    A: smallvec::Array,
366    A::Item: MallocConditionalSizeOf,
367{
368    fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
369        if !self.spilled() {
370            return 0;
371        }
372
373        self.shallow_size_of(ops) +
374            self.iter()
375                .map(|element| element.conditional_size_of(ops))
376                .sum::<usize>()
377    }
378}
379
380impl<T: MallocSizeOf> MallocSizeOf for BinaryHeap<T> {
381    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
382        self.iter().map(|element| element.size_of(ops)).sum()
383    }
384}
385
386macro_rules! malloc_size_of_hash_set {
387    ($ty:ty) => {
388        impl<T, S> MallocShallowSizeOf for $ty
389        where
390            T: Eq + Hash,
391            S: BuildHasher,
392        {
393            fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
394                if ops.has_malloc_enclosing_size_of() {
395                    // The first value from the iterator gives us an interior pointer.
396                    // `ops.malloc_enclosing_size_of()` then gives us the storage size.
397                    // This assumes that the `HashSet`'s contents (values and hashes)
398                    // are all stored in a single contiguous heap allocation.
399                    self.iter()
400                        .next()
401                        .map_or(0, |t| unsafe { ops.malloc_enclosing_size_of(t) })
402                } else {
403                    // An estimate.
404                    self.capacity() * (size_of::<T>() + size_of::<usize>())
405                }
406            }
407        }
408
409        impl<T, S> MallocSizeOf for $ty
410        where
411            T: Eq + Hash + MallocSizeOf,
412            S: BuildHasher,
413        {
414            fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
415                let mut n = self.shallow_size_of(ops);
416                for t in self.iter() {
417                    n += t.size_of(ops);
418                }
419                n
420            }
421        }
422    };
423}
424
425malloc_size_of_hash_set!(std::collections::HashSet<T, S>);
426
427macro_rules! malloc_size_of_hash_map {
428    ($ty:ty) => {
429        impl<K, V, S> MallocShallowSizeOf for $ty
430        where
431            K: Eq + Hash,
432            S: BuildHasher,
433        {
434            fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
435                // See the implementation for std::collections::HashSet for details.
436                if ops.has_malloc_enclosing_size_of() {
437                    self.values()
438                        .next()
439                        .map_or(0, |v| unsafe { ops.malloc_enclosing_size_of(v) })
440                } else {
441                    self.capacity() * (size_of::<V>() + size_of::<K>() + size_of::<usize>())
442                }
443            }
444        }
445
446        impl<K, V, S> MallocSizeOf for $ty
447        where
448            K: Eq + Hash + MallocSizeOf,
449            V: MallocSizeOf,
450            S: BuildHasher,
451        {
452            fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
453                let mut n = self.shallow_size_of(ops);
454                for (k, v) in self.iter() {
455                    n += k.size_of(ops);
456                    n += v.size_of(ops);
457                }
458                n
459            }
460        }
461    };
462}
463
464malloc_size_of_hash_map!(std::collections::HashMap<K, V, S>);
465
466impl<K, V> MallocShallowSizeOf for std::collections::BTreeMap<K, V>
467where
468    K: Eq + Hash,
469{
470    fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
471        if ops.has_malloc_enclosing_size_of() {
472            self.values()
473                .next()
474                .map_or(0, |v| unsafe { ops.malloc_enclosing_size_of(v) })
475        } else {
476            self.len() * (size_of::<V>() + size_of::<K>() + size_of::<usize>())
477        }
478    }
479}
480
481impl<K, V> MallocSizeOf for std::collections::BTreeMap<K, V>
482where
483    K: Eq + Hash + MallocSizeOf,
484    V: MallocSizeOf,
485{
486    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
487        let mut n = self.shallow_size_of(ops);
488        for (k, v) in self.iter() {
489            n += k.size_of(ops);
490            n += v.size_of(ops);
491        }
492        n
493    }
494}
495
496// PhantomData is always 0.
497impl<T> MallocSizeOf for std::marker::PhantomData<T> {
498    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
499        0
500    }
501}
502
503impl<T: MallocSizeOf> MallocSizeOf for OnceCell<T> {
504    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
505        self.get()
506            .map(|interior| interior.size_of(ops))
507            .unwrap_or_default()
508    }
509}
510
511// See https://github.com/rust-lang/rust/issues/68318:
512// We don't want MallocSizeOf to be defined for Rc and Arc. If negative trait bounds are
513// ever allowed, this code should be uncommented.  Instead, there is a compile-fail test for
514// this.
515// impl<T> !MallocSizeOf for Arc<T> { }
516// impl<T> !MallocShallowSizeOf for Arc<T> { }
517
518impl<T> MallocUnconditionalShallowSizeOf for servo_arc::Arc<T> {
519    fn unconditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
520        unsafe { ops.malloc_size_of(self.heap_ptr()) }
521    }
522}
523
524impl<T: MallocSizeOf> MallocUnconditionalSizeOf for servo_arc::Arc<T> {
525    fn unconditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
526        self.unconditional_shallow_size_of(ops) + (**self).size_of(ops)
527    }
528}
529
530impl<T> MallocConditionalShallowSizeOf for servo_arc::Arc<T> {
531    fn conditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
532        if ops.have_seen_ptr(self.heap_ptr()) {
533            0
534        } else {
535            self.unconditional_shallow_size_of(ops)
536        }
537    }
538}
539
540impl<T: MallocSizeOf> MallocConditionalSizeOf for servo_arc::Arc<T> {
541    fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
542        if ops.have_seen_ptr(self.heap_ptr()) {
543            0
544        } else {
545            self.unconditional_size_of(ops)
546        }
547    }
548}
549
550impl<T> MallocUnconditionalShallowSizeOf for Arc<T> {
551    fn unconditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
552        unsafe { ops.malloc_size_of(Arc::as_ptr(self)) }
553    }
554}
555
556impl<T: MallocSizeOf> MallocUnconditionalSizeOf for Arc<T> {
557    fn unconditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
558        self.unconditional_shallow_size_of(ops) + (**self).size_of(ops)
559    }
560}
561
562impl<T> MallocConditionalShallowSizeOf for Arc<T> {
563    fn conditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
564        if ops.have_seen_ptr(Arc::as_ptr(self)) {
565            0
566        } else {
567            self.unconditional_shallow_size_of(ops)
568        }
569    }
570}
571
572impl<T: MallocSizeOf> MallocConditionalSizeOf for Arc<T> {
573    fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
574        if ops.have_seen_ptr(Arc::as_ptr(self)) {
575            0
576        } else {
577            self.unconditional_size_of(ops)
578        }
579    }
580}
581
582impl<T> MallocUnconditionalShallowSizeOf for Rc<T> {
583    fn unconditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
584        unsafe { ops.malloc_size_of(Rc::as_ptr(self)) }
585    }
586}
587
588impl<T: MallocSizeOf> MallocUnconditionalSizeOf for Rc<T> {
589    fn unconditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
590        self.unconditional_shallow_size_of(ops) + (**self).size_of(ops)
591    }
592}
593
594impl<T: MallocSizeOf> MallocConditionalSizeOf for Rc<T> {
595    fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
596        if ops.have_seen_ptr(Rc::as_ptr(self)) {
597            0
598        } else {
599            self.unconditional_size_of(ops)
600        }
601    }
602}
603
604/// If a mutex is stored directly as a member of a data type that is being measured,
605/// it is the unique owner of its contents and deserves to be measured.
606///
607/// If a mutex is stored inside of an Arc value as a member of a data type that is being measured,
608/// the Arc will not be automatically measured so there is no risk of overcounting the mutex's
609/// contents.
610impl<T: MallocSizeOf> MallocSizeOf for std::sync::Mutex<T> {
611    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
612        (*self.lock().unwrap()).size_of(ops)
613    }
614}
615
616impl<T: MallocSizeOf> MallocSizeOf for parking_lot::Mutex<T> {
617    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
618        (*self.lock()).size_of(ops)
619    }
620}
621
622impl<T: MallocSizeOf> MallocSizeOf for parking_lot::RwLock<T> {
623    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
624        (*self.read()).size_of(ops)
625    }
626}
627
628impl<T: MallocSizeOf, Unit> MallocSizeOf for euclid::Length<T, Unit> {
629    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
630        self.0.size_of(ops)
631    }
632}
633
634impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::Scale<T, Src, Dst> {
635    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
636        self.0.size_of(ops)
637    }
638}
639
640impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Point2D<T, U> {
641    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
642        self.x.size_of(ops) + self.y.size_of(ops)
643    }
644}
645
646impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Box2D<T, U> {
647    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
648        self.min.size_of(ops) + self.max.size_of(ops)
649    }
650}
651
652impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Rect<T, U> {
653    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
654        self.origin.size_of(ops) + self.size.size_of(ops)
655    }
656}
657
658impl<T: MallocSizeOf, U> MallocSizeOf for euclid::SideOffsets2D<T, U> {
659    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
660        self.top.size_of(ops) +
661            self.right.size_of(ops) +
662            self.bottom.size_of(ops) +
663            self.left.size_of(ops)
664    }
665}
666
667impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Size2D<T, U> {
668    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
669        self.width.size_of(ops) + self.height.size_of(ops)
670    }
671}
672
673impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::Transform2D<T, Src, Dst> {
674    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
675        self.m11.size_of(ops) +
676            self.m12.size_of(ops) +
677            self.m21.size_of(ops) +
678            self.m22.size_of(ops) +
679            self.m31.size_of(ops) +
680            self.m32.size_of(ops)
681    }
682}
683
684impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::Transform3D<T, Src, Dst> {
685    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
686        self.m11.size_of(ops) +
687            self.m12.size_of(ops) +
688            self.m13.size_of(ops) +
689            self.m14.size_of(ops) +
690            self.m21.size_of(ops) +
691            self.m22.size_of(ops) +
692            self.m23.size_of(ops) +
693            self.m24.size_of(ops) +
694            self.m31.size_of(ops) +
695            self.m32.size_of(ops) +
696            self.m33.size_of(ops) +
697            self.m34.size_of(ops) +
698            self.m41.size_of(ops) +
699            self.m42.size_of(ops) +
700            self.m43.size_of(ops) +
701            self.m44.size_of(ops)
702    }
703}
704
705impl MallocSizeOf for url::Host {
706    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
707        match *self {
708            url::Host::Domain(ref s) => s.size_of(ops),
709            _ => 0,
710        }
711    }
712}
713
714impl MallocSizeOf for url::Url {
715    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
716        // TODO: This is an estimate, but a real size should be calculated in `rust-url` once
717        // it has support for `malloc_size_of`.
718        self.to_string().size_of(ops)
719    }
720}
721
722impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Vector2D<T, U> {
723    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
724        self.x.size_of(ops) + self.y.size_of(ops)
725    }
726}
727
728impl<Static: string_cache::StaticAtomSet> MallocSizeOf for string_cache::Atom<Static> {
729    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
730        0
731    }
732}
733
734// Placeholder for unique case where internals of Sender cannot be measured.
735// malloc size of is 0 macro complains about type supplied!
736impl<T> MallocSizeOf for crossbeam_channel::Sender<T> {
737    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
738        0
739    }
740}
741
742impl<T> MallocSizeOf for tokio::sync::mpsc::UnboundedSender<T> {
743    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
744        0
745    }
746}
747
748impl<T> MallocSizeOf for ipc_channel::ipc::IpcSender<T> {
749    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
750        0
751    }
752}
753
754impl<T> MallocSizeOf for ipc_channel::ipc::IpcReceiver<T> {
755    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
756        0
757    }
758}
759
760impl MallocSizeOf for ipc_channel::ipc::IpcSharedMemory {
761    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
762        self.len()
763    }
764}
765
766impl<T: MallocSizeOf> MallocSizeOf for accountable_refcell::RefCell<T> {
767    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
768        self.borrow().size_of(ops)
769    }
770}
771
772impl MallocSizeOf for servo_arc::Arc<ComputedValues> {
773    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
774        self.conditional_size_of(ops)
775    }
776}
777
778malloc_size_of_hash_map!(indexmap::IndexMap<K, V, S>);
779malloc_size_of_hash_set!(indexmap::IndexSet<T, S>);
780
781malloc_size_of_is_0!(bool, char, str);
782malloc_size_of_is_0!(f32, f64);
783malloc_size_of_is_0!(i8, i16, i32, i64, i128, isize);
784malloc_size_of_is_0!(u8, u16, u32, u64, u128, usize);
785
786malloc_size_of_is_0!(Range<f32>, Range<f64>);
787malloc_size_of_is_0!(Range<i8>, Range<i16>, Range<i32>, Range<i64>, Range<isize>);
788malloc_size_of_is_0!(Range<u8>, Range<u16>, Range<u32>, Range<u64>, Range<usize>);
789
790malloc_size_of_is_0!(Uuid);
791malloc_size_of_is_0!(content_security_policy::Destination);
792malloc_size_of_is_0!(http::StatusCode);
793malloc_size_of_is_0!(app_units::Au);
794malloc_size_of_is_0!(keyboard_types::Modifiers);
795malloc_size_of_is_0!(mime::Mime);
796malloc_size_of_is_0!(std::num::NonZeroU16);
797malloc_size_of_is_0!(std::num::NonZeroU64);
798malloc_size_of_is_0!(std::num::NonZeroUsize);
799malloc_size_of_is_0!(std::sync::atomic::AtomicBool);
800malloc_size_of_is_0!(std::sync::atomic::AtomicIsize);
801malloc_size_of_is_0!(std::sync::atomic::AtomicUsize);
802malloc_size_of_is_0!(std::time::Duration);
803malloc_size_of_is_0!(std::time::Instant);
804malloc_size_of_is_0!(std::time::SystemTime);
805malloc_size_of_is_0!(resvg::usvg::Tree);
806malloc_size_of_is_0!(style::data::ElementData);
807malloc_size_of_is_0!(style::font_face::SourceList);
808malloc_size_of_is_0!(style::properties::ComputedValues);
809malloc_size_of_is_0!(style::properties::declaration_block::PropertyDeclarationBlock);
810malloc_size_of_is_0!(style::queries::values::PrefersColorScheme);
811malloc_size_of_is_0!(style::stylesheets::Stylesheet);
812malloc_size_of_is_0!(style::values::specified::source_size_list::SourceSizeList);
813malloc_size_of_is_0!(taffy::Layout);
814malloc_size_of_is_0!(unicode_bidi::Level);
815malloc_size_of_is_0!(unicode_script::Script);
816malloc_size_of_is_0!(urlpattern::UrlPattern);
817
818macro_rules! malloc_size_of_is_webrender_malloc_size_of(
819    ($($ty:ty),+) => (
820        $(
821            impl MallocSizeOf for $ty {
822                fn size_of(&self, _: &mut MallocSizeOfOps) -> usize {
823                    let mut ops = wr_malloc_size_of::MallocSizeOfOps::new(servo_allocator::usable_size, None);
824                    <$ty as wr_malloc_size_of::MallocSizeOf>::size_of(self, &mut ops)
825                }
826            }
827        )+
828    );
829);
830
831malloc_size_of_is_webrender_malloc_size_of!(webrender_api::BorderRadius);
832malloc_size_of_is_webrender_malloc_size_of!(webrender_api::BorderStyle);
833malloc_size_of_is_webrender_malloc_size_of!(webrender_api::BoxShadowClipMode);
834malloc_size_of_is_webrender_malloc_size_of!(webrender_api::ColorF);
835malloc_size_of_is_webrender_malloc_size_of!(webrender_api::Epoch);
836malloc_size_of_is_webrender_malloc_size_of!(webrender_api::ExtendMode);
837malloc_size_of_is_webrender_malloc_size_of!(webrender_api::ExternalScrollId);
838malloc_size_of_is_webrender_malloc_size_of!(webrender_api::FontKey);
839malloc_size_of_is_webrender_malloc_size_of!(webrender_api::FontInstanceKey);
840malloc_size_of_is_webrender_malloc_size_of!(webrender_api::GlyphInstance);
841malloc_size_of_is_webrender_malloc_size_of!(webrender_api::GradientStop);
842malloc_size_of_is_webrender_malloc_size_of!(webrender_api::ImageKey);
843malloc_size_of_is_webrender_malloc_size_of!(webrender_api::ImageRendering);
844malloc_size_of_is_webrender_malloc_size_of!(webrender_api::LineStyle);
845malloc_size_of_is_webrender_malloc_size_of!(webrender_api::MixBlendMode);
846malloc_size_of_is_webrender_malloc_size_of!(webrender_api::NormalBorder);
847malloc_size_of_is_webrender_malloc_size_of!(webrender_api::PipelineId);
848malloc_size_of_is_webrender_malloc_size_of!(webrender_api::ReferenceFrameKind);
849malloc_size_of_is_webrender_malloc_size_of!(webrender_api::RepeatMode);
850malloc_size_of_is_webrender_malloc_size_of!(webrender_api::FontVariation);
851malloc_size_of_is_webrender_malloc_size_of!(webrender_api::SpatialId);
852malloc_size_of_is_webrender_malloc_size_of!(webrender_api::StickyOffsetBounds);
853malloc_size_of_is_webrender_malloc_size_of!(webrender_api::TransformStyle);
854malloc_size_of_is_webrender_malloc_size_of!(webrender::FastTransform<webrender_api::units::LayoutPixel,webrender_api::units::LayoutPixel>);
855
856macro_rules! malloc_size_of_is_stylo_malloc_size_of(
857    ($($ty:ty),+) => (
858        $(
859            impl MallocSizeOf for $ty {
860                fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
861                    <$ty as stylo_malloc_size_of::MallocSizeOf>::size_of(self, ops)
862                }
863            }
864        )+
865    );
866);
867
868impl<S> MallocSizeOf for style::author_styles::GenericAuthorStyles<S>
869where
870    S: style::stylesheets::StylesheetInDocument
871        + std::cmp::PartialEq
872        + stylo_malloc_size_of::MallocSizeOf,
873{
874    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
875        <style::author_styles::GenericAuthorStyles<S> as stylo_malloc_size_of::MallocSizeOf>::size_of(self, ops)
876    }
877}
878
879impl<S> MallocSizeOf for style::stylesheet_set::DocumentStylesheetSet<S>
880where
881    S: style::stylesheets::StylesheetInDocument
882        + std::cmp::PartialEq
883        + stylo_malloc_size_of::MallocSizeOf,
884{
885    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
886        <style::stylesheet_set::DocumentStylesheetSet<S> as stylo_malloc_size_of::MallocSizeOf>::size_of(self, ops)
887    }
888}
889
890impl<T> MallocSizeOf for style::shared_lock::Locked<T> {
891    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
892        // TODO: fix this implementation when Locked derives MallocSizeOf.
893        0
894        // <style::shared_lock::Locked<T> as stylo_malloc_size_of::MallocSizeOf>::size_of(self, ops)
895    }
896}
897
898impl<T: MallocSizeOf> MallocSizeOf for atomic_refcell::AtomicRefCell<T> {
899    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
900        self.borrow().size_of(ops)
901    }
902}
903
904malloc_size_of_is_stylo_malloc_size_of!(style::animation::DocumentAnimationSet);
905malloc_size_of_is_stylo_malloc_size_of!(style::attr::AttrIdentifier);
906malloc_size_of_is_stylo_malloc_size_of!(style::attr::AttrValue);
907malloc_size_of_is_stylo_malloc_size_of!(style::color::AbsoluteColor);
908malloc_size_of_is_stylo_malloc_size_of!(style::computed_values::font_variant_caps::T);
909malloc_size_of_is_stylo_malloc_size_of!(style::computed_values::text_decoration_style::T);
910malloc_size_of_is_stylo_malloc_size_of!(style::dom::OpaqueNode);
911malloc_size_of_is_stylo_malloc_size_of!(style::invalidation::element::restyle_hints::RestyleHint);
912malloc_size_of_is_stylo_malloc_size_of!(style::logical_geometry::WritingMode);
913malloc_size_of_is_stylo_malloc_size_of!(style::media_queries::MediaList);
914malloc_size_of_is_stylo_malloc_size_of!(
915    style::properties::longhands::align_items::computed_value::T
916);
917malloc_size_of_is_stylo_malloc_size_of!(
918    style::properties::longhands::flex_direction::computed_value::T
919);
920malloc_size_of_is_stylo_malloc_size_of!(style::properties::longhands::flex_wrap::computed_value::T);
921malloc_size_of_is_stylo_malloc_size_of!(style::properties::style_structs::Font);
922malloc_size_of_is_stylo_malloc_size_of!(style::selector_parser::PseudoElement);
923malloc_size_of_is_stylo_malloc_size_of!(style::selector_parser::RestyleDamage);
924malloc_size_of_is_stylo_malloc_size_of!(style::selector_parser::Snapshot);
925malloc_size_of_is_stylo_malloc_size_of!(style::shared_lock::SharedRwLock);
926malloc_size_of_is_stylo_malloc_size_of!(style::stylesheets::DocumentStyleSheet);
927malloc_size_of_is_stylo_malloc_size_of!(style::stylist::Stylist);
928malloc_size_of_is_stylo_malloc_size_of!(style::values::computed::AlignContent);
929malloc_size_of_is_stylo_malloc_size_of!(style::values::computed::BorderStyle);
930malloc_size_of_is_stylo_malloc_size_of!(style::values::computed::FontStretch);
931malloc_size_of_is_stylo_malloc_size_of!(style::values::computed::FontStyle);
932malloc_size_of_is_stylo_malloc_size_of!(style::values::computed::FontWeight);
933malloc_size_of_is_stylo_malloc_size_of!(style::values::computed::font::SingleFontFamily);
934malloc_size_of_is_stylo_malloc_size_of!(style::values::computed::JustifyContent);
935malloc_size_of_is_stylo_malloc_size_of!(style::values::specified::align::AlignFlags);
936malloc_size_of_is_stylo_malloc_size_of!(style::values::specified::TextDecorationLine);
937malloc_size_of_is_stylo_malloc_size_of!(stylo_dom::ElementState);
938
939impl<T> MallocSizeOf for GenericLengthPercentageOrAuto<T>
940where
941    T: stylo_malloc_size_of::MallocSizeOf,
942{
943    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
944        <GenericLengthPercentageOrAuto<T> as stylo_malloc_size_of::MallocSizeOf>::size_of(self, ops)
945    }
946}