Bug 1890689 accumulate input in LargerReceiverBlockSizeThanDesiredBuffering GTest...
[gecko.git] / gfx / wr / wr_malloc_size_of / lib.rs
blobed432e2a50da4f31da7965b7d66e9bdffab28893
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.
11 //! A reduced fork of Firefox's malloc_size_of crate, for bundling with WebRender.
13 extern crate app_units;
14 extern crate euclid;
16 use std::hash::{BuildHasher, Hash};
17 use std::mem::size_of;
18 use std::ops::Range;
19 use std::os::raw::c_void;
20 use std::path::PathBuf;
22 /// A C function that takes a pointer to a heap allocation and returns its size.
23 type VoidPtrToSizeFn = unsafe extern "C" fn(ptr: *const c_void) -> usize;
25 /// Operations used when measuring heap usage of data structures.
26 pub struct MallocSizeOfOps {
27     /// A function that returns the size of a heap allocation.
28     pub size_of_op: VoidPtrToSizeFn,
30     /// Like `size_of_op`, but can take an interior pointer. Optional because
31     /// not all allocators support this operation. If it's not provided, some
32     /// memory measurements will actually be computed estimates rather than
33     /// real and accurate measurements.
34     pub enclosing_size_of_op: Option<VoidPtrToSizeFn>,
37 impl MallocSizeOfOps {
38     pub fn new(
39         size_of: VoidPtrToSizeFn,
40         malloc_enclosing_size_of: Option<VoidPtrToSizeFn>,
41     ) -> Self {
42         MallocSizeOfOps {
43             size_of_op: size_of,
44             enclosing_size_of_op: malloc_enclosing_size_of,
45         }
46     }
48     /// Check if an allocation is empty. This relies on knowledge of how Rust
49     /// handles empty allocations, which may change in the future.
50     fn is_empty<T: ?Sized>(ptr: *const T) -> bool {
51         // The correct condition is this:
52         //   `ptr as usize <= ::std::mem::align_of::<T>()`
53         // But we can't call align_of() on a ?Sized T. So we approximate it
54         // with the following. 256 is large enough that it should always be
55         // larger than the required alignment, but small enough that it is
56         // always in the first page of memory and therefore not a legitimate
57         // address.
58         ptr as *const usize as usize <= 256
59     }
61     /// Call `size_of_op` on `ptr`, first checking that the allocation isn't
62     /// empty, because some types (such as `Vec`) utilize empty allocations.
63     pub unsafe fn malloc_size_of<T: ?Sized>(&self, ptr: *const T) -> usize {
64         if MallocSizeOfOps::is_empty(ptr) {
65             0
66         } else {
67             (self.size_of_op)(ptr as *const c_void)
68         }
69     }
71     /// Is an `enclosing_size_of_op` available?
72     pub fn has_malloc_enclosing_size_of(&self) -> bool {
73         self.enclosing_size_of_op.is_some()
74     }
76     /// Call `enclosing_size_of_op`, which must be available, on `ptr`, which
77     /// must not be empty.
78     pub unsafe fn malloc_enclosing_size_of<T>(&self, ptr: *const T) -> usize {
79         assert!(!MallocSizeOfOps::is_empty(ptr));
80         (self.enclosing_size_of_op.unwrap())(ptr as *const c_void)
81     }
84 /// Trait for measuring the "deep" heap usage of a data structure. This is the
85 /// most commonly-used of the traits.
86 pub trait MallocSizeOf {
87     /// Measure the heap usage of all descendant heap-allocated structures, but
88     /// not the space taken up by the value itself.
89     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize;
92 /// Trait for measuring the "shallow" heap usage of a container.
93 pub trait MallocShallowSizeOf {
94     /// Measure the heap usage of immediate heap-allocated descendant
95     /// structures, but not the space taken up by the value itself. Anything
96     /// beyond the immediate descendants must be measured separately, using
97     /// iteration.
98     fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize;
101 impl MallocSizeOf for String {
102     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
103         unsafe { ops.malloc_size_of(self.as_ptr()) }
104     }
107 impl<T: ?Sized> MallocShallowSizeOf for Box<T> {
108     fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
109         unsafe { ops.malloc_size_of(&**self) }
110     }
113 impl<T: MallocSizeOf + ?Sized> MallocSizeOf for Box<T> {
114     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
115         self.shallow_size_of(ops) + (**self).size_of(ops)
116     }
119 impl MallocSizeOf for () {
120     fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
121         0
122     }
125 impl<T1, T2> MallocSizeOf for (T1, T2)
126 where
127     T1: MallocSizeOf,
128     T2: MallocSizeOf,
130     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
131         self.0.size_of(ops) + self.1.size_of(ops)
132     }
135 impl<T1, T2, T3> MallocSizeOf for (T1, T2, T3)
136 where
137     T1: MallocSizeOf,
138     T2: MallocSizeOf,
139     T3: MallocSizeOf,
141     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
142         self.0.size_of(ops) + self.1.size_of(ops) + self.2.size_of(ops)
143     }
146 impl<T1, T2, T3, T4> MallocSizeOf for (T1, T2, T3, T4)
147 where
148     T1: MallocSizeOf,
149     T2: MallocSizeOf,
150     T3: MallocSizeOf,
151     T4: MallocSizeOf,
153     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
154         self.0.size_of(ops) + self.1.size_of(ops) + self.2.size_of(ops) + self.3.size_of(ops)
155     }
158 impl<T: MallocSizeOf> MallocSizeOf for Option<T> {
159     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
160         if let Some(val) = self.as_ref() {
161             val.size_of(ops)
162         } else {
163             0
164         }
165     }
168 impl<T: MallocSizeOf, E: MallocSizeOf> MallocSizeOf for Result<T, E> {
169     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
170         match *self {
171             Ok(ref x) => x.size_of(ops),
172             Err(ref e) => e.size_of(ops),
173         }
174     }
177 impl<T: MallocSizeOf + Copy> MallocSizeOf for std::cell::Cell<T> {
178     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
179         self.get().size_of(ops)
180     }
183 impl<T: MallocSizeOf> MallocSizeOf for std::cell::RefCell<T> {
184     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
185         self.borrow().size_of(ops)
186     }
189 impl<'a, B: ?Sized + ToOwned> MallocSizeOf for std::borrow::Cow<'a, B>
190 where
191     B::Owned: MallocSizeOf,
193     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
194         match *self {
195             std::borrow::Cow::Borrowed(_) => 0,
196             std::borrow::Cow::Owned(ref b) => b.size_of(ops),
197         }
198     }
201 impl<T: MallocSizeOf> MallocSizeOf for [T] {
202     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
203         let mut n = 0;
204         for elem in self.iter() {
205             n += elem.size_of(ops);
206         }
207         n
208     }
211 impl<T> MallocShallowSizeOf for Vec<T> {
212     fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
213         unsafe { ops.malloc_size_of(self.as_ptr()) }
214     }
217 impl<T: MallocSizeOf> MallocSizeOf for Vec<T> {
218     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
219         let mut n = self.shallow_size_of(ops);
220         for elem in self.iter() {
221             n += elem.size_of(ops);
222         }
223         n
224     }
227 macro_rules! malloc_size_of_hash_set {
228     ($ty:ty) => {
229         impl<T, S> MallocShallowSizeOf for $ty
230         where
231             T: Eq + Hash,
232             S: BuildHasher,
233         {
234             fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
235                 if ops.has_malloc_enclosing_size_of() {
236                     // The first value from the iterator gives us an interior pointer.
237                     // `ops.malloc_enclosing_size_of()` then gives us the storage size.
238                     // This assumes that the `HashSet`'s contents (values and hashes)
239                     // are all stored in a single contiguous heap allocation.
240                     self.iter()
241                         .next()
242                         .map_or(0, |t| unsafe { ops.malloc_enclosing_size_of(t) })
243                 } else {
244                     // An estimate.
245                     self.capacity() * (size_of::<T>() + size_of::<usize>())
246                 }
247             }
248         }
250         impl<T, S> MallocSizeOf for $ty
251         where
252             T: Eq + Hash + MallocSizeOf,
253             S: BuildHasher,
254         {
255             fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
256                 let mut n = self.shallow_size_of(ops);
257                 for t in self.iter() {
258                     n += t.size_of(ops);
259                 }
260                 n
261             }
262         }
263     };
266 malloc_size_of_hash_set!(std::collections::HashSet<T, S>);
268 macro_rules! malloc_size_of_hash_map {
269     ($ty:ty) => {
270         impl<K, V, S> MallocShallowSizeOf for $ty
271         where
272             K: Eq + Hash,
273             S: BuildHasher,
274         {
275             fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
276                 // See the implementation for std::collections::HashSet for details.
277                 if ops.has_malloc_enclosing_size_of() {
278                     self.values()
279                         .next()
280                         .map_or(0, |v| unsafe { ops.malloc_enclosing_size_of(v) })
281                 } else {
282                     self.capacity() * (size_of::<V>() + size_of::<K>() + size_of::<usize>())
283                 }
284             }
285         }
287         impl<K, V, S> MallocSizeOf for $ty
288         where
289             K: Eq + Hash + MallocSizeOf,
290             V: MallocSizeOf,
291             S: BuildHasher,
292         {
293             fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
294                 let mut n = self.shallow_size_of(ops);
295                 for (k, v) in self.iter() {
296                     n += k.size_of(ops);
297                     n += v.size_of(ops);
298                 }
299                 n
300             }
301         }
302     };
305 malloc_size_of_hash_map!(std::collections::HashMap<K, V, S>);
307 // PhantomData is always 0.
308 impl<T> MallocSizeOf for std::marker::PhantomData<T> {
309     fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
310         0
311     }
314 impl MallocSizeOf for PathBuf {
315     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
316         match self.to_str() {
317             Some(s) => unsafe { ops.malloc_size_of(s.as_ptr()) },
318             None => self.as_os_str().len(),
319         }
320     }
323 impl<T: MallocSizeOf, Unit> MallocSizeOf for euclid::Length<T, Unit> {
324     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
325         self.0.size_of(ops)
326     }
329 impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::Scale<T, Src, Dst> {
330     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
331         self.0.size_of(ops)
332     }
335 impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Point2D<T, U> {
336     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
337         self.x.size_of(ops) + self.y.size_of(ops)
338     }
341 impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Rect<T, U> {
342     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
343         self.origin.size_of(ops) + self.size.size_of(ops)
344     }
347 impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Box2D<T, U> {
348     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
349         self.min.size_of(ops) + self.max.size_of(ops)
350     }
353 impl<T: MallocSizeOf, U> MallocSizeOf for euclid::SideOffsets2D<T, U> {
354     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
355         self.top.size_of(ops) +
356             self.right.size_of(ops) +
357             self.bottom.size_of(ops) +
358             self.left.size_of(ops)
359     }
362 impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Size2D<T, U> {
363     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
364         self.width.size_of(ops) + self.height.size_of(ops)
365     }
368 impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::Transform2D<T, Src, Dst> {
369     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
370         self.m11.size_of(ops) +
371             self.m12.size_of(ops) +
372             self.m21.size_of(ops) +
373             self.m22.size_of(ops) +
374             self.m31.size_of(ops) +
375             self.m32.size_of(ops)
376     }
379 impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::Transform3D<T, Src, Dst> {
380     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
381         self.m11.size_of(ops) +
382             self.m12.size_of(ops) +
383             self.m13.size_of(ops) +
384             self.m14.size_of(ops) +
385             self.m21.size_of(ops) +
386             self.m22.size_of(ops) +
387             self.m23.size_of(ops) +
388             self.m24.size_of(ops) +
389             self.m31.size_of(ops) +
390             self.m32.size_of(ops) +
391             self.m33.size_of(ops) +
392             self.m34.size_of(ops) +
393             self.m41.size_of(ops) +
394             self.m42.size_of(ops) +
395             self.m43.size_of(ops) +
396             self.m44.size_of(ops)
397     }
400 impl<T: MallocSizeOf, U> MallocSizeOf for euclid::Vector2D<T, U> {
401     fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
402         self.x.size_of(ops) + self.y.size_of(ops)
403     }
406 /// For use on types where size_of() returns 0.
407 #[macro_export]
408 macro_rules! malloc_size_of_is_0(
409     ($($ty:ty),+) => (
410         $(
411             impl $crate::MallocSizeOf for $ty {
412                 #[inline(always)]
413                 fn size_of(&self, _: &mut $crate::MallocSizeOfOps) -> usize {
414                     0
415                 }
416             }
417         )+
418     );
419     ($($ty:ident<$($gen:ident),+>),+) => (
420         $(
421         impl<$($gen: $crate::MallocSizeOf),+> $crate::MallocSizeOf for $ty<$($gen),+> {
422             #[inline(always)]
423             fn size_of(&self, _: &mut $crate::MallocSizeOfOps) -> usize {
424                 0
425             }
426         }
427         )+
428     );
431 malloc_size_of_is_0!(bool, char, str);
432 malloc_size_of_is_0!(u8, u16, u32, u64, u128, usize);
433 malloc_size_of_is_0!(i8, i16, i32, i64, i128, isize);
434 malloc_size_of_is_0!(f32, f64);
436 malloc_size_of_is_0!(std::sync::atomic::AtomicBool);
437 malloc_size_of_is_0!(std::sync::atomic::AtomicIsize);
438 malloc_size_of_is_0!(std::sync::atomic::AtomicUsize);
440 malloc_size_of_is_0!(std::num::NonZeroUsize);
441 malloc_size_of_is_0!(std::num::NonZeroU32);
443 malloc_size_of_is_0!(std::time::Duration);
444 malloc_size_of_is_0!(std::time::Instant);
445 malloc_size_of_is_0!(std::time::SystemTime);
447 malloc_size_of_is_0!(Range<u8>, Range<u16>, Range<u32>, Range<u64>, Range<usize>);
448 malloc_size_of_is_0!(Range<i8>, Range<i16>, Range<i32>, Range<i64>, Range<isize>);
449 malloc_size_of_is_0!(Range<f32>, Range<f64>);
451 malloc_size_of_is_0!(app_units::Au);