diff options
author | Josh Matthews <josh@joshmatthews.net> | 2015-07-31 12:46:36 -0400 |
---|---|---|
committer | Josh Matthews <josh@joshmatthews.net> | 2015-08-03 23:05:00 -0400 |
commit | 8620fe599538effe755029e895fca6b9ca3b0f47 (patch) | |
tree | b7e1661271c4e358a7d003cf0b4837196ad198d0 | |
parent | c2497fcd49933f3782d529b891f4c8bb5de198c4 (diff) | |
download | servo-8620fe599538effe755029e895fca6b9ca3b0f47.tar.gz servo-8620fe599538effe755029e895fca6b9ca3b0f47.zip |
Start reporting memory usage for Window and all nodes in all DOM trees for frame treese in script tasks.
33 files changed, 317 insertions, 107 deletions
diff --git a/components/msg/Cargo.toml b/components/msg/Cargo.toml index edb799eee14..0575608d294 100644 --- a/components/msg/Cargo.toml +++ b/components/msg/Cargo.toml @@ -41,6 +41,9 @@ git = "https://github.com/pcwalton/ipc-channel" git = "https://github.com/ecoal95/rust-offscreen-rendering-context" features = ["texture_surface"] +[dependencies.plugins] +path = "../plugins" + [dependencies] bitflags = "0.3" rustc-serialize = "0.3.4" diff --git a/components/msg/constellation_msg.rs b/components/msg/constellation_msg.rs index 97d673deecb..286d0f71a2b 100644 --- a/components/msg/constellation_msg.rs +++ b/components/msg/constellation_msg.rs @@ -48,7 +48,7 @@ pub struct Failure { pub parent_info: Option<(PipelineId, SubpageId)>, } -#[derive(Copy, Clone, Deserialize, Serialize)] +#[derive(Copy, Clone, Deserialize, Serialize, HeapSizeOf)] pub struct WindowSizeData { /// The size of the initial layout viewport, before parsing an /// http://www.w3.org/TR/css-device-adapt/#initial-viewport @@ -386,13 +386,13 @@ pub enum NavigationDirection { #[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, Deserialize, Serialize)] pub struct FrameId(pub u32); -#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, Deserialize, Serialize)] +#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, Deserialize, Serialize, HeapSizeOf)] pub struct WorkerId(pub u32); -#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, Deserialize, Serialize)] +#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, Deserialize, Serialize, HeapSizeOf)] pub struct PipelineId(pub u32); -#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, Deserialize, Serialize)] +#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, Deserialize, Serialize, HeapSizeOf)] pub struct SubpageId(pub u32); // The type of pipeline exit. During complete shutdowns, pipelines do not have to diff --git a/components/msg/lib.rs b/components/msg/lib.rs index 4c2dd1f999b..7c03b73d591 100644 --- a/components/msg/lib.rs +++ b/components/msg/lib.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #![feature(custom_derive, plugin)] -#![plugin(serde_macros)] +#![plugin(serde_macros, plugins)] extern crate azure; #[macro_use] extern crate bitflags; diff --git a/components/script/document_loader.rs b/components/script/document_loader.rs index 56ee98bdbbf..9046f5cbbcf 100644 --- a/components/script/document_loader.rs +++ b/components/script/document_loader.rs @@ -12,7 +12,7 @@ use net_traits::AsyncResponseTarget; use std::sync::Arc; use url::Url; -#[derive(JSTraceable, PartialEq, Clone, Debug)] +#[derive(JSTraceable, PartialEq, Clone, Debug, HeapSizeOf)] pub enum LoadType { Image(Url), Script(Url), @@ -33,17 +33,19 @@ impl LoadType { } } -#[derive(JSTraceable)] +#[derive(JSTraceable, HeapSizeOf)] pub struct DocumentLoader { /// We use an `Arc<ResourceTask>` here in order to avoid file descriptor exhaustion when there /// are lots of iframes. + #[ignore_heap_size_of = "channels are hard"] pub resource_task: Arc<ResourceTask>, notifier_data: Option<NotifierData>, blocking_loads: Vec<LoadType>, } -#[derive(JSTraceable)] +#[derive(JSTraceable, HeapSizeOf)] pub struct NotifierData { + #[ignore_heap_size_of = "trait objects are hard"] pub script_chan: Box<ScriptChan + Send>, pub pipeline: PipelineId, } diff --git a/components/script/dom/bindings/cell.rs b/components/script/dom/bindings/cell.rs index 35b20d0a417..80bab8839bc 100644 --- a/components/script/dom/bindings/cell.rs +++ b/components/script/dom/bindings/cell.rs @@ -16,7 +16,7 @@ use std::cell::{BorrowState, RefCell, Ref, RefMut}; /// /// This extends the API of `core::cell::RefCell` to allow unsafe access in /// certain situations, with dynamic checking in debug builds. -#[derive(Clone)] +#[derive(Clone, HeapSizeOf)] pub struct DOMRefCell<T> { value: RefCell<T>, } diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index a46c58ff7c7..9bfaa0c9cfd 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -3314,7 +3314,7 @@ class CGEnum(CGThing): decl = """\ #[repr(usize)] -#[derive(JSTraceable, PartialEq, Copy, Clone)] +#[derive(JSTraceable, PartialEq, Copy, Clone, HeapSizeOf)] pub enum %s { %s } diff --git a/components/script/dom/bindings/js.rs b/components/script/dom/bindings/js.rs index fc929db1cac..0fde5678ab2 100644 --- a/components/script/dom/bindings/js.rs +++ b/components/script/dom/bindings/js.rs @@ -31,6 +31,7 @@ use js::jsapi::{JSObject, Heap, JSTracer}; use js::jsval::JSVal; use layout_interface::TrustedNodeAddress; use script_task::STACK_ROOTS; +use util::mem::HeapSizeOf; use core::nonzero::NonZero; use std::cell::{Cell, UnsafeCell}; @@ -44,6 +45,14 @@ pub struct JS<T> { ptr: NonZero<*const T> } +// JS<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 JS<T> { + fn heap_size_of_children(&self) -> usize { + 0 + } +} + impl<T> JS<T> { /// Returns `LayoutJS<T>` containing the same pointer. pub unsafe fn to_layout(self) -> LayoutJS<T> { @@ -226,7 +235,7 @@ impl<T: HeapGCValue+Copy> MutHeap<T> { /// place of traditional internal mutability to ensure that the proper GC /// barriers are enforced. #[must_root] -#[derive(JSTraceable)] +#[derive(JSTraceable, HeapSizeOf)] pub struct MutNullableHeap<T: HeapGCValue+Copy> { ptr: Cell<Option<T>> } diff --git a/components/script/dom/bindings/utils.rs b/components/script/dom/bindings/utils.rs index bacb6bc05ae..80db27bd894 100644 --- a/components/script/dom/bindings/utils.rs +++ b/components/script/dom/bindings/utils.rs @@ -16,6 +16,7 @@ use dom::bindings::js::Root; use dom::bindings::trace::trace_object; use dom::browsercontext; use dom::window; +use util::mem::HeapSizeOf; use util::str::DOMString; use libc; @@ -61,10 +62,18 @@ use js; use string_cache::{Atom, Namespace}; /// Proxy handler for a WindowProxy. +#[allow(raw_pointer_derive)] pub struct WindowProxyHandler(pub *const libc::c_void); +impl HeapSizeOf for WindowProxyHandler { + fn heap_size_of_children(&self) -> usize { + //FIXME(#6907) this is a pointer to memory allocated by `new` in NewProxyHandler in rust-mozjs. + 0 + } +} + #[allow(raw_pointer_derive)] -#[derive(JSTraceable)] +#[derive(JSTraceable, HeapSizeOf)] /// Static data associated with a global object. pub struct GlobalStaticData { /// The WindowProxy proxy handler for this global. @@ -416,8 +425,10 @@ pub fn reflect_dom_object<T: Reflectable> #[allow(raw_pointer_derive, unrooted_must_root)] #[must_root] #[servo_lang = "reflector"] +#[derive(HeapSizeOf)] // 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"] object: UnsafeCell<*mut JSObject>, } diff --git a/components/script/dom/browsercontext.rs b/components/script/dom/browsercontext.rs index cc4dc346c3f..8fe518844ba 100644 --- a/components/script/dom/browsercontext.rs +++ b/components/script/dom/browsercontext.rs @@ -27,7 +27,7 @@ use js::{JSTrue, JSFalse}; use std::ptr; use std::default::Default; -#[derive(JSTraceable)] +#[derive(JSTraceable, HeapSizeOf)] #[privatize] #[allow(raw_pointer_derive)] #[must_root] @@ -88,7 +88,7 @@ impl BrowsingContext { // without a reflector, so we don't mark this as #[dom_struct] #[must_root] #[privatize] -#[derive(JSTraceable)] +#[derive(JSTraceable, HeapSizeOf)] pub struct SessionHistoryEntry { document: JS<Document>, children: Vec<BrowsingContext> diff --git a/components/script/dom/characterdata.rs b/components/script/dom/characterdata.rs index 377a69b3d2d..f15b66c68f8 100644 --- a/components/script/dom/characterdata.rs +++ b/components/script/dom/characterdata.rs @@ -24,6 +24,7 @@ use std::cell::Ref; // https://dom.spec.whatwg.org/#characterdata #[dom_struct] +#[derive(HeapSizeOf)] pub struct CharacterData { node: Node, data: DOMRefCell<DOMString>, @@ -150,7 +151,7 @@ impl<'a> CharacterDataMethods for &'a CharacterData { } /// The different types of CharacterData. -#[derive(JSTraceable, Copy, Clone, PartialEq, Debug)] +#[derive(JSTraceable, Copy, Clone, PartialEq, Debug, HeapSizeOf)] pub enum CharacterDataTypeId { Comment, Text, diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index dd7dc90e0fe..5383ea6df33 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -110,6 +110,7 @@ pub enum IsHTMLDocument { // https://dom.spec.whatwg.org/#document #[dom_struct] +#[derive(HeapSizeOf)] pub struct Document { node: Node, window: JS<Window>, @@ -144,6 +145,7 @@ pub struct Document { animation_frame_ident: Cell<i32>, /// https://html.spec.whatwg.org/multipage/#list-of-animation-frame-callbacks /// List of animation frame callbacks + #[ignore_heap_size_of = "closures are hard"] animation_frame_list: RefCell<HashMap<i32, Box<Fn(f64)>>>, /// Tracks all outstanding loads related to this document. loader: DOMRefCell<DocumentLoader>, diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 046b9a57c5f..1b200ed4e61 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -120,7 +120,7 @@ impl PartialEq for Element { } } -#[derive(JSTraceable, Copy, Clone, PartialEq, Debug)] +#[derive(JSTraceable, Copy, Clone, PartialEq, Debug, HeapSizeOf)] pub enum ElementTypeId { HTMLElement(HTMLElementTypeId), Element, diff --git a/components/script/dom/eventtarget.rs b/components/script/dom/eventtarget.rs index dfeae4ff08f..79679ff14d2 100644 --- a/components/script/dom/eventtarget.rs +++ b/components/script/dom/eventtarget.rs @@ -20,6 +20,7 @@ use js::jsapi::{CompileFunction, JS_GetFunctionObject}; use js::jsapi::{JSContext, RootedFunction, HandleObject}; use js::jsapi::{JSAutoCompartment, JSAutoRequest}; use js::rust::{AutoObjectVectorWrapper, CompileOptionsWrapper}; +use util::mem::HeapSizeOf; use util::str::DOMString; use fnv::FnvHasher; @@ -36,13 +37,14 @@ use url::Url; use std::collections::HashMap; -#[derive(JSTraceable, Copy, Clone, PartialEq)] +#[derive(JSTraceable, Copy, Clone, PartialEq, HeapSizeOf)] pub enum ListenerPhase { Capturing, Bubbling, } #[derive(JSTraceable, Copy, Clone)] +#[derive(HeapSizeOf)] pub enum EventTargetTypeId { Node(NodeTypeId), WebSocket, @@ -95,6 +97,13 @@ pub enum EventListenerType { Inline(Rc<EventListener>), } +impl HeapSizeOf for EventListenerType { + fn heap_size_of_children(&self) -> usize { + // FIXME: Rc<T> isn't HeapSizeOf and we can't ignore it due to #6870 and #6871 + 0 + } +} + impl EventListenerType { fn get_listener(&self) -> Rc<EventListener> { match *self { @@ -104,7 +113,7 @@ impl EventListenerType { } } -#[derive(JSTraceable, Clone, PartialEq)] +#[derive(JSTraceable, Clone, PartialEq, HeapSizeOf)] #[privatize] pub struct EventListenerEntry { phase: ListenerPhase, @@ -112,6 +121,7 @@ pub struct EventListenerEntry { } #[dom_struct] +#[derive(HeapSizeOf)] pub struct EventTarget { reflector_: Reflector, type_id: EventTargetTypeId, diff --git a/components/script/dom/htmlelement.rs b/components/script/dom/htmlelement.rs index 376bec890cc..2a196073513 100644 --- a/components/script/dom/htmlelement.rs +++ b/components/script/dom/htmlelement.rs @@ -366,7 +366,7 @@ impl<'a> VirtualMethods for &'a HTMLElement { } } -#[derive(JSTraceable, Copy, Clone, Debug)] +#[derive(JSTraceable, Copy, Clone, Debug, HeapSizeOf)] pub enum HTMLElementTypeId { HTMLElement, diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs index b0b3ae9c6e9..847132c6452 100644 --- a/components/script/dom/htmlmediaelement.rs +++ b/components/script/dom/htmlmediaelement.rs @@ -41,7 +41,7 @@ impl HTMLMediaElement { } } -#[derive(JSTraceable, Copy, Clone, Debug)] +#[derive(JSTraceable, Copy, Clone, Debug, HeapSizeOf)] pub enum HTMLMediaElementTypeId { HTMLAudioElement = 0, HTMLVideoElement = 1, diff --git a/components/script/dom/htmltablecellelement.rs b/components/script/dom/htmltablecellelement.rs index 66359deb22f..873cbb184e8 100644 --- a/components/script/dom/htmltablecellelement.rs +++ b/components/script/dom/htmltablecellelement.rs @@ -22,7 +22,7 @@ use std::cmp::max; const DEFAULT_COLSPAN: u32 = 1; -#[derive(JSTraceable, Copy, Clone, Debug)] +#[derive(JSTraceable, Copy, Clone, Debug, HeapSizeOf)] pub enum HTMLTableCellElementTypeId { HTMLTableDataCellElement = 0, HTMLTableHeaderCellElement = 1, diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index 1f6a681e582..94a0a1e05c0 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -78,6 +78,7 @@ use string_cache::{Atom, Namespace, QualName}; /// An HTML node. #[dom_struct] +#[derive(HeapSizeOf)] pub struct Node { /// The JavaScript reflector for this node. eventtarget: EventTarget, @@ -135,7 +136,7 @@ impl NodeDerived for EventTarget { bitflags! { #[doc = "Flags for node items."] - #[derive(JSTraceable)] + #[derive(JSTraceable, HeapSizeOf)] flags NodeFlags: u16 { #[doc = "Specifies whether this node is in a document."] const IS_IN_DOC = 0x01, @@ -206,20 +207,25 @@ enum SuppressObserver { } /// Layout data that is shared between the script and layout tasks. +#[derive(HeapSizeOf)] pub struct SharedLayoutData { /// The results of CSS styling for this node. pub style: Option<Arc<ComputedValues>>, } /// Encapsulates the abstract layout data. +#[allow(raw_pointer_derive)] +#[derive(HeapSizeOf)] pub struct LayoutData { _shared_data: SharedLayoutData, + #[ignore_heap_size_of = "TODO(#6910) Box value that should be counted but the type lives in layout"] _data: NonZero<*const ()>, } #[allow(unsafe_code)] unsafe impl Send for LayoutData {} +#[derive(HeapSizeOf)] pub struct LayoutDataRef { data_cell: RefCell<Option<LayoutData>>, } @@ -274,6 +280,7 @@ impl LayoutDataRef { /// The different types of nodes. #[derive(JSTraceable, Copy, Clone, PartialEq, Debug)] +#[derive(HeapSizeOf)] pub enum NodeTypeId { CharacterData(CharacterDataTypeId), DocumentType, diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index af6f719f729..ba86c85b3ac 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -8,7 +8,7 @@ use dom::bindings::codegen::Bindings::EventHandlerBinding::{OnErrorEventHandlerN use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods; use dom::bindings::codegen::Bindings::FunctionBinding::Function; use dom::bindings::codegen::Bindings::WindowBinding::{self, WindowMethods, FrameRequestCallback}; -use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast, EventTargetCast}; +use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast, EventTargetCast, WindowDerived}; use dom::bindings::global::global_object_for_js_object; use dom::bindings::error::{report_pending_exception, Fallible}; use dom::bindings::error::Error::InvalidCharacter; @@ -81,7 +81,7 @@ use std::sync::mpsc::{channel, Receiver}; use time; /// Current state of the window object -#[derive(JSTraceable, Copy, Clone, Debug, PartialEq)] +#[derive(JSTraceable, Copy, Clone, Debug, PartialEq, HeapSizeOf)] enum WindowState { Alive, Zombie, // Pipeline is closed, but the window hasn't been GCed yet. @@ -106,15 +106,21 @@ pub enum ReflowReason { } #[dom_struct] +#[derive(HeapSizeOf)] pub struct Window { eventtarget: EventTarget, + #[ignore_heap_size_of = "trait objects are hard"] script_chan: Box<ScriptChan+Send>, + #[ignore_heap_size_of = "channels are hard"] control_chan: ScriptControlChan, console: MutNullableHeap<JS<Console>>, crypto: MutNullableHeap<JS<Crypto>>, navigator: MutNullableHeap<JS<Navigator>>, + #[ignore_heap_size_of = "channels are hard"] image_cache_task: ImageCacheTask, + #[ignore_heap_size_of = "channels are hard"] image_cache_chan: ImageCacheChan, + #[ignore_heap_size_of = "TODO(#6911) newtypes containing unmeasurable types are hard"] compositor: DOMRefCell<ScriptListener>, browsing_context: DOMRefCell<Option<BrowsingContext>>, page: Rc<Page>, @@ -129,13 +135,17 @@ pub struct Window { next_worker_id: Cell<WorkerId>, /// For sending messages to the memory profiler. + #[ignore_heap_size_of = "channels are hard"] mem_profiler_chan: mem::ProfilerChan, /// For providing instructions to an optional devtools server. + #[ignore_heap_size_of = "channels are hard"] devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>, /// For sending timeline markers. Will be ignored if /// no devtools server + #[ignore_heap_size_of = "TODO(#6909) need to measure HashSet"] devtools_markers: RefCell<HashSet<TimelineMarkerType>>, + #[ignore_heap_size_of = "channels are hard"] devtools_marker_sender: RefCell<Option<IpcSender<TimelineMarker>>>, /// A flag to indicate whether the developer tools have requested live updates of @@ -160,27 +170,34 @@ pub struct Window { dom_static: GlobalStaticData, /// The JavaScript runtime. + #[ignore_heap_size_of = "Rc<T> is hard"] js_runtime: DOMRefCell<Option<Rc<Runtime>>>, /// A handle for communicating messages to the layout task. + #[ignore_heap_size_of = "channels are hard"] layout_chan: LayoutChan, /// A handle to perform RPC calls into the layout, quickly. + #[ignore_heap_size_of = "trait objects are hard"] layout_rpc: Box<LayoutRPC+'static>, /// The port that we will use to join layout. If this is `None`, then layout is not running. + #[ignore_heap_size_of = "channels are hard"] layout_join_port: DOMRefCell<Option<Receiver<()>>>, /// The current size of the window, in pixels. window_size: Cell<Option<WindowSizeData>>, /// Associated resource task for use by DOM objects like XMLHttpRequest + #[ignore_heap_size_of = "channels are hard"] resource_task: Arc<ResourceTask>, /// A handle for communicating messages to the storage task. + #[ignore_heap_size_of = "channels are hard"] storage_task: StorageTask, /// A handle for communicating messages to the constellation task. + #[ignore_heap_size_of = "channels are hard"] constellation_chan: ConstellationChan, /// Pending scroll to fragment event, if any @@ -194,6 +211,7 @@ pub struct Window { pending_reflow_count: Cell<u32>, /// A channel for communicating results of async scripts back to the webdriver server + #[ignore_heap_size_of = "channels are hard"] webdriver_script_chan: RefCell<Option<IpcSender<WebDriverJSResult>>>, /// The current state of the window object @@ -1182,3 +1200,9 @@ fn debug_reflow_events(goal: &ReflowGoal, query_type: &ReflowQueryType, reason: println!("{}", debug_msg); } + +impl WindowDerived for EventTarget { + fn is_window(&self) -> bool { + self.type_id() == &EventTargetTypeId::Window + } +} diff --git a/components/script/dom/workerglobalscope.rs b/components/script/dom/workerglobalscope.rs index 91d140dc823..550834f7d09 100644 --- a/components/script/dom/workerglobalscope.rs +++ b/components/script/dom/workerglobalscope.rs @@ -37,7 +37,7 @@ use std::cell::Cell; use std::rc::Rc; use std::sync::mpsc::Receiver; -#[derive(JSTraceable, Copy, Clone, PartialEq)] +#[derive(JSTraceable, Copy, Clone, PartialEq, HeapSizeOf)] pub enum WorkerGlobalScopeTypeId { DedicatedGlobalScope, } diff --git a/components/script/dom/xmlhttprequesteventtarget.rs b/components/script/dom/xmlhttprequesteventtarget.rs index 8c17d3c8b1a..6b50898ab27 100644 --- a/components/script/dom/xmlhttprequesteventtarget.rs +++ b/components/script/dom/xmlhttprequesteventtarget.rs @@ -8,7 +8,7 @@ use dom::bindings::codegen::InheritTypes::EventTargetCast; use dom::bindings::codegen::InheritTypes::XMLHttpRequestEventTargetDerived; use dom::eventtarget::{EventTarget, EventTargetHelpers, EventTargetTypeId}; -#[derive(JSTraceable, Copy, Clone, PartialEq)] +#[derive(JSTraceable, Copy, Clone, PartialEq, HeapSizeOf)] pub enum XMLHttpRequestEventTargetTypeId { XMLHttpRequest, XMLHttpRequestUpload, diff --git a/components/script/lib.rs b/components/script/lib.rs index 47dadf0d956..8fc23dc78b4 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -84,6 +84,7 @@ pub mod dom; pub mod parse; pub mod layout_interface; +mod mem; mod network_listener; pub mod page; pub mod script_task; diff --git a/components/script/mem.rs b/components/script/mem.rs new file mode 100644 index 00000000000..6dbd45e5b8a --- /dev/null +++ b/components/script/mem.rs @@ -0,0 +1,36 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//! Routines for handling measuring the memory usage of arbitrary DOM nodes. + +use dom::bindings::codegen::InheritTypes::{DocumentCast, WindowCast, CharacterDataCast, NodeCast}; +use dom::eventtarget::{EventTarget, EventTargetTypeId}; +use dom::node::NodeTypeId; +use libc; +use util::mem::{HeapSizeOf, heap_size_of}; + +// This is equivalent to measuring a Box<T>, except that DOM objects lose their +// associated box in order to stash their pointers in a reserved slot of their +// JS reflector. It is assumed that the caller passes a pointer to the most-derived +// type that this pointer represents, or the actual heap usage of the pointee will +// be under-reported. +fn heap_size_of_self_and_children<T: HeapSizeOf>(obj: &T) -> usize { + heap_size_of(obj as *const T as *const libc::c_void) + obj.heap_size_of_children() +} + +pub fn heap_size_of_eventtarget(target: &EventTarget) -> usize { + //TODO: add more specific matches for concrete element types as derive(HeapSizeOf) is + // added to each one. + match target.type_id() { + &EventTargetTypeId::Window => + heap_size_of_self_and_children(WindowCast::to_ref(target).unwrap()), + &EventTargetTypeId::Node(NodeTypeId::CharacterData(_)) => + heap_size_of_self_and_children(CharacterDataCast::to_ref(target).unwrap()), + &EventTargetTypeId::Node(NodeTypeId::Document) => + heap_size_of_self_and_children(DocumentCast::to_ref(target).unwrap()), + &EventTargetTypeId::Node(_) => + heap_size_of_self_and_children(NodeCast::to_ref(target).unwrap()), + _ => 0, + } +} diff --git a/components/script/page.rs b/components/script/page.rs index 1286a1427f1..f4b3fd6cd18 100644 --- a/components/script/page.rs +++ b/components/script/page.rs @@ -13,7 +13,7 @@ use std::cell::Cell; use std::rc::Rc; /// Encapsulates a handle to a frame in a frame tree. -#[derive(JSTraceable)] +#[derive(JSTraceable, HeapSizeOf)] #[allow(unrooted_must_root)] // FIXME(#6687) this is wrong pub struct Page { /// Pipeline id associated with this page. @@ -127,7 +127,7 @@ impl Page { } /// Information for one frame in the browsing context. -#[derive(JSTraceable)] +#[derive(JSTraceable, HeapSizeOf)] #[must_root] pub struct Frame { /// The document for this frame. diff --git a/components/script/script_task.rs b/components/script/script_task.rs index 279ff364bda..b3ea5b16818 100644 --- a/components/script/script_task.rs +++ b/components/script/script_task.rs @@ -46,6 +46,7 @@ use dom::worker::TrustedWorkerAddress; use parse::html::{ParseContext, parse_html}; use layout_interface::{self, NewLayoutTaskInfo, ScriptLayoutChan, LayoutChan, ReflowGoal}; use layout_interface::{ReflowQueryType}; +use mem::heap_size_of_eventtarget; use network_listener::NetworkListener; use page::{Page, IterablePage, Frame}; use timers::TimerId; @@ -1104,11 +1105,28 @@ impl ScriptTask { fn collect_reports(&self, reports_chan: ReportsChan) { let mut urls = vec![]; + let mut dom_tree_size = 0; + let mut reports = vec![]; for it_page in self.root_page().iter() { - urls.push(it_page.document().url().serialize()); + let current_url = it_page.document().url().serialize(); + urls.push(current_url.clone()); + + for child in NodeCast::from_ref(&*it_page.document()).traverse_preorder() { + let target = EventTargetCast::from_ref(&*child); + dom_tree_size += heap_size_of_eventtarget(target); + } + let window = it_page.window(); + let target = EventTargetCast::from_ref(&*window); + dom_tree_size += heap_size_of_eventtarget(target); + + reports.push(Report { + path: path![format!("url({})", current_url), "dom-tree"], + kind: ReportKind::ExplicitJemallocHeapSize, + size: dom_tree_size, + }) } let path_seg = format!("url({})", urls.join(", ")); - let reports = ScriptTask::get_reports(self.get_cx(), path_seg); + reports.extend(ScriptTask::get_reports(self.get_cx(), path_seg)); reports_chan.send(reports); } diff --git a/components/script/timers.rs b/components/script/timers.rs index 0a0a37e0a7a..ac7142914ad 100644 --- a/components/script/timers.rs +++ b/components/script/timers.rs @@ -13,6 +13,7 @@ use dom::window::ScriptHelpers; use script_task::{ScriptChan, ScriptMsg, TimerSource}; use horribly_inefficient_timers; +use util::mem::HeapSizeOf; use util::task::spawn_named; use util::str::DOMString; @@ -29,14 +30,15 @@ use std::hash::{Hash, Hasher}; use std::rc::Rc; use std::default::Default; -#[derive(JSTraceable, PartialEq, Eq, Copy, Clone)] +#[derive(JSTraceable, PartialEq, Eq, Copy, Clone, HeapSizeOf)] pub struct TimerId(i32); -#[derive(JSTraceable)] +#[derive(JSTraceable, HeapSizeOf)] #[privatize] struct TimerHandle { handle: TimerId, data: TimerData, + #[ignore_heap_size_of = "channels are hard"] control_chan: Option<Sender<TimerControlMsg>>, } @@ -46,6 +48,13 @@ pub enum TimerCallback { FunctionTimerCallback(Rc<Function>) } +impl HeapSizeOf for TimerCallback { + fn heap_size_of_children(&self) -> usize { + // FIXME: Rc<T> isn't HeapSizeOf and we can't ignore it due to #6870 and #6871 + 0 + } +} + impl Hash for TimerId { fn hash<H: Hasher>(&self, state: &mut H) { let TimerId(id) = *self; @@ -65,7 +74,7 @@ impl TimerHandle { } } -#[derive(JSTraceable)] +#[derive(JSTraceable, HeapSizeOf)] #[privatize] pub struct TimerManager { active_timers: DOMRefCell<HashMap<TimerId, TimerHandle>>, @@ -82,7 +91,7 @@ impl Drop for TimerManager { } // Enum allowing more descriptive values for the is_interval field -#[derive(JSTraceable, PartialEq, Copy, Clone)] +#[derive(JSTraceable, PartialEq, Copy, Clone, HeapSizeOf)] pub enum IsInterval { Interval, NonInterval, @@ -100,7 +109,7 @@ pub enum TimerControlMsg { // (ie. function value to invoke and all arguments to pass // to the function when calling it) // TODO: Handle rooting during fire_timer when movable GC is turned on -#[derive(JSTraceable)] +#[derive(JSTraceable, HeapSizeOf)] #[privatize] struct TimerData { is_interval: IsInterval, diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index 14f8284ed3e..9c4efbdb167 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -872,6 +872,7 @@ dependencies = [ "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)", "offscreen_gl_context 0.1.0 (git+https://github.com/ecoal95/rust-offscreen-rendering-context)", + "plugins 0.0.1", "png 0.1.0 (git+https://github.com/servo/rust-png)", "rustc-serialize 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1502,7 +1503,10 @@ dependencies = [ "bitflags 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "cssparser 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "html5ever 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", + "js 0.1.0 (git+https://github.com/servo/rust-mozjs)", + "layers 0.1.0 (git+https://github.com/servo/rust-layers)", "lazy_static 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1514,6 +1518,7 @@ dependencies = [ "serde 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde_macros 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/components/style/properties.mako.rs b/components/style/properties.mako.rs index 4010f46307f..36c2787dc76 100644 --- a/components/style/properties.mako.rs +++ b/components/style/properties.mako.rs @@ -486,7 +486,7 @@ pub mod longhands { use cssparser::ToCss; use std::fmt; - #[derive(PartialEq, Clone, Eq, Copy, Debug)] + #[derive(PartialEq, Clone, Eq, Copy, Debug, HeapSizeOf)] pub enum T { Auto, Number(i32), @@ -604,7 +604,7 @@ pub mod longhands { use values::CSSFloat; use util::geometry::Au; use std::fmt; - #[derive(PartialEq, Copy, Clone)] + #[derive(PartialEq, Copy, Clone, HeapSizeOf)] pub enum T { Normal, Length(Au), @@ -704,7 +704,7 @@ pub mod longhands { use util::geometry::Au; use std::fmt; #[allow(non_camel_case_types)] - #[derive(PartialEq, Copy, Clone)] + #[derive(PartialEq, Copy, Clone, HeapSizeOf)] pub enum T { % for keyword in vertical_align_keywords: ${to_rust_ident(keyword)}, @@ -812,7 +812,7 @@ pub mod longhands { } pub mod computed_value { - #[derive(Clone, Copy, PartialEq)] + #[derive(Clone, Copy, PartialEq, HeapSizeOf)] pub struct T(pub super::super::overflow_x::computed_value::T); } @@ -865,7 +865,7 @@ pub mod longhands { use cssparser::{self, ToCss}; use std::fmt; - #[derive(PartialEq, Eq, Clone)] + #[derive(PartialEq, Eq, Clone, HeapSizeOf)] pub enum ContentItem { /// Literal string content. String(String), @@ -914,7 +914,7 @@ pub mod longhands { } #[allow(non_camel_case_types)] - #[derive(PartialEq, Eq, Clone)] + #[derive(PartialEq, Eq, Clone, HeapSizeOf)] pub enum T { normal, none, @@ -1055,7 +1055,7 @@ pub mod longhands { use cssparser::{ToCss, Token}; use std::fmt; - #[derive(Clone, PartialEq)] + #[derive(Clone, PartialEq, HeapSizeOf)] pub struct T(pub Option<Url>); impl ToCss for T { @@ -1103,7 +1103,7 @@ pub mod longhands { pub use self::computed_value::T as SpecifiedValue; pub mod computed_value { - #[derive(Clone, PartialEq)] + #[derive(Clone, PartialEq, HeapSizeOf)] pub struct T(pub Vec<(String,String)>); } @@ -1172,7 +1172,7 @@ pub mod longhands { pub use self::computed_value::T as SpecifiedValue; pub mod computed_value { - #[derive(Clone, PartialEq)] + #[derive(Clone, PartialEq, HeapSizeOf)] pub struct T(pub Vec<(String,i32)>); } @@ -1247,7 +1247,7 @@ pub mod longhands { pub mod computed_value { use values::computed; - #[derive(Clone, PartialEq)] + #[derive(Clone, PartialEq, HeapSizeOf)] pub struct T(pub Option<computed::Image>); } @@ -1308,7 +1308,7 @@ pub mod longhands { pub mod computed_value { use values::computed::LengthOrPercentage; - #[derive(PartialEq, Copy, Clone, Debug)] + #[derive(PartialEq, Copy, Clone, Debug, HeapSizeOf)] pub struct T { pub horizontal: LengthOrPercentage, pub vertical: LengthOrPercentage, @@ -1431,13 +1431,13 @@ pub mod longhands { pub mod computed_value { use values::computed::LengthOrPercentageOrAuto; - #[derive(PartialEq, Clone, Debug)] + #[derive(PartialEq, Clone, Debug, HeapSizeOf)] pub struct ExplicitSize { pub width: LengthOrPercentageOrAuto, pub height: LengthOrPercentageOrAuto, } - #[derive(PartialEq, Clone, Debug)] + #[derive(PartialEq, Clone, Debug, HeapSizeOf)] pub enum T { Explicit(ExplicitSize), Cover, @@ -1613,7 +1613,7 @@ pub mod longhands { use string_cache::Atom; use std::fmt; - #[derive(PartialEq, Eq, Clone, Hash)] + #[derive(PartialEq, Eq, Clone, Hash, HeapSizeOf)] pub enum FontFamily { FamilyName(Atom), // Generic @@ -1649,7 +1649,7 @@ pub mod longhands { Ok(()) } } - #[derive(Clone, PartialEq, Eq, Hash)] + #[derive(Clone, PartialEq, Eq, Hash, HeapSizeOf)] pub struct T(pub Vec<FontFamily>); } @@ -1741,7 +1741,7 @@ pub mod longhands { } pub mod computed_value { use std::fmt; - #[derive(PartialEq, Eq, Copy, Clone, Hash, Deserialize, Serialize)] + #[derive(PartialEq, Eq, Copy, Clone, Hash, Deserialize, Serialize, HeapSizeOf)] pub enum T { % for weight in range(100, 901, 100): Weight${weight} = ${weight}, @@ -1958,7 +1958,7 @@ pub mod longhands { pub mod computed_value { use util::geometry::Au; - #[derive(Clone, PartialEq)] + #[derive(Clone, PartialEq, HeapSizeOf)] pub struct T(pub Option<Au>); } @@ -2020,7 +2020,7 @@ pub mod longhands { pub mod computed_value { use util::geometry::Au; - #[derive(Clone, PartialEq)] + #[derive(Clone, PartialEq, HeapSizeOf)] pub struct T(pub Option<Au>); } @@ -2085,7 +2085,7 @@ pub mod longhands { impl ComputedValueAsSpecified for SpecifiedValue {} - #[derive(PartialEq, Eq, Copy, Clone, Debug)] + #[derive(PartialEq, Eq, Copy, Clone, Debug, HeapSizeOf)] pub struct SpecifiedValue { pub underline: bool, pub overline: bool, @@ -2178,7 +2178,7 @@ pub mod longhands { impl ComputedValueAsSpecified for SpecifiedValue {} - #[derive(Clone, PartialEq, Copy, Debug)] + #[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)] pub struct SpecifiedValue { pub underline: Option<RGBA>, pub overline: Option<RGBA>, @@ -2286,7 +2286,7 @@ pub mod longhands { pub mod computed_value { use util::geometry::Au; - #[derive(Clone, Copy, Debug, PartialEq, RustcEncodable)] + #[derive(Clone, Copy, Debug, PartialEq, RustcEncodable, HeapSizeOf)] pub struct T { pub horizontal: Au, pub vertical: Au, @@ -2398,7 +2398,7 @@ pub mod longhands { use std::fmt; use util::cursor::Cursor; - #[derive(Clone, PartialEq, Eq, Copy, Debug)] + #[derive(Clone, PartialEq, Eq, Copy, Debug, HeapSizeOf)] pub enum T { AutoCursor, SpecifiedCursor(Cursor), @@ -2460,7 +2460,7 @@ pub mod longhands { pub mod computed_value { use util::geometry::Au; - #[derive(Clone, PartialEq)] + #[derive(Clone, PartialEq, HeapSizeOf)] pub struct T(pub Option<Au>); } @@ -2521,7 +2521,7 @@ pub mod longhands { } pub mod computed_value { - #[derive(Clone, PartialEq)] + #[derive(Clone, PartialEq, HeapSizeOf)] pub struct T(pub Option<u32>); } @@ -2588,7 +2588,7 @@ pub mod longhands { pub mod computed_value { use util::geometry::Au; - #[derive(Clone, PartialEq)] + #[derive(Clone, PartialEq, HeapSizeOf)] pub struct T(pub Option<Au>); } @@ -2734,10 +2734,10 @@ pub mod longhands { use values::computed; use std::fmt; - #[derive(Clone, PartialEq)] + #[derive(Clone, PartialEq, HeapSizeOf)] pub struct T(pub Vec<BoxShadow>); - #[derive(Clone, PartialEq, Copy)] + #[derive(Clone, PartialEq, Copy, HeapSizeOf)] pub struct BoxShadow { pub offset_x: Au, pub offset_y: Au, @@ -2903,7 +2903,7 @@ pub mod longhands { pub mod computed_value { use util::geometry::Au; - #[derive(Clone, PartialEq, Eq, Copy, Debug)] + #[derive(Clone, PartialEq, Eq, Copy, Debug, HeapSizeOf)] pub struct ClipRect { pub top: Au, pub right: Option<Au>, @@ -2911,7 +2911,7 @@ pub mod longhands { pub left: Au, } - #[derive(Clone, PartialEq)] + #[derive(Clone, PartialEq, HeapSizeOf)] pub struct T(pub Option<ClipRect>); } @@ -3081,10 +3081,10 @@ pub mod longhands { use cssparser::Color; use util::geometry::Au; - #[derive(Clone, PartialEq, Debug)] + #[derive(Clone, PartialEq, Debug, HeapSizeOf)] pub struct T(pub Vec<TextShadow>); - #[derive(Clone, PartialEq, Debug)] + #[derive(Clone, PartialEq, Debug, HeapSizeOf)] pub struct TextShadow { pub offset_x: Au, pub offset_y: Au, @@ -3484,7 +3484,7 @@ pub mod longhands { use values::CSSFloat; use values::computed; - #[derive(Clone, Copy, Debug, PartialEq)] + #[derive(Clone, Copy, Debug, PartialEq, HeapSizeOf)] pub struct ComputedMatrix { pub m11: CSSFloat, pub m12: CSSFloat, pub m13: CSSFloat, pub m14: CSSFloat, pub m21: CSSFloat, pub m22: CSSFloat, pub m23: CSSFloat, pub m24: CSSFloat, @@ -3503,7 +3503,7 @@ pub mod longhands { } } - #[derive(Clone, Debug, PartialEq)] + #[derive(Clone, Debug, PartialEq, HeapSizeOf)] pub enum ComputedOperation { Matrix(ComputedMatrix), Skew(CSSFloat, CSSFloat), @@ -3515,7 +3515,7 @@ pub mod longhands { Perspective(computed::Length), } - #[derive(Clone, Debug, PartialEq)] + #[derive(Clone, Debug, PartialEq, HeapSizeOf)] pub struct T(pub Option<Vec<ComputedOperation>>); } @@ -3934,7 +3934,7 @@ pub mod longhands { pub mod computed_value { use values::computed::{Length, LengthOrPercentage}; - #[derive(Clone, Copy, Debug, PartialEq)] + #[derive(Clone, Copy, Debug, PartialEq, HeapSizeOf)] pub struct T { pub horizontal: LengthOrPercentage, pub vertical: LengthOrPercentage, @@ -4082,7 +4082,7 @@ pub mod longhands { pub mod computed_value { use values::computed::LengthOrPercentage; - #[derive(Clone, Copy, Debug, PartialEq)] + #[derive(Clone, Copy, Debug, PartialEq, HeapSizeOf)] pub struct T { pub horizontal: LengthOrPercentage, pub vertical: LengthOrPercentage, @@ -4275,7 +4275,7 @@ pub mod longhands { pub use values::computed::Time as SingleComputedValue; - #[derive(Clone, PartialEq)] + #[derive(Clone, PartialEq, HeapSizeOf)] pub struct T(pub Vec<SingleComputedValue>); impl ToComputedValue for T { @@ -4382,7 +4382,7 @@ pub mod longhands { pub use self::TransitionTimingFunction as SingleComputedValue; - #[derive(Copy, Clone, Debug, PartialEq)] + #[derive(Copy, Clone, Debug, PartialEq, HeapSizeOf)] pub enum TransitionTimingFunction { CubicBezier(Point2D<f32>, Point2D<f32>), Steps(u32, StartEnd), @@ -4413,7 +4413,7 @@ pub mod longhands { } } - #[derive(Copy, Clone, Debug, PartialEq)] + #[derive(Copy, Clone, Debug, PartialEq, HeapSizeOf)] pub enum StartEnd { Start, End, @@ -4428,7 +4428,7 @@ pub mod longhands { } } - #[derive(Clone, Debug, PartialEq)] + #[derive(Clone, Debug, PartialEq, HeapSizeOf)] pub struct T(pub Vec<TransitionTimingFunction>); impl ToCss for T { @@ -4535,7 +4535,7 @@ pub mod longhands { pub use self::TransitionProperty as SingleComputedValue; - #[derive(Copy, Clone, Debug, PartialEq)] + #[derive(Copy, Clone, Debug, PartialEq, HeapSizeOf)] pub enum TransitionProperty { All, BackgroundColor, @@ -4686,7 +4686,7 @@ pub mod longhands { } } - #[derive(Clone, Debug, PartialEq)] + #[derive(Clone, Debug, PartialEq, HeapSizeOf)] pub struct T(pub Vec<SingleComputedValue>); impl ToCss for T { @@ -5781,7 +5781,7 @@ pub mod style_structs { use super::longhands; % for style_struct in STYLE_STRUCTS: - #[derive(PartialEq, Clone)] + #[derive(PartialEq, Clone, HeapSizeOf)] pub struct ${style_struct.name} { % for longhand in style_struct.longhands: pub ${longhand.ident}: longhands::${longhand.ident}::computed_value::T, @@ -5793,7 +5793,7 @@ pub mod style_structs { % endfor } -#[derive(Clone)] +#[derive(Clone, HeapSizeOf)] pub struct ComputedValues { % for style_struct in STYLE_STRUCTS: ${style_struct.ident}: Arc<style_structs::${style_struct.name}>, diff --git a/components/style/values.rs b/components/style/values.rs index 03167b3fd36..da542f812fe 100644 --- a/components/style/values.rs +++ b/components/style/values.rs @@ -103,7 +103,7 @@ pub mod specified { } } - #[derive(Clone, PartialEq, Debug)] + #[derive(Clone, PartialEq, Debug, HeapSizeOf)] pub struct CSSColor { pub parsed: cssparser::Color, pub authored: Option<String>, @@ -147,7 +147,7 @@ pub mod specified { } } - #[derive(Clone, PartialEq, Copy, Debug)] + #[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)] pub enum FontRelativeLength { Em(CSSFloat), Ex(CSSFloat), @@ -181,7 +181,7 @@ pub mod specified { } } - #[derive(Clone, PartialEq, Copy, Debug)] + #[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)] pub enum ViewportPercentageLength { Vw(CSSFloat), Vh(CSSFloat), @@ -222,7 +222,7 @@ pub mod specified { } } - #[derive(Clone, PartialEq, Copy, Debug)] + #[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)] pub struct CharacterWidth(pub i32); impl CharacterWidth { @@ -237,7 +237,7 @@ pub mod specified { } } - #[derive(Clone, PartialEq, Copy, Debug)] + #[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)] pub enum Length { Absolute(Au), // application units FontRelative(FontRelativeLength), @@ -354,7 +354,7 @@ pub mod specified { } - #[derive(Clone, PartialEq, Copy, Debug)] + #[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)] pub enum LengthOrPercentage { Length(Length), Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0] @@ -398,7 +398,7 @@ pub mod specified { } } - #[derive(Clone, PartialEq, Copy, Debug)] + #[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)] pub enum LengthOrPercentageOrAuto { Length(Length), Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0] @@ -442,7 +442,7 @@ pub mod specified { } } - #[derive(Clone, PartialEq, Copy, Debug)] + #[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)] pub enum LengthOrPercentageOrNone { Length(Length), Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0] @@ -486,7 +486,7 @@ pub mod specified { } } - #[derive(Clone, PartialEq, Copy, Debug)] + #[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)] pub enum LengthOrNone { Length(Length), None, @@ -617,7 +617,7 @@ pub mod specified { } /// Specified values for an image according to CSS-IMAGES. - #[derive(Clone, PartialEq, Debug)] + #[derive(Clone, PartialEq, Debug, HeapSizeOf)] pub enum Image { Url(Url), LinearGradient(LinearGradient), @@ -658,7 +658,7 @@ pub mod specified { } /// Specified values for a CSS linear gradient. - #[derive(Clone, PartialEq, Debug)] + #[derive(Clone, PartialEq, Debug, HeapSizeOf)] pub struct LinearGradient { /// The angle or corner of the gradient. pub angle_or_corner: AngleOrCorner, @@ -681,7 +681,7 @@ pub mod specified { } /// Specified values for an angle or a corner in a linear gradient. - #[derive(Clone, PartialEq, Copy, Debug)] + #[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)] pub enum AngleOrCorner { Angle(Angle), Corner(HorizontalDirection, VerticalDirection), @@ -703,7 +703,7 @@ pub mod specified { } /// Specified values for one color stop in a linear gradient. - #[derive(Clone, PartialEq, Debug)] + #[derive(Clone, PartialEq, Debug, HeapSizeOf)] pub struct ColorStop { /// The color of this stop. pub color: CSSColor, @@ -810,7 +810,7 @@ pub mod specified { } /// A time in seconds according to CSS-VALUES § 6.2. - #[derive(Clone, Copy, Debug, PartialEq, PartialOrd)] + #[derive(Clone, Copy, Debug, PartialEq, PartialOrd, HeapSizeOf)] pub struct Time(pub CSSFloat); impl Time { @@ -938,7 +938,7 @@ pub mod computed { } } - #[derive(PartialEq, Clone, Copy)] + #[derive(PartialEq, Clone, Copy, HeapSizeOf)] pub enum LengthOrPercentage { Length(Au), Percentage(CSSFloat), @@ -984,7 +984,7 @@ pub mod computed { } } - #[derive(PartialEq, Clone, Copy)] + #[derive(PartialEq, Clone, Copy, HeapSizeOf)] pub enum LengthOrPercentageOrAuto { Length(Au), Percentage(CSSFloat), @@ -1030,7 +1030,7 @@ pub mod computed { } } - #[derive(PartialEq, Clone, Copy)] + #[derive(PartialEq, Clone, Copy, HeapSizeOf)] pub enum LengthOrPercentageOrNone { Length(Au), Percentage(CSSFloat), @@ -1076,7 +1076,7 @@ pub mod computed { } } - #[derive(PartialEq, Clone, Copy)] + #[derive(PartialEq, Clone, Copy, HeapSizeOf)] pub enum LengthOrNone { Length(Au), None, @@ -1131,7 +1131,7 @@ pub mod computed { /// Computed values for an image according to CSS-IMAGES. - #[derive(Clone, PartialEq)] + #[derive(Clone, PartialEq, HeapSizeOf)] pub enum Image { Url(Url), LinearGradient(LinearGradient), @@ -1147,7 +1147,7 @@ pub mod computed { } /// Computed values for a CSS linear gradient. - #[derive(Clone, PartialEq)] + #[derive(Clone, PartialEq, HeapSizeOf)] pub struct LinearGradient { /// The angle or corner of the gradient. pub angle_or_corner: AngleOrCorner, @@ -1180,7 +1180,7 @@ pub mod computed { } /// Computed values for one color stop in a linear gradient. - #[derive(Clone, PartialEq, Copy)] + #[derive(Clone, PartialEq, Copy, HeapSizeOf)] pub struct ColorStop { /// The color of this stop. pub color: CSSColor, diff --git a/components/util/Cargo.toml b/components/util/Cargo.toml index 4d9027653f9..5b8e9f726f8 100644 --- a/components/util/Cargo.toml +++ b/components/util/Cargo.toml @@ -21,6 +21,12 @@ path = "../plugins" [dependencies.azure] git = "https://github.com/servo/rust-azure" +[dependencies.js] +git = "https://github.com/servo/rust-mozjs" + +[dependencies.layers] +git = "https://github.com/servo/rust-layers" + [dependencies.cssparser] version = "0.3" features = [ "serde-serialization" ] @@ -35,6 +41,7 @@ features = [ "serde_serialization" ] [dependencies] log = "0.3" bitflags = "0.3" +html5ever = { version = "0.2.1", features = ["unstable"] } libc = "0.1" rand = "0.3" rustc-serialize = "0.3" @@ -44,4 +51,5 @@ num = "0.1.24" euclid = "0.1" serde = "0.4" serde_macros = "0.4" +string_cache = "0.1" lazy_static = "0.1" diff --git a/components/util/lib.rs b/components/util/lib.rs index 8db4b17f5ec..df3f90f5dfb 100644 --- a/components/util/lib.rs +++ b/components/util/lib.rs @@ -31,7 +31,10 @@ extern crate alloc; #[macro_use] extern crate cssparser; extern crate euclid; extern crate getopts; +extern crate html5ever; extern crate ipc_channel; +extern crate js; +extern crate layers; extern crate libc; extern crate num as num_lib; extern crate num_cpus; @@ -39,6 +42,7 @@ extern crate rand; extern crate rustc_serialize; extern crate serde; extern crate smallvec; +extern crate string_cache; extern crate url; use std::sync::Arc; diff --git a/components/util/mem.rs b/components/util/mem.rs index 51ec56c0f05..370840b7a16 100644 --- a/components/util/mem.rs +++ b/components/util/mem.rs @@ -5,17 +5,30 @@ //! Data structure measurement. use libc::{c_void, size_t}; -use std::cell::RefCell; -use std::collections::LinkedList; -use std::mem::transmute; +use std::cell::{Cell, RefCell}; +use std::collections::{HashMap, LinkedList, hash_state}; +use std::hash::Hash; +use std::mem::{size_of, transmute}; use std::sync::Arc; +use std::rc::Rc; use azure::azure_hl::Color; +use cssparser::Color as CSSParserColor; +use cssparser::RGBA; use cursor::Cursor; use euclid::{Point2D, Rect, SideOffsets2D, Size2D, Matrix2D, Matrix4}; -use geometry::Au; +use euclid::length::Length; +use euclid::scale_factor::ScaleFactor; +use geometry::{PagePx, ViewportPx, Au}; +use html5ever::tree_builder::QuirksMode; +use layers::geometry::DevicePixel; +use js::jsapi::Heap; +use js::rust::GCMethods; +use js::jsval::JSVal; +use logical_geometry::WritingMode; use range::Range; +use string_cache::atom::Atom; use url; extern { @@ -129,6 +142,12 @@ impl HeapSizeOf for url::Host { } } +impl<T: HeapSizeOf, U: HeapSizeOf> HeapSizeOf for (T, U) { + fn heap_size_of_children(&self) -> usize { + self.0.heap_size_of_children() + self.1.heap_size_of_children() + } +} + impl<T: HeapSizeOf> HeapSizeOf for Arc<T> { fn heap_size_of_children(&self) -> usize { (**self).heap_size_of_children() @@ -141,6 +160,12 @@ impl<T: HeapSizeOf> HeapSizeOf for RefCell<T> { } } +impl<T: HeapSizeOf + Copy> HeapSizeOf for Cell<T> { + fn heap_size_of_children(&self) -> usize { + self.get().heap_size_of_children() + } +} + impl<T: HeapSizeOf> HeapSizeOf for Vec<T> { fn heap_size_of_children(&self) -> usize { heap_size_of(self.as_ptr() as *const c_void) + @@ -148,6 +173,25 @@ impl<T: HeapSizeOf> HeapSizeOf for Vec<T> { } } +impl<T> HeapSizeOf for Vec<Rc<T>> { + fn heap_size_of_children(&self) -> usize { + // The fate of measuring Rc<T> is still undecided, but we still want to measure + // the space used for storing them. + heap_size_of(self.as_ptr() as *const c_void) + } +} + +impl<K: HeapSizeOf, V: HeapSizeOf, S> HeapSizeOf for HashMap<K, V, S> + where K: Eq + Hash, S: hash_state::HashState { + fn heap_size_of_children(&self) -> usize { + //TODO(#6908) measure actual bucket memory usage instead of approximating + let size = self.capacity() * (size_of::<V>() + size_of::<K>()); + self.iter().fold(size, |n, (key, value)| { + n + key.heap_size_of_children() + value.heap_size_of_children() + }) + } +} + // FIXME(njn): We can't implement HeapSizeOf accurately for LinkedList because it requires access // to the private Node type. Eventually we'll want to add HeapSizeOf (or equivalent) to Rust // itself. In the meantime, we use the dirty hack of transmuting LinkedList into an identical type @@ -242,7 +286,15 @@ known_heap_size!(0, u8, u16, u32, u64, usize); known_heap_size!(0, i8, i16, i32, i64, isize); known_heap_size!(0, bool, f32, f64); -known_heap_size!(0, Rect<T>, Point2D<T>, Size2D<T>, Matrix2D<T>, SideOffsets2D<T>); +known_heap_size!(0, Rect<T>, Point2D<T>, Size2D<T>, Matrix2D<T>, SideOffsets2D<T>, Range<T>); +known_heap_size!(0, Length<T, U>, ScaleFactor<T, U, V>); -known_heap_size!(0, Au, Color, Cursor, Matrix4); -known_heap_size!(0, Range<T>); +known_heap_size!(0, Au, WritingMode, CSSParserColor, Color, RGBA, Cursor, Matrix4, Atom); +known_heap_size!(0, JSVal, PagePx, ViewportPx, DevicePixel, QuirksMode); + +// This is measured properly by the heap measurement implemented in SpiderMonkey. +impl<T: Copy + GCMethods<T>> HeapSizeOf for Heap<T> { + fn heap_size_of_children(&self) -> usize { + 0 + } +} diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock index 72efd080eda..67ac282bfec 100644 --- a/ports/cef/Cargo.lock +++ b/ports/cef/Cargo.lock @@ -869,6 +869,7 @@ dependencies = [ "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)", "offscreen_gl_context 0.1.0 (git+https://github.com/ecoal95/rust-offscreen-rendering-context)", + "plugins 0.0.1", "png 0.1.0 (git+https://github.com/servo/rust-png)", "rustc-serialize 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1490,6 +1491,8 @@ dependencies = [ "cssparser 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", + "js 0.1.0 (git+https://github.com/servo/rust-mozjs)", + "layers 0.1.0 (git+https://github.com/servo/rust-layers)", "lazy_static 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1501,6 +1504,7 @@ dependencies = [ "serde 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde_macros 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/ports/gonk/Cargo.lock b/ports/gonk/Cargo.lock index 0e3c601ee9d..1b45696a94e 100644 --- a/ports/gonk/Cargo.lock +++ b/ports/gonk/Cargo.lock @@ -789,6 +789,7 @@ dependencies = [ "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)", "offscreen_gl_context 0.1.0 (git+https://github.com/ecoal95/rust-offscreen-rendering-context)", + "plugins 0.0.1", "png 0.1.0 (git+https://github.com/servo/rust-png)", "rustc-serialize 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1373,6 +1374,8 @@ dependencies = [ "cssparser 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", + "js 0.1.0 (git+https://github.com/servo/rust-mozjs)", + "layers 0.1.0 (git+https://github.com/servo/rust-layers)", "lazy_static 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1384,6 +1387,7 @@ dependencies = [ "serde 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde_macros 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", ] |