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:
Nicholas Nethercote 2017-10-18 10:42:01 +11:00
parent 421baa854e
commit 4506f0d30c
269 changed files with 1418 additions and 1521 deletions

View file

@ -11,7 +11,7 @@ use style::thread_state;
///
/// This extends the API of `std::cell::RefCell` to allow unsafe access in
/// certain situations, with dynamic checking in debug builds.
#[derive(Clone, Debug, Default, HeapSizeOf, PartialEq)]
#[derive(Clone, Debug, Default, MallocSizeOf, PartialEq)]
pub struct DomRefCell<T> {
value: RefCell<T>,
}

View file

@ -2029,7 +2029,7 @@ def DOMClass(descriptor):
# padding.
protoList.extend(['PrototypeList::ID::Last'] * (descriptor.config.maxProtoChainLength - len(protoList)))
prototypeChainString = ', '.join(protoList)
heapSizeOf = 'heap_size_of_raw_self_and_children::<%s>' % descriptor.concreteType
mallocSizeOf = 'malloc_size_of_including_raw_self::<%s>' % descriptor.concreteType
if descriptor.isGlobal():
globals_ = camel_to_upper_snake(descriptor.name)
else:
@ -2038,9 +2038,9 @@ def DOMClass(descriptor):
DOMClass {
interface_chain: [ %s ],
type_id: %s,
heap_size_of: %s as unsafe fn(_) -> _,
malloc_size_of: %s as unsafe fn(&mut _, _) -> _,
global: InterfaceObjectMap::%s,
}""" % (prototypeChainString, DOMClassTypeId(descriptor), heapSizeOf, globals_)
}""" % (prototypeChainString, DOMClassTypeId(descriptor), mallocSizeOf, globals_)
class CGDOMJSClass(CGThing):
@ -4005,7 +4005,7 @@ class CGEnum(CGThing):
ident = enum.identifier.name
decl = """\
#[repr(usize)]
#[derive(JSTraceable, PartialEq, Copy, Clone, HeapSizeOf, Debug)]
#[derive(Copy, Clone, Debug, JSTraceable, MallocSizeOf, PartialEq)]
pub enum %s {
%s
}
@ -5794,7 +5794,7 @@ def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries
'dom::bindings::weakref::WeakReferenceable',
'dom::windowproxy::WindowProxy',
'dom::globalscope::GlobalScope',
'mem::heap_size_of_raw_self_and_children',
'mem::malloc_size_of_including_raw_self',
'libc',
'servo_config::prefs::PREFS',
'std::borrow::ToOwned',

View file

@ -25,7 +25,7 @@ use libc::c_uint;
use std::slice::from_raw_parts;
/// DOM exceptions that can be thrown by a native DOM method.
#[derive(Clone, Debug, HeapSizeOf)]
#[derive(Clone, Debug, MallocSizeOf)]
pub enum Error {
/// IndexSizeError DOMException
IndexSize,

View file

@ -22,7 +22,7 @@ use std::cell::Cell;
use std::ptr;
/// The values that an iterator will iterate over.
#[derive(HeapSizeOf, JSTraceable)]
#[derive(JSTraceable, MallocSizeOf)]
pub enum IteratorType {
/// The keys of the iterable object.
Keys,

View file

@ -4,7 +4,7 @@
//! The `Finite<T>` struct.
use heapsize::HeapSizeOf;
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use num_traits::Float;
use std::default::Default;
use std::ops::Deref;
@ -41,9 +41,9 @@ impl<T: Float> Deref for Finite<T> {
}
}
impl<T: Float + HeapSizeOf> HeapSizeOf for Finite<T> {
fn heap_size_of_children(&self) -> usize {
(**self).heap_size_of_children()
impl<T: Float + MallocSizeOf> MallocSizeOf for Finite<T> {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
(**self).size_of(ops)
}
}

View file

@ -27,11 +27,11 @@ pub fn reflect_dom_object<T, U>(
/// A struct to store a reference to the reflector of a DOM object.
#[allow(unrooted_must_root)]
#[derive(HeapSizeOf)]
#[derive(MallocSizeOf)]
#[must_root]
// If you're renaming or moving this field, update the path in plugins::reflector as well
pub struct Reflector {
#[ignore_heap_size_of = "defined and measured in rust-mozjs"]
#[ignore_malloc_size_of = "defined and measured in rust-mozjs"]
object: Heap<*mut JSObject>,
}

View file

@ -30,9 +30,9 @@ use dom::bindings::reflector::{DomObject, Reflector};
use dom::bindings::trace::JSTraceable;
use dom::bindings::trace::trace_reflector;
use dom::node::Node;
use heapsize::HeapSizeOf;
use js::jsapi::{JSObject, JSTracer, Heap};
use js::rust::GCMethods;
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use mitochondria::OnceCell;
use nonzero::NonZero;
use script_layout_interface::TrustedNodeAddress;
@ -157,12 +157,12 @@ impl<T: DomObject> DomRoot<T> {
}
}
impl<T> HeapSizeOf for DomRoot<T>
impl<T> MallocSizeOf for DomRoot<T>
where
T: DomObject + HeapSizeOf,
T: DomObject + MallocSizeOf,
{
fn heap_size_of_children(&self) -> usize {
(**self).heap_size_of_children()
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
(**self).size_of(ops)
}
}
@ -317,8 +317,8 @@ pub struct Dom<T> {
// Dom<T> is similar to Rc<T>, in that it's not always clear how to avoid double-counting.
// For now, we choose not to follow any such pointers.
impl<T> HeapSizeOf for Dom<T> {
fn heap_size_of_children(&self) -> usize {
impl<T> MallocSizeOf for Dom<T> {
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
0
}
}
@ -516,9 +516,9 @@ impl<T: DomObject> MutDom<T> {
}
}
impl<T: DomObject> HeapSizeOf for MutDom<T> {
fn heap_size_of_children(&self) -> usize {
// See comment on HeapSizeOf for Dom<T>.
impl<T: DomObject> MallocSizeOf for MutDom<T> {
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
// See comment on MallocSizeOf for Dom<T>.
0
}
}
@ -635,9 +635,9 @@ impl<T: DomObject> Default for MutNullableDom<T> {
}
}
impl<T: DomObject> HeapSizeOf for MutNullableDom<T> {
fn heap_size_of_children(&self) -> usize {
// See comment on HeapSizeOf for Dom<T>.
impl<T: DomObject> MallocSizeOf for MutNullableDom<T> {
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
// See comment on MallocSizeOf for Dom<T>.
0
}
}
@ -678,9 +678,9 @@ impl<T: DomObject> Default for DomOnceCell<T> {
}
}
impl<T: DomObject> HeapSizeOf for DomOnceCell<T> {
fn heap_size_of_children(&self) -> usize {
// See comment on HeapSizeOf for Dom<T>.
impl<T: DomObject> MallocSizeOf for DomOnceCell<T> {
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
// See comment on MallocSizeOf for Dom<T>.
0
}
}

View file

@ -19,7 +19,7 @@ use std::str;
use std::str::{Bytes, FromStr};
/// Encapsulates the IDL `ByteString` type.
#[derive(Clone, Debug, Default, Eq, HeapSizeOf, JSTraceable, PartialEq)]
#[derive(Clone, Debug, Default, Eq, JSTraceable, MallocSizeOf, PartialEq)]
pub struct ByteString(Vec<u8>);
impl ByteString {
@ -78,7 +78,7 @@ impl ops::Deref for ByteString {
/// A string that is constructed from a UCS-2 buffer by replacing invalid code
/// points with the replacement character.
#[derive(Clone, Default, HeapSizeOf)]
#[derive(Clone, Default, MallocSizeOf)]
pub struct USVString(pub String);
@ -153,7 +153,7 @@ pub fn is_token(s: &[u8]) -> bool {
///
/// This type is currently `!Send`, in order to help with an independent
/// experiment to store `JSString`s rather than Rust `String`s.
#[derive(Clone, Debug, Eq, Hash, HeapSizeOf, Ord, PartialEq, PartialOrd)]
#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, Ord, PartialEq, PartialOrd)]
pub struct DOMString(String, PhantomData<*const ()>);
impl DOMString {

View file

@ -13,7 +13,6 @@ use dom::bindings::inheritance::TopTypeId;
use dom::bindings::str::DOMString;
use dom::bindings::trace::trace_object;
use dom::windowproxy;
use heapsize::HeapSizeOf;
use js;
use js::JS_CALLEE;
use js::glue::{CallJitGetterOp, CallJitMethodOp, CallJitSetterOp, IsWrapper};
@ -32,6 +31,7 @@ use js::jsapi::{JS_StringHasLatin1Chars, MutableHandleValue, ObjectOpResult};
use js::jsval::{JSVal, UndefinedValue};
use js::rust::{GCMethods, ToString, get_object_class, is_dom_class};
use libc;
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use std::ffi::CString;
use std::os::raw::{c_char, c_void};
use std::ptr;
@ -40,14 +40,14 @@ use std::slice;
/// Proxy handler for a WindowProxy.
pub struct WindowProxyHandler(pub *const libc::c_void);
impl HeapSizeOf for WindowProxyHandler {
fn heap_size_of_children(&self) -> usize {
impl MallocSizeOf for WindowProxyHandler {
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
// FIXME(#6907) this is a pointer to memory allocated by `new` in NewProxyHandler in rust-mozjs.
0
}
}
#[derive(HeapSizeOf, JSTraceable)]
#[derive(JSTraceable, MallocSizeOf)]
/// Static data associated with a global object.
pub struct GlobalStaticData {
/// The WindowProxy proxy handler for this global.
@ -88,8 +88,8 @@ pub struct DOMClass {
/// The type ID of that interface.
pub type_id: TopTypeId,
/// The HeapSizeOf function wrapper for that interface.
pub heap_size_of: unsafe fn(*const c_void) -> usize,
/// The MallocSizeOf function wrapper for that interface.
pub malloc_size_of: unsafe fn(ops: &mut MallocSizeOfOps, *const c_void) -> usize,
/// The `Globals` flag for this global interface, if any.
pub global: InterfaceObjectMap::Globals,

View file

@ -14,10 +14,10 @@
use dom::bindings::reflector::DomObject;
use dom::bindings::root::DomRoot;
use dom::bindings::trace::JSTraceable;
use heapsize::HeapSizeOf;
use js::jsapi::{JSTracer, JS_GetReservedSlot, JS_SetReservedSlot};
use js::jsval::PrivateValue;
use libc::c_void;
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use nonzero::NonZero;
use std::cell::{Cell, UnsafeCell};
use std::mem;
@ -110,8 +110,8 @@ impl<T: WeakReferenceable> Clone for WeakRef<T> {
}
}
impl<T: WeakReferenceable> HeapSizeOf for WeakRef<T> {
fn heap_size_of_children(&self) -> usize {
impl<T: WeakReferenceable> MallocSizeOf for WeakRef<T> {
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
0
}
}
@ -188,8 +188,8 @@ impl<T: WeakReferenceable> MutableWeakRef<T> {
}
}
impl<T: WeakReferenceable> HeapSizeOf for MutableWeakRef<T> {
fn heap_size_of_children(&self) -> usize {
impl<T: WeakReferenceable> MallocSizeOf for MutableWeakRef<T> {
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
0
}
}
@ -210,7 +210,7 @@ unsafe impl<T: WeakReferenceable> JSTraceable for MutableWeakRef<T> {
/// A vector of weak references. On tracing, the vector retains
/// only references which still point to live objects.
#[allow_unrooted_interior]
#[derive(HeapSizeOf)]
#[derive(MallocSizeOf)]
pub struct WeakRefVec<T: WeakReferenceable> {
vec: Vec<WeakRef<T>>,
}