mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Start reporting memory usage for Window and all nodes in all DOM trees for frame treese in script tasks.
This commit is contained in:
parent
c2497fcd49
commit
8620fe5995
33 changed files with 317 additions and 107 deletions
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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>,
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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>>
|
||||
}
|
||||
|
|
|
@ -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>,
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ impl HTMLMediaElement {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(JSTraceable, Copy, Clone, Debug)]
|
||||
#[derive(JSTraceable, Copy, Clone, Debug, HeapSizeOf)]
|
||||
pub enum HTMLMediaElementTypeId {
|
||||
HTMLAudioElement = 0,
|
||||
HTMLVideoElement = 1,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
36
components/script/mem.rs
Normal file
36
components/script/mem.rs
Normal file
|
@ -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,
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue