mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Replace all uses of the heapsize
crate with malloc_size_of
.
Servo currently uses `heapsize`, but Stylo/Gecko use `malloc_size_of`. `malloc_size_of` is better -- it handles various cases that `heapsize` does not -- so this patch changes Servo to use `malloc_size_of`. This patch makes the following changes to the `malloc_size_of` crate. - Adds `MallocSizeOf` trait implementations for numerous types, some built-in (e.g. `VecDeque`), some external and Servo-only (e.g. `string_cache`). - Makes `enclosing_size_of_op` optional, because vanilla jemalloc doesn't support that operation. - For `HashSet`/`HashMap`, falls back to a computed estimate when `enclosing_size_of_op` isn't available. - Adds an extern "C" `malloc_size_of` function that does the actual heap measurement; this is based on the same functions from the `heapsize` crate. This patch makes the following changes elsewhere. - Converts all the uses of `heapsize` to instead use `malloc_size_of`. - Disables the "heapsize"/"heap_size" feature for the external crates that provide it. - Removes the `HeapSizeOf` implementation from `hashglobe`. - Adds `ignore` annotations to a few `Rc`/`Arc`, because `malloc_size_of` doesn't derive those types, unlike `heapsize`.
This commit is contained in:
parent
421baa854e
commit
4506f0d30c
269 changed files with 1418 additions and 1521 deletions
|
@ -10,28 +10,15 @@
|
|||
|
||||
//! A crate for measuring the heap usage of data structures in a way that
|
||||
//! integrates with Firefox's memory reporting, particularly the use of
|
||||
//! mozjemalloc and DMD.
|
||||
//!
|
||||
//! This crate has a lot of overlap with the existing `heapsize` crate, and may
|
||||
//! one day be merged into it. But for now, `heapsize` has the following
|
||||
//! major shortcomings.
|
||||
//! - It basically assumes that the `HeapSizeOf` trait can be used for every
|
||||
//! type, which is not true. Sometimes more than a single size measurement
|
||||
//! needs to be returned for a type, and sometimes additional synchronization
|
||||
//! arguments (such as lock guards) need to be passed in.
|
||||
//! - It has no proper way of measuring some common types, such as `HashSet`
|
||||
//! and `HashMap`, that don't expose internal pointers.
|
||||
//! - It has no proper way of handling values with multiple referents, such as
|
||||
//! `Rc` and `Arc`.
|
||||
//!
|
||||
//! This crate solves those problems.
|
||||
//! mozjemalloc and DMD. In particular, it has the following features.
|
||||
//! - It isn't bound to a particular heap allocator.
|
||||
//! - It provides traits for both "shallow" and "deep" measurement, which gives
|
||||
//! more flexibility in the cases where the traits can't be used.
|
||||
//! flexibility in the cases where the traits can't be used.
|
||||
//! - It allows for measuring blocks even when only an interior pointer can be
|
||||
//! obtained for heap allocations, e.g. `HashSet` and `HashMap`. (This relies
|
||||
//! on the heap allocator having suitable support, which mozjemalloc has.)
|
||||
//! - It allows handling of types like `Rc` and `Arc` by providing special
|
||||
//! traits that are different to the ones for non-graph structures.
|
||||
//! - It allows handling of types like `Rc` and `Arc` by providing traits that
|
||||
//! are different to the ones for non-graph structures.
|
||||
//!
|
||||
//! Suggested uses are as follows.
|
||||
//! - When possible, use the `MallocSizeOf` trait. (Deriving support is
|
||||
|
@ -60,11 +47,26 @@ extern crate app_units;
|
|||
extern crate cssparser;
|
||||
extern crate euclid;
|
||||
extern crate hashglobe;
|
||||
#[cfg(feature = "servo")]
|
||||
extern crate js;
|
||||
#[cfg(target_os = "windows")]
|
||||
extern crate kernel32;
|
||||
extern crate servo_arc;
|
||||
extern crate smallbitvec;
|
||||
extern crate smallvec;
|
||||
#[cfg(feature = "servo")]
|
||||
extern crate string_cache;
|
||||
#[cfg(feature = "servo")]
|
||||
extern crate url;
|
||||
#[cfg(feature = "servo")]
|
||||
extern crate webrender_api;
|
||||
#[cfg(feature = "servo")]
|
||||
extern crate xml5ever;
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
use kernel32::{GetProcessHeap, HeapSize, HeapValidate};
|
||||
use std::hash::{BuildHasher, Hash};
|
||||
use std::mem::size_of;
|
||||
use std::ops::Range;
|
||||
use std::os::raw::c_void;
|
||||
|
||||
|
@ -79,8 +81,11 @@ pub struct MallocSizeOfOps {
|
|||
/// A function that returns the size of a heap allocation.
|
||||
size_of_op: VoidPtrToSizeFn,
|
||||
|
||||
/// Like `size_of_op`, but can take an interior pointer.
|
||||
enclosing_size_of_op: VoidPtrToSizeFn,
|
||||
/// Like `size_of_op`, but can take an interior pointer. Optional because
|
||||
/// not all allocators support this operation. If it's not provided, some
|
||||
/// memory measurements will actually be computed estimates rather than
|
||||
/// real and accurate measurements.
|
||||
enclosing_size_of_op: Option<VoidPtrToSizeFn>,
|
||||
|
||||
/// Check if a pointer has been seen before, and remember it for next time.
|
||||
/// Useful when measuring `Rc`s and `Arc`s. Optional, because many places
|
||||
|
@ -89,7 +94,8 @@ pub struct MallocSizeOfOps {
|
|||
}
|
||||
|
||||
impl MallocSizeOfOps {
|
||||
pub fn new(size_of: VoidPtrToSizeFn, malloc_enclosing_size_of: VoidPtrToSizeFn,
|
||||
pub fn new(size_of: VoidPtrToSizeFn,
|
||||
malloc_enclosing_size_of: Option<VoidPtrToSizeFn>,
|
||||
have_seen_ptr: Option<Box<VoidPtrToBoolFnMut>>) -> Self {
|
||||
MallocSizeOfOps {
|
||||
size_of_op: size_of,
|
||||
|
@ -121,10 +127,16 @@ impl MallocSizeOfOps {
|
|||
}
|
||||
}
|
||||
|
||||
/// Call `enclosing_size_of_op` on `ptr`, which must not be empty.
|
||||
/// Is an `enclosing_size_of_op` available?
|
||||
pub fn has_malloc_enclosing_size_of(&self) -> bool {
|
||||
self.enclosing_size_of_op.is_some()
|
||||
}
|
||||
|
||||
/// Call `enclosing_size_of_op`, which must be available, on `ptr`, which
|
||||
/// must not be empty.
|
||||
pub unsafe fn malloc_enclosing_size_of<T>(&self, ptr: *const T) -> usize {
|
||||
assert!(!MallocSizeOfOps::is_empty(ptr));
|
||||
(self.enclosing_size_of_op)(ptr as *const c_void)
|
||||
(self.enclosing_size_of_op.unwrap())(ptr as *const c_void)
|
||||
}
|
||||
|
||||
/// Call `have_seen_ptr_op` on `ptr`.
|
||||
|
@ -134,6 +146,33 @@ impl MallocSizeOfOps {
|
|||
}
|
||||
}
|
||||
|
||||
/// Get the size of a heap block.
|
||||
#[cfg(not(target_os = "windows"))]
|
||||
pub unsafe extern "C" fn malloc_size_of(ptr: *const c_void) -> usize {
|
||||
// The C prototype is `je_malloc_usable_size(JEMALLOC_USABLE_SIZE_CONST void *ptr)`. On some
|
||||
// platforms `JEMALLOC_USABLE_SIZE_CONST` is `const` and on some it is empty. But in practice
|
||||
// this function doesn't modify the contents of the block that `ptr` points to, so we use
|
||||
// `*const c_void` here.
|
||||
extern "C" {
|
||||
#[cfg_attr(any(prefixed_jemalloc, target_os = "macos", target_os = "ios", target_os = "android"),
|
||||
link_name = "je_malloc_usable_size")]
|
||||
fn malloc_usable_size(ptr: *const c_void) -> usize;
|
||||
}
|
||||
malloc_usable_size(ptr)
|
||||
}
|
||||
|
||||
/// Get the size of a heap block.
|
||||
#[cfg(target_os = "windows")]
|
||||
pub unsafe extern "C" fn malloc_size_of(mut ptr: *const c_void) -> usize {
|
||||
let heap = GetProcessHeap();
|
||||
|
||||
if HeapValidate(heap, 0, ptr) == 0 {
|
||||
ptr = *(ptr as *const *const c_void).offset(-1);
|
||||
}
|
||||
|
||||
HeapSize(heap, 0, ptr) as usize
|
||||
}
|
||||
|
||||
/// Trait for measuring the "deep" heap usage of a data structure. This is the
|
||||
/// most commonly-used of the traits.
|
||||
pub trait MallocSizeOf {
|
||||
|
@ -188,6 +227,13 @@ impl MallocSizeOf for String {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, T: ?Sized> MallocSizeOf for &'a T {
|
||||
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
|
||||
// Zero makes sense for a non-owning reference.
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> MallocShallowSizeOf for Box<T> {
|
||||
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
unsafe { ops.malloc_size_of(&**self) }
|
||||
|
@ -200,12 +246,36 @@ impl<T: MallocSizeOf + ?Sized> MallocSizeOf for Box<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<A: MallocSizeOf, B: MallocSizeOf> MallocSizeOf for (A, B) {
|
||||
impl MallocSizeOf for () {
|
||||
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
impl<T1, T2> MallocSizeOf for (T1, T2)
|
||||
where T1: MallocSizeOf, T2: MallocSizeOf
|
||||
{
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.0.size_of(ops) + self.1.size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T1, T2, T3> MallocSizeOf for (T1, T2, T3)
|
||||
where T1: MallocSizeOf, T2: MallocSizeOf, T3: MallocSizeOf
|
||||
{
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.0.size_of(ops) + self.1.size_of(ops) + self.2.size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T1, T2, T3, T4> MallocSizeOf for (T1, T2, T3, T4)
|
||||
where T1: MallocSizeOf, T2: MallocSizeOf, T3: MallocSizeOf, T4: MallocSizeOf
|
||||
{
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.0.size_of(ops) + self.1.size_of(ops) + self.2.size_of(ops) + self.3.size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf> MallocSizeOf for Option<T> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
if let Some(val) = self.as_ref() {
|
||||
|
@ -216,6 +286,38 @@ impl<T: MallocSizeOf> MallocSizeOf for Option<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf, E: MallocSizeOf> MallocSizeOf for Result<T, E> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
match *self {
|
||||
Ok(ref x) => x.size_of(ops),
|
||||
Err(ref e) => e.size_of(ops),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf + Copy> MallocSizeOf for std::cell::Cell<T> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.get().size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf> MallocSizeOf for std::cell::RefCell<T> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.borrow().size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, B: ?Sized + ToOwned> MallocSizeOf for std::borrow::Cow<'a, B>
|
||||
where B::Owned: MallocSizeOf
|
||||
{
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
match *self {
|
||||
std::borrow::Cow::Borrowed(_) => 0,
|
||||
std::borrow::Cow::Owned(ref b) => b.size_of(ops),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf> MallocSizeOf for [T] {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
let mut n = 0;
|
||||
|
@ -242,6 +344,33 @@ impl<T: MallocSizeOf> MallocSizeOf for Vec<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> MallocShallowSizeOf for std::collections::VecDeque<T> {
|
||||
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
if ops.has_malloc_enclosing_size_of() {
|
||||
if let Some(front) = self.front() {
|
||||
// The front element is an interior pointer.
|
||||
unsafe { ops.malloc_enclosing_size_of(&*front) }
|
||||
} else {
|
||||
// This assumes that no memory is allocated when the VecDeque is empty.
|
||||
0
|
||||
}
|
||||
} else {
|
||||
// An estimate.
|
||||
self.capacity() * size_of::<T>()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf> MallocSizeOf for std::collections::VecDeque<T> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
let mut n = self.shallow_size_of(ops);
|
||||
for elem in self.iter() {
|
||||
n += elem.size_of(ops);
|
||||
}
|
||||
n
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: smallvec::Array> MallocShallowSizeOf for smallvec::SmallVec<A> {
|
||||
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
if self.spilled() {
|
||||
|
@ -270,11 +399,16 @@ impl<T, S> MallocShallowSizeOf for std::collections::HashSet<T, S>
|
|||
S: BuildHasher
|
||||
{
|
||||
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
// The first value from the iterator gives us an interior pointer.
|
||||
// `ops.malloc_enclosing_size_of()` then gives us the storage size.
|
||||
// This assumes that the `HashSet`'s contents (values and hashes) are
|
||||
// all stored in a single contiguous heap allocation.
|
||||
self.iter().next().map_or(0, |t| unsafe { ops.malloc_enclosing_size_of(t) })
|
||||
if ops.has_malloc_enclosing_size_of() {
|
||||
// The first value from the iterator gives us an interior pointer.
|
||||
// `ops.malloc_enclosing_size_of()` then gives us the storage size.
|
||||
// This assumes that the `HashSet`'s contents (values and hashes)
|
||||
// are all stored in a single contiguous heap allocation.
|
||||
self.iter().next().map_or(0, |t| unsafe { ops.malloc_enclosing_size_of(t) })
|
||||
} else {
|
||||
// An estimate.
|
||||
self.capacity() * (size_of::<T>() + size_of::<usize>())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -297,7 +431,11 @@ impl<T, S> MallocShallowSizeOf for hashglobe::hash_set::HashSet<T, S>
|
|||
{
|
||||
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
// See the implementation for std::collections::HashSet for details.
|
||||
self.iter().next().map_or(0, |t| unsafe { ops.malloc_enclosing_size_of(t) })
|
||||
if ops.has_malloc_enclosing_size_of() {
|
||||
self.iter().next().map_or(0, |t| unsafe { ops.malloc_enclosing_size_of(t) })
|
||||
} else {
|
||||
self.capacity() * (size_of::<T>() + size_of::<usize>())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -314,13 +452,66 @@ impl<T, S> MallocSizeOf for hashglobe::hash_set::HashSet<T, S>
|
|||
}
|
||||
}
|
||||
|
||||
impl<T, S> MallocShallowSizeOf for hashglobe::fake::HashSet<T, S>
|
||||
where T: Eq + Hash,
|
||||
S: BuildHasher,
|
||||
{
|
||||
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
use std::ops::Deref;
|
||||
self.deref().shallow_size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S> MallocSizeOf for hashglobe::fake::HashSet<T, S>
|
||||
where T: Eq + Hash + MallocSizeOf,
|
||||
S: BuildHasher,
|
||||
{
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
use std::ops::Deref;
|
||||
self.deref().size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V, S> MallocShallowSizeOf for std::collections::HashMap<K, V, S>
|
||||
where K: Eq + Hash,
|
||||
S: BuildHasher
|
||||
{
|
||||
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
// See the implementation for std::collections::HashSet for details.
|
||||
if ops.has_malloc_enclosing_size_of() {
|
||||
self.values().next().map_or(0, |v| unsafe { ops.malloc_enclosing_size_of(v) })
|
||||
} else {
|
||||
self.capacity() * (size_of::<V>() + size_of::<K>() + size_of::<usize>())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V, S> MallocSizeOf for std::collections::HashMap<K, V, S>
|
||||
where K: Eq + Hash + MallocSizeOf,
|
||||
V: MallocSizeOf,
|
||||
S: BuildHasher,
|
||||
{
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
let mut n = self.shallow_size_of(ops);
|
||||
for (k, v) in self.iter() {
|
||||
n += k.size_of(ops);
|
||||
n += v.size_of(ops);
|
||||
}
|
||||
n
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V, S> MallocShallowSizeOf for hashglobe::hash_map::HashMap<K, V, S>
|
||||
where K: Eq + Hash,
|
||||
S: BuildHasher
|
||||
{
|
||||
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
// See the implementation for std::collections::HashSet for details.
|
||||
self.values().next().map_or(0, |v| unsafe { ops.malloc_enclosing_size_of(v) })
|
||||
if ops.has_malloc_enclosing_size_of() {
|
||||
self.values().next().map_or(0, |v| unsafe { ops.malloc_enclosing_size_of(v) })
|
||||
} else {
|
||||
self.capacity() * (size_of::<V>() + size_of::<K>() + size_of::<usize>())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -358,6 +549,34 @@ impl<K, V, S> MallocSizeOf for hashglobe::diagnostic::DiagnosticHashMap<K, V, S>
|
|||
}
|
||||
}
|
||||
|
||||
impl<K, V, S> MallocShallowSizeOf for hashglobe::fake::HashMap<K, V, S>
|
||||
where K: Eq + Hash,
|
||||
S: BuildHasher,
|
||||
{
|
||||
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
use std::ops::Deref;
|
||||
self.deref().shallow_size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V, S> MallocSizeOf for hashglobe::fake::HashMap<K, V, S>
|
||||
where K: Eq + Hash + MallocSizeOf,
|
||||
V: MallocSizeOf,
|
||||
S: BuildHasher,
|
||||
{
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
use std::ops::Deref;
|
||||
self.deref().size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
// PhantomData is always 0.
|
||||
impl<T> MallocSizeOf for std::marker::PhantomData<T> {
|
||||
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: we don't want MallocSizeOf to be defined for Rc and Arc. If negative
|
||||
// trait bounds are ever allowed, this code should be uncommented.
|
||||
// (We do have a compile-fail test for this:
|
||||
|
@ -407,12 +626,86 @@ impl MallocSizeOf for smallbitvec::SmallBitVec {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf, Unit> MallocSizeOf for euclid::Length<T, Unit> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.0.size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::ScaleFactor<T, Src, Dst> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.0.size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedPoint2D<T, U> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.x.size_of(ops) + self.y.size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedRect<T, U> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.origin.size_of(ops) + self.size.size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedSideOffsets2D<T, U> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.top.size_of(ops) + self.right.size_of(ops) +
|
||||
self.bottom.size_of(ops) + self.left.size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedSize2D<T, U> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.width.size_of(ops) + self.height.size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::TypedTransform2D<T, Src, Dst> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.m11.size_of(ops) + self.m12.size_of(ops) +
|
||||
self.m21.size_of(ops) + self.m22.size_of(ops) +
|
||||
self.m31.size_of(ops) + self.m32.size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::TypedTransform3D<T, Src, Dst> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.m11.size_of(ops) + self.m12.size_of(ops) +
|
||||
self.m13.size_of(ops) + self.m14.size_of(ops) +
|
||||
self.m21.size_of(ops) + self.m22.size_of(ops) +
|
||||
self.m23.size_of(ops) + self.m24.size_of(ops) +
|
||||
self.m31.size_of(ops) + self.m32.size_of(ops) +
|
||||
self.m33.size_of(ops) + self.m34.size_of(ops) +
|
||||
self.m41.size_of(ops) + self.m42.size_of(ops) +
|
||||
self.m43.size_of(ops) + self.m44.size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedVector2D<T, U> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.x.size_of(ops) + self.y.size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "servo")]
|
||||
impl<Static: string_cache::StaticAtomSet> MallocSizeOf for string_cache::Atom<Static> {
|
||||
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
// This is measured properly by the heap measurement implemented in
|
||||
// SpiderMonkey.
|
||||
#[cfg(feature = "servo")]
|
||||
impl<T: Copy + js::rust::GCMethods> MallocSizeOf for js::jsapi::Heap<T> {
|
||||
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
/// For use on types where size_of() returns 0.
|
||||
#[macro_export]
|
||||
macro_rules! malloc_size_of_is_0(
|
||||
|
@ -443,9 +736,57 @@ malloc_size_of_is_0!(u8, u16, u32, u64, usize);
|
|||
malloc_size_of_is_0!(i8, i16, i32, i64, isize);
|
||||
malloc_size_of_is_0!(f32, f64);
|
||||
|
||||
malloc_size_of_is_0!(std::sync::atomic::AtomicBool);
|
||||
malloc_size_of_is_0!(std::sync::atomic::AtomicIsize, std::sync::atomic::AtomicUsize);
|
||||
|
||||
malloc_size_of_is_0!(Range<u8>, Range<u16>, Range<u32>, Range<u64>, Range<usize>);
|
||||
malloc_size_of_is_0!(Range<i8>, Range<i16>, Range<i32>, Range<i64>, Range<isize>);
|
||||
malloc_size_of_is_0!(Range<f32>, Range<f64>);
|
||||
|
||||
malloc_size_of_is_0!(app_units::Au);
|
||||
|
||||
malloc_size_of_is_0!(cssparser::RGBA, cssparser::TokenSerializationType);
|
||||
|
||||
#[cfg(feature = "servo")]
|
||||
impl MallocSizeOf for url::Host {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
match *self {
|
||||
url::Host::Domain(ref s) => s.size_of(ops),
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "servo")]
|
||||
malloc_size_of_is_0!(webrender_api::ClipAndScrollInfo);
|
||||
#[cfg(feature = "servo")]
|
||||
malloc_size_of_is_0!(webrender_api::ClipId);
|
||||
#[cfg(feature = "servo")]
|
||||
malloc_size_of_is_0!(webrender_api::ColorF);
|
||||
#[cfg(feature = "servo")]
|
||||
malloc_size_of_is_0!(webrender_api::GradientStop);
|
||||
#[cfg(feature = "servo")]
|
||||
malloc_size_of_is_0!(webrender_api::ImageKey);
|
||||
#[cfg(feature = "servo")]
|
||||
malloc_size_of_is_0!(webrender_api::LocalClip);
|
||||
#[cfg(feature = "servo")]
|
||||
malloc_size_of_is_0!(webrender_api::MixBlendMode);
|
||||
#[cfg(feature = "servo")]
|
||||
malloc_size_of_is_0!(webrender_api::RepeatMode);
|
||||
#[cfg(feature = "servo")]
|
||||
malloc_size_of_is_0!(webrender_api::ScrollPolicy);
|
||||
#[cfg(feature = "servo")]
|
||||
malloc_size_of_is_0!(webrender_api::ScrollSensitivity);
|
||||
#[cfg(feature = "servo")]
|
||||
malloc_size_of_is_0!(webrender_api::StickySideConstraint);
|
||||
#[cfg(feature = "servo")]
|
||||
malloc_size_of_is_0!(webrender_api::TransformStyle);
|
||||
|
||||
#[cfg(feature = "servo")]
|
||||
impl MallocSizeOf for xml5ever::QualName {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.prefix.size_of(ops) +
|
||||
self.ns.size_of(ops) +
|
||||
self.local.size_of(ops)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue