servo: Merge #7097 - Measure heap memory usage for more types. Fixes #6951 (from boghison:memtypes); r=jdm
authorBogdan Cuza <boghison22@gmail.com>
Thu, 13 Aug 2015 13:16:14 -0600
changeset 365959 8d25407687c942600245e66c88f851f9abbb84fd
parent 365958 24ede77d0b0247e7dba63c73b4e7172a22bf1fbd
child 365960 b4028fdfcedf77e4f3554a4d5d4c9dc233716de9
push id10863
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 23:02:23 +0000
treeherdermozilla-aurora@0931190cd725 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdm
servo: Merge #7097 - Measure heap memory usage for more types. Fixes #6951 (from boghison:memtypes); r=jdm Also adds HeapSizeOf implementations/derive for some types. I've used "Cannot calculate Heap size" as a reason everywhere, because my imagination is rather limited. If you'd like me to change this message for specific types, please write something like this: "Trusted - Cannot calculate Heap size for Trusted" so that it would be easier for me to replace them through a script :) Source-Repo: https://github.com/servo/servo Source-Revision: a03616f379c255cc6c9b6e1d04dd7d98bd9926ce
servo/components/canvas_traits/Cargo.toml
servo/components/canvas_traits/lib.rs
servo/components/devtools_traits/Cargo.toml
servo/components/devtools_traits/lib.rs
servo/components/msg/constellation_msg.rs
servo/components/net_traits/Cargo.toml
servo/components/net_traits/hosts.rs
servo/components/net_traits/image/base.rs
servo/components/net_traits/image_cache_task.rs
servo/components/net_traits/lib.rs
servo/components/net_traits/storage_task.rs
servo/components/script/cors.rs
servo/components/script/dom/attr.rs
servo/components/script/dom/bindings/error.rs
servo/components/script/dom/bindings/global.rs
servo/components/script/dom/bindings/js.rs
servo/components/script/dom/bindings/str.rs
servo/components/script/dom/blob.rs
servo/components/script/dom/canvasgradient.rs
servo/components/script/dom/canvaspattern.rs
servo/components/script/dom/canvasrenderingcontext2d.rs
servo/components/script/dom/closeevent.rs
servo/components/script/dom/comment.rs
servo/components/script/dom/console.rs
servo/components/script/dom/crypto.rs
servo/components/script/dom/css.rs
servo/components/script/dom/cssstyledeclaration.rs
servo/components/script/dom/customevent.rs
servo/components/script/dom/dedicatedworkerglobalscope.rs
servo/components/script/dom/document.rs
servo/components/script/dom/documentfragment.rs
servo/components/script/dom/documenttype.rs
servo/components/script/dom/domexception.rs
servo/components/script/dom/domimplementation.rs
servo/components/script/dom/domparser.rs
servo/components/script/dom/dompoint.rs
servo/components/script/dom/dompointreadonly.rs
servo/components/script/dom/domrect.rs
servo/components/script/dom/domrectlist.rs
servo/components/script/dom/domstringmap.rs
servo/components/script/dom/domtokenlist.rs
servo/components/script/dom/element.rs
servo/components/script/dom/errorevent.rs
servo/components/script/dom/event.rs
servo/components/script/dom/file.rs
servo/components/script/dom/filelist.rs
servo/components/script/dom/filereader.rs
servo/components/script/dom/formdata.rs
servo/components/script/dom/htmlanchorelement.rs
servo/components/script/dom/htmlappletelement.rs
servo/components/script/dom/htmlareaelement.rs
servo/components/script/dom/htmlaudioelement.rs
servo/components/script/dom/htmlbaseelement.rs
servo/components/script/dom/htmlbodyelement.rs
servo/components/script/dom/htmlbrelement.rs
servo/components/script/dom/htmlbuttonelement.rs
servo/components/script/dom/htmlcanvaselement.rs
servo/components/script/dom/htmlcollection.rs
servo/components/script/dom/htmldataelement.rs
servo/components/script/dom/htmldatalistelement.rs
servo/components/script/dom/htmldialogelement.rs
servo/components/script/dom/htmldirectoryelement.rs
servo/components/script/dom/htmldivelement.rs
servo/components/script/dom/htmldlistelement.rs
servo/components/script/dom/htmlelement.rs
servo/components/script/dom/htmlembedelement.rs
servo/components/script/dom/htmlfieldsetelement.rs
servo/components/script/dom/htmlfontelement.rs
servo/components/script/dom/htmlformelement.rs
servo/components/script/dom/htmlframeelement.rs
servo/components/script/dom/htmlframesetelement.rs
servo/components/script/dom/htmlheadelement.rs
servo/components/script/dom/htmlheadingelement.rs
servo/components/script/dom/htmlhrelement.rs
servo/components/script/dom/htmlhtmlelement.rs
servo/components/script/dom/htmliframeelement.rs
servo/components/script/dom/htmlimageelement.rs
servo/components/script/dom/htmlinputelement.rs
servo/components/script/dom/htmllabelelement.rs
servo/components/script/dom/htmllegendelement.rs
servo/components/script/dom/htmllielement.rs
servo/components/script/dom/htmllinkelement.rs
servo/components/script/dom/htmlmapelement.rs
servo/components/script/dom/htmlmediaelement.rs
servo/components/script/dom/htmlmetaelement.rs
servo/components/script/dom/htmlmeterelement.rs
servo/components/script/dom/htmlmodelement.rs
servo/components/script/dom/htmlobjectelement.rs
servo/components/script/dom/htmlolistelement.rs
servo/components/script/dom/htmloptgroupelement.rs
servo/components/script/dom/htmloptionelement.rs
servo/components/script/dom/htmloutputelement.rs
servo/components/script/dom/htmlparagraphelement.rs
servo/components/script/dom/htmlparamelement.rs
servo/components/script/dom/htmlpreelement.rs
servo/components/script/dom/htmlprogresselement.rs
servo/components/script/dom/htmlquoteelement.rs
servo/components/script/dom/htmlscriptelement.rs
servo/components/script/dom/htmlselectelement.rs
servo/components/script/dom/htmlsourceelement.rs
servo/components/script/dom/htmlspanelement.rs
servo/components/script/dom/htmlstyleelement.rs
servo/components/script/dom/htmltablecaptionelement.rs
servo/components/script/dom/htmltablecellelement.rs
servo/components/script/dom/htmltablecolelement.rs
servo/components/script/dom/htmltabledatacellelement.rs
servo/components/script/dom/htmltableelement.rs
servo/components/script/dom/htmltableheadercellelement.rs
servo/components/script/dom/htmltablerowelement.rs
servo/components/script/dom/htmltablesectionelement.rs
servo/components/script/dom/htmltemplateelement.rs
servo/components/script/dom/htmltextareaelement.rs
servo/components/script/dom/htmltimeelement.rs
servo/components/script/dom/htmltitleelement.rs
servo/components/script/dom/htmltrackelement.rs
servo/components/script/dom/htmlulistelement.rs
servo/components/script/dom/htmlunknownelement.rs
servo/components/script/dom/htmlvideoelement.rs
servo/components/script/dom/imagedata.rs
servo/components/script/dom/keyboardevent.rs
servo/components/script/dom/location.rs
servo/components/script/dom/messageevent.rs
servo/components/script/dom/mouseevent.rs
servo/components/script/dom/namednodemap.rs
servo/components/script/dom/navigator.rs
servo/components/script/dom/node.rs
servo/components/script/dom/nodeiterator.rs
servo/components/script/dom/nodelist.rs
servo/components/script/dom/performance.rs
servo/components/script/dom/performancetiming.rs
servo/components/script/dom/processinginstruction.rs
servo/components/script/dom/progressevent.rs
servo/components/script/dom/range.rs
servo/components/script/dom/screen.rs
servo/components/script/dom/servohtmlparser.rs
servo/components/script/dom/storage.rs
servo/components/script/dom/storageevent.rs
servo/components/script/dom/testbinding.rs
servo/components/script/dom/testbindingproxy.rs
servo/components/script/dom/text.rs
servo/components/script/dom/textdecoder.rs
servo/components/script/dom/textencoder.rs
servo/components/script/dom/uievent.rs
servo/components/script/dom/url.rs
servo/components/script/dom/urlhelper.rs
servo/components/script/dom/urlsearchparams.rs
servo/components/script/dom/validitystate.rs
servo/components/script/dom/webglactiveinfo.rs
servo/components/script/dom/webglbuffer.rs
servo/components/script/dom/webglframebuffer.rs
servo/components/script/dom/webglobject.rs
servo/components/script/dom/webglprogram.rs
servo/components/script/dom/webglrenderbuffer.rs
servo/components/script/dom/webglrenderingcontext.rs
servo/components/script/dom/webglshader.rs
servo/components/script/dom/webglshaderprecisionformat.rs
servo/components/script/dom/webgltexture.rs
servo/components/script/dom/webgluniformlocation.rs
servo/components/script/dom/websocket.rs
servo/components/script/dom/window.rs
servo/components/script/dom/worker.rs
servo/components/script/dom/workerglobalscope.rs
servo/components/script/dom/workerlocation.rs
servo/components/script/dom/workernavigator.rs
servo/components/script/dom/xmlhttprequest.rs
servo/components/script/dom/xmlhttprequesteventtarget.rs
servo/components/script/dom/xmlhttprequestupload.rs
servo/components/script/lib.rs
servo/components/script/mem.rs
servo/components/script/textinput.rs
servo/components/servo/Cargo.lock
servo/components/style/properties.mako.rs
servo/components/util/Cargo.toml
servo/components/util/lib.rs
servo/components/util/mem.rs
--- a/servo/components/canvas_traits/Cargo.toml
+++ b/servo/components/canvas_traits/Cargo.toml
@@ -25,12 +25,18 @@ git = "https://github.com/pcwalton/ipc-c
 [dependencies.serde]
 version = "0.5"
 features = [ "nightly" ]
 
 [dependencies.cssparser]
 version = "0.3"
 features = [ "serde-serialization" ]
 
+[dependencies.plugins]
+path = "../plugins"
+
+[dependencies.util]
+path = "../util"
+
 [dependencies]
 euclid = "0.1"
 serde_macros = "0.5"
 
--- a/servo/components/canvas_traits/lib.rs
+++ b/servo/components/canvas_traits/lib.rs
@@ -3,27 +3,28 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #![crate_name = "canvas_traits"]
 #![crate_type = "rlib"]
 #![feature(core)]
 #![feature(custom_derive)]
 #![feature(nonzero)]
 #![feature(plugin)]
-#![plugin(serde_macros)]
+#![plugin(serde_macros, plugins)]
 
 extern crate core;
 extern crate azure;
 extern crate euclid;
 extern crate cssparser;
 extern crate gfx_traits;
 extern crate ipc_channel;
 extern crate layers;
 extern crate offscreen_gl_context;
 extern crate serde;
+extern crate util;
 
 use azure::azure::{AzFloat, AzColor};
 use azure::azure_hl::{DrawTarget, Pattern, ColorPattern};
 use azure::azure_hl::{GradientStop, LinearGradientPattern, RadialGradientPattern, ExtendMode};
 use azure::azure_hl::{JoinStyle, CapStyle, CompositionOp};
 use azure::azure_hl::{SurfacePattern, SurfaceFormat};
 use cssparser::RGBA;
 use euclid::matrix2d::Matrix2D;
@@ -32,16 +33,17 @@ use euclid::rect::Rect;
 use euclid::size::Size2D;
 use gfx_traits::color;
 use ipc_channel::ipc::{IpcSender, IpcSharedMemory};
 use std::sync::mpsc::Sender;
 use layers::platform::surface::NativeSurface;
 use offscreen_gl_context::GLContextAttributes;
 use serde::{Deserialize, Deserializer, Serialize, Serializer};
 use core::nonzero::NonZero;
+use util::mem::HeapSizeOf;
 
 #[derive(Clone, Deserialize, Serialize)]
 pub enum CanvasMsg {
     Canvas2d(Canvas2dMsg),
     Common(CanvasCommonMsg),
     FromLayout(FromLayoutMsg),
     FromPaint(FromPaintMsg),
     WebGL(CanvasWebGLMsg),
@@ -154,17 +156,17 @@ pub enum CanvasWebGLMsg {
     Uniform4fv(i32, Vec<f32>),
     UseProgram(u32),
     VertexAttribPointer2f(u32, i32, bool, i32, i64),
     Viewport(i32, i32, i32, i32),
     DrawingBufferWidth(IpcSender<i32>),
     DrawingBufferHeight(IpcSender<i32>),
 }
 
-#[derive(Clone, Copy, PartialEq, Deserialize, Serialize)]
+#[derive(Clone, Copy, PartialEq, Deserialize, Serialize, HeapSizeOf)]
 pub enum WebGLError {
     InvalidEnum,
     InvalidOperation,
     InvalidValue,
     OutOfMemory,
     ContextLost,
 }
 
@@ -178,23 +180,23 @@ pub enum WebGLFramebufferBindingRequest 
 
 #[derive(Clone, Deserialize, Serialize)]
 pub enum WebGLShaderParameter {
     Int(i32),
     Bool(bool),
     Invalid,
 }
 
-#[derive(Clone, Deserialize, Serialize)]
+#[derive(Clone, Deserialize, Serialize, HeapSizeOf)]
 pub struct CanvasGradientStop {
     pub offset: f64,
     pub color: RGBA,
 }
 
-#[derive(Clone, Deserialize, Serialize)]
+#[derive(Clone, Deserialize, Serialize, HeapSizeOf)]
 pub struct LinearGradientStyle {
     pub x0: f64,
     pub y0: f64,
     pub x1: f64,
     pub y1: f64,
     pub stops: Vec<CanvasGradientStop>
 }
 
@@ -206,17 +208,17 @@ impl LinearGradientStyle {
             y0: y0,
             x1: x1,
             y1: y1,
             stops: stops,
         }
     }
 }
 
-#[derive(Clone, Deserialize, Serialize)]
+#[derive(Clone, Deserialize, Serialize, HeapSizeOf)]
 pub struct RadialGradientStyle {
     pub x0: f64,
     pub y0: f64,
     pub r0: f64,
     pub x1: f64,
     pub y1: f64,
     pub r1: f64,
     pub stops: Vec<CanvasGradientStop>
@@ -316,17 +318,17 @@ impl FillOrStrokeStyle {
                     surface_style.repeat_x,
                     surface_style.repeat_y,
                     &Matrix2D::identity()))
             }
         }
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Deserialize, Serialize)]
+#[derive(Copy, Clone, PartialEq, Deserialize, Serialize, HeapSizeOf)]
 pub enum LineCapStyle {
     Butt = 0,
     Round = 1,
     Square = 2,
 }
 
 impl LineCapStyle {
     pub fn to_azure_style(&self) -> CapStyle {
@@ -342,17 +344,17 @@ impl LineCapStyle {
             "butt" => Some(LineCapStyle::Butt),
             "round" => Some(LineCapStyle::Round),
             "square" => Some(LineCapStyle::Square),
             _ => None
         }
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Deserialize, Serialize)]
+#[derive(Copy, Clone, PartialEq, Deserialize, Serialize, HeapSizeOf)]
 pub enum LineJoinStyle {
     Round = 0,
     Bevel = 1,
     Miter = 2,
 }
 
 impl LineJoinStyle {
     pub fn to_azure_style(&self) -> JoinStyle {
@@ -388,17 +390,17 @@ impl RepetitionStyle {
             "repeat-x" => Some(RepetitionStyle::RepeatX),
             "repeat-y" => Some(RepetitionStyle::RepeatY),
             "no-repeat" => Some(RepetitionStyle::NoRepeat),
             _ => None
         }
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Deserialize, Serialize)]
+#[derive(Copy, Clone, PartialEq, Deserialize, Serialize, HeapSizeOf)]
 pub enum CompositionStyle {
     SrcIn,
     SrcOut,
     SrcOver,
     SrcAtop,
     DestIn,
     DestOut,
     DestOver,
@@ -454,17 +456,17 @@ impl CompositionStyle {
             CompositionStyle::DestAtop => "destination-atop",
             CompositionStyle::Copy     => "copy",
             CompositionStyle::Lighter  => "lighter",
             CompositionStyle::Xor      => "xor",
         }
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Deserialize, Serialize)]
+#[derive(Copy, Clone, PartialEq, Deserialize, Serialize, HeapSizeOf)]
 pub enum BlendingStyle {
     Multiply,
     Screen,
     Overlay,
     Darken,
     Lighten,
     ColorDodge,
     ColorBurn,
@@ -536,17 +538,17 @@ impl BlendingStyle {
             BlendingStyle::Hue        => "hue",
             BlendingStyle::Saturation => "saturation",
             BlendingStyle::Color      => "color",
             BlendingStyle::Luminosity => "luminosity",
         }
     }
 }
 
-#[derive(Copy, Clone, PartialEq, Deserialize, Serialize)]
+#[derive(Copy, Clone, PartialEq, Deserialize, Serialize, HeapSizeOf)]
 pub enum CompositionOrBlending {
     Composition(CompositionStyle),
     Blending(BlendingStyle),
 }
 
 impl CompositionOrBlending {
     pub fn to_azure_style(&self) -> CompositionOp {
         match *self {
--- a/servo/components/devtools_traits/Cargo.toml
+++ b/servo/components/devtools_traits/Cargo.toml
@@ -19,15 +19,18 @@ path = "../util"
 
 [dependencies.url]
 version = "0.2"
 features = [ "serde_serialization" ]
 
 [dependencies.ipc-channel]
 git = "https://github.com/pcwalton/ipc-channel"
 
+[dependencies.plugins]
+path = "../plugins"
+
 [dependencies]
 time = "0.1"
 rustc-serialize = "0.3"
 bitflags = "0.3"
 serde = "0.5"
 serde_macros = "0.5"
 
--- a/servo/components/devtools_traits/lib.rs
+++ b/servo/components/devtools_traits/lib.rs
@@ -8,17 +8,17 @@
 
 #![crate_name = "devtools_traits"]
 #![crate_type = "rlib"]
 
 #![allow(non_snake_case)]
 #![deny(unsafe_code)]
 
 #![feature(custom_derive, plugin)]
-#![plugin(serde_macros)]
+#![plugin(serde_macros, plugins)]
 
 #[macro_use]
 extern crate bitflags;
 
 extern crate ipc_channel;
 extern crate msg;
 extern crate rustc_serialize;
 extern crate serde;
--- a/servo/components/msg/constellation_msg.rs
+++ b/servo/components/msg/constellation_msg.rs
@@ -14,16 +14,17 @@ use euclid::scale_factor::ScaleFactor;
 use hyper::header::Headers;
 use hyper::method::Method;
 use ipc_channel::ipc::IpcSender;
 use layers::geometry::DevicePixel;
 use offscreen_gl_context::GLContextAttributes;
 use png::Image;
 use util::cursor::Cursor;
 use util::geometry::{PagePx, ViewportPx};
+use util::mem::HeapSizeOf;
 use std::collections::HashMap;
 use std::sync::mpsc::{channel, Sender, Receiver};
 use style::viewport::ViewportConstraints;
 use url::Url;
 use webdriver_msg::{WebDriverScriptCommand, LoadStatus};
 
 #[derive(Clone)]
 pub struct ConstellationChan(pub Sender<Msg>);
@@ -64,17 +65,17 @@ pub struct WindowSizeData {
 #[derive(PartialEq, Eq, Copy, Clone, Deserialize, Serialize)]
 pub enum KeyState {
     Pressed,
     Released,
     Repeated,
 }
 
 //N.B. Based on the glutin key enum
-#[derive(Debug, PartialEq, Eq, Copy, Clone, Deserialize, Serialize)]
+#[derive(Debug, PartialEq, Eq, Copy, Clone, Deserialize, Serialize, HeapSizeOf)]
 pub enum Key {
     Space,
     Apostrophe,
     Comma,
     Minus,
     Period,
     Slash,
     Num0,
--- a/servo/components/net_traits/Cargo.toml
+++ b/servo/components/net_traits/Cargo.toml
@@ -26,15 +26,18 @@ features = [ "serde-serialization" ]
 
 [dependencies.ipc-channel]
 git = "https://github.com/pcwalton/ipc-channel"
 
 [dependencies.url]
 version = "0.2"
 features = [ "serde_serialization" ]
 
+[dependencies.plugins]
+path = "../plugins"
+
 [dependencies]
 log = "0.3"
 euclid = "0.1"
 regex = "0.1.33"
 regex_macros = "0.1.19"
 serde = "0.5"
 serde_macros = "0.5"
--- a/servo/components/net_traits/hosts.rs
+++ b/servo/components/net_traits/hosts.rs
@@ -46,17 +46,17 @@ pub fn parse_hostsfile(hostsfile_content
         if ip_host.len() > 1 {
             if !IPV4_REGEX.is_match(ip_host[0]) && !IPV6_REGEX.is_match(ip_host[0]) { continue; }
             let address = ip_host[0].to_owned();
 
             for token in ip_host.iter().skip(1) {
                 if token.as_bytes()[0] == b'#' {
                     break;
                 }
-                host_table.insert(token.to_owned().to_string(), address.clone());
+                host_table.insert((*token).to_owned(), address.clone());
             }
         }
     }
     box host_table
 }
 
 pub fn replace_hosts(url: &Url) -> Url {
     unsafe {
--- a/servo/components/net_traits/image/base.rs
+++ b/servo/components/net_traits/image/base.rs
@@ -1,34 +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/. */
 
 use ipc_channel::ipc::IpcSharedMemory;
 use png;
 use stb_image::image as stb_image2;
 use std::mem;
+use util::mem::HeapSizeOf;
 use util::vec::byte_swap;
 
 // FIXME: Images must not be copied every frame. Instead we should atomically
 // reference count them.
 
-#[derive(Deserialize, Serialize)]
+#[derive(Deserialize, Serialize, HeapSizeOf)]
 pub enum PixelFormat {
     K8,         // Luminance channel only
     KA8,        // Luminance + alpha
     RGB8,       // RGB, 8 bits per channel
     RGBA8,      // RGB + alpha, 8 bits per channel
 }
 
-#[derive(Deserialize, Serialize)]
+#[derive(Deserialize, Serialize, HeapSizeOf)]
 pub struct Image {
     pub width: u32,
     pub height: u32,
     pub format: PixelFormat,
+    #[ignore_heap_size_of = "Defined in ipc-channel"]
     pub bytes: IpcSharedMemory,
 }
 
 // TODO(pcwalton): Speed up with SIMD, or better yet, find some way to not do this.
 fn byte_swap_and_premultiply(data: &mut [u8]) {
     let length = data.len();
     for i in (0..length).step_by(4) {
         let r = data[i + 2];
--- a/servo/components/net_traits/image_cache_task.rs
+++ b/servo/components/net_traits/image_cache_task.rs
@@ -1,16 +1,17 @@
 /* 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/. */
 
 use image::base::Image;
 use ipc_channel::ipc::{self, IpcSender};
 use url::Url;
 use std::sync::Arc;
+use util::mem::HeapSizeOf;
 
 /// This is optionally passed to the image cache when requesting
 /// and image, and returned to the specified event loop when the
 /// image load completes. It is typically used to trigger a reflow
 /// and/or repaint.
 #[derive(Deserialize, Serialize)]
 pub struct ImageResponder {
     sender: IpcSender<ImageResponse>,
@@ -32,17 +33,17 @@ impl ImageResponder {
 #[derive(PartialEq, Copy, Clone, Deserialize, Serialize)]
 pub enum ImageState {
     Pending,
     LoadError,
     NotRequested,
 }
 
 /// The returned image.
-#[derive(Clone, Deserialize, Serialize)]
+#[derive(Clone, Deserialize, Serialize, HeapSizeOf)]
 pub enum ImageResponse {
     /// The requested image was loaded.
     Loaded(Arc<Image>),
     /// The requested image failed to load, so a placeholder was loaded instead.
     PlaceholderLoaded(Arc<Image>),
     /// Neither the requested image nor the placeholder could be loaded.
     None
 }
--- a/servo/components/net_traits/lib.rs
+++ b/servo/components/net_traits/lib.rs
@@ -4,17 +4,18 @@
 
 #![feature(box_syntax)]
 #![feature(custom_derive)]
 #![feature(box_raw)]
 #![feature(plugin)]
 #![feature(slice_patterns)]
 #![feature(step_by)]
 #![feature(vec_push_all)]
-#![plugin(serde_macros)]
+#![feature(custom_attribute)]
+#![plugin(serde_macros, plugins)]
 
 #![plugin(regex_macros)]
 
 extern crate euclid;
 extern crate hyper;
 extern crate ipc_channel;
 #[macro_use]
 extern crate log;
@@ -30,16 +31,17 @@ use hyper::header::{ContentType, Headers
 use hyper::http::RawStatus;
 use hyper::method::Method;
 use hyper::mime::{Mime, Attr};
 use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
 use msg::constellation_msg::{PipelineId};
 use regex::Regex;
 use serde::{Deserializer, Serializer};
 use url::Url;
+use util::mem::HeapSizeOf;
 
 use std::thread;
 
 pub mod hosts;
 pub mod image_cache_task;
 pub mod net_error_list;
 pub mod storage_task;
 
@@ -51,22 +53,24 @@ pub static IPV6_REGEX: Regex = regex!(r"
 ///
 /// It may be surprising that this goes in the network crate as opposed to the graphics crate.
 /// However, image handling is generally very integrated with the network stack (especially where
 /// caching is involved) and as a result it must live in here.
 pub mod image {
     pub mod base;
 }
 
-#[derive(Clone, Deserialize, Serialize)]
+#[derive(Clone, Deserialize, Serialize, HeapSizeOf)]
 pub struct LoadData {
     pub url: Url,
     pub method: Method,
+    #[ignore_heap_size_of = "Defined in hyper"]
     /// Headers that will apply to the initial request only
     pub headers: Headers,
+    #[ignore_heap_size_of = "Defined in hyper"]
     /// Headers that will apply to the initial request and any redirects
     pub preserved_headers: Headers,
     pub data: Option<Vec<u8>>,
     pub cors: Option<ResourceCORSData>,
     pub pipeline_id: Option<PipelineId>,
 }
 
 impl LoadData {
@@ -226,36 +230,37 @@ impl PendingAsyncLoad {
 #[derive(Serialize, Deserialize)]
 pub struct LoadResponse {
     /// Metadata, such as from HTTP headers.
     pub metadata: Metadata,
     /// Port for reading data.
     pub progress_port: IpcReceiver<ProgressMsg>,
 }
 
-#[derive(Clone, Deserialize, Serialize)]
+#[derive(Clone, Deserialize, Serialize, HeapSizeOf)]
 pub struct ResourceCORSData {
     /// CORS Preflight flag
     pub preflight: bool,
     /// Origin of CORS Request
     pub origin: Url,
 }
 
 /// Metadata about a loaded resource, such as is obtained from HTTP headers.
-#[derive(Clone, Deserialize, Serialize)]
+#[derive(Clone, Deserialize, Serialize, HeapSizeOf)]
 pub struct Metadata {
     /// Final URL after redirects.
     pub final_url: Url,
 
     /// MIME type / subtype.
     pub content_type: Option<(ContentType)>,
 
     /// Character set.
     pub charset: Option<String>,
 
+    #[ignore_heap_size_of = "Defined in hyper"]
     /// Headers
     pub headers: Option<Headers>,
 
     /// HTTP Status
     pub status: Option<RawStatus>,
 }
 
 impl Metadata {
--- a/servo/components/net_traits/storage_task.rs
+++ b/servo/components/net_traits/storage_task.rs
@@ -2,17 +2,17 @@
  * 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/. */
 
 use ipc_channel::ipc::IpcSender;
 use url::Url;
 
 use util::str::DOMString;
 
-#[derive(Copy, Clone, Deserialize, Serialize)]
+#[derive(Copy, Clone, Deserialize, Serialize, HeapSizeOf)]
 pub enum StorageType {
     Session,
     Local
 }
 
 /// Request operations on the storage data associated with a particular url
 #[derive(Deserialize, Serialize)]
 pub enum StorageTaskMsg {
--- a/servo/components/script/cors.rs
+++ b/servo/components/script/cors.rs
@@ -27,40 +27,42 @@ use hyper::header::{Headers, HeaderView}
 use hyper::client::Request;
 use hyper::mime::{Mime, TopLevel, SubLevel};
 use hyper::header::{ContentType, Host};
 use hyper::method::Method;
 use hyper::status::StatusClass::Success;
 
 use unicase::UniCase;
 use url::{SchemeData, Url};
+use util::mem::HeapSizeOf;
 use util::task::spawn_named;
 
 /// Interface for network listeners concerned with CORS checks. Proper network requests
 /// should be initiated from this method, based on the response provided.
 pub trait AsyncCORSResponseListener {
     fn response_available(&self, response: CORSResponse);
 }
 
-#[derive(Clone)]
+#[derive(Clone, HeapSizeOf)]
 pub struct CORSRequest {
     pub origin: Url,
     pub destination: Url,
     pub mode: RequestMode,
     pub method: Method,
+    #[ignore_heap_size_of = "Defined in hyper"]
     pub headers: Headers,
     /// CORS preflight flag (https://fetch.spec.whatwg.org/#concept-http-fetch)
     /// Indicates that a CORS preflight request and/or cache check is to be performed
     pub preflight_flag: bool
 }
 
 /// https://fetch.spec.whatwg.org/#concept-request-mode
 /// This only covers some of the request modes. The
 /// `same-origin` and `no CORS` modes are unnecessary for XHR.
-#[derive(PartialEq, Copy, Clone)]
+#[derive(PartialEq, Copy, Clone, HeapSizeOf)]
 pub enum RequestMode {
     CORS, // CORS
     ForcedPreflight // CORS-with-forced-preflight
 }
 
 impl CORSRequest {
     /// Creates a CORS request if necessary. Will return an error when fetching is forbidden
     pub fn maybe_new(referer: Url, destination: Url, mode: RequestMode,
--- a/servo/components/script/dom/attr.rs
+++ b/servo/components/script/dom/attr.rs
@@ -18,22 +18,23 @@ use util::str::{DOMString, parse_unsigne
 
 use string_cache::{Atom, Namespace};
 
 use std::borrow::ToOwned;
 use std::cell::Ref;
 use std::mem;
 use std::ops::Deref;
 
+#[derive(HeapSizeOf)]
 pub enum AttrSettingType {
     FirstSetAttr,
     ReplacedAttr,
 }
 
-#[derive(JSTraceable, PartialEq, Clone)]
+#[derive(JSTraceable, PartialEq, Clone, HeapSizeOf)]
 pub enum AttrValue {
     String(DOMString),
     TokenList(DOMString, Vec<Atom>),
     UInt(DOMString, u32),
     Atom(Atom),
 }
 
 impl AttrValue {
@@ -105,16 +106,17 @@ impl Deref for AttrValue {
                 AttrValue::UInt(ref value, _) => &value,
             AttrValue::Atom(ref value) => &value,
         }
     }
 }
 
 // https://dom.spec.whatwg.org/#interface-attr
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct Attr {
     reflector_: Reflector,
     local_name: Atom,
     value: DOMRefCell<AttrValue>,
     name: Atom,
     namespace: Namespace,
     prefix: Option<Atom>,
 
--- a/servo/components/script/dom/bindings/error.rs
+++ b/servo/components/script/dom/bindings/error.rs
@@ -4,32 +4,33 @@
 
 //! Utilities to throw exceptions from Rust bindings.
 
 use dom::bindings::codegen::PrototypeList::proto_id_to_name;
 use dom::bindings::conversions::ToJSValConvertible;
 use dom::bindings::global::GlobalRef;
 use dom::domexception::{DOMException, DOMErrorName};
 
+use util::mem::HeapSizeOf;
 use util::str::DOMString;
 
 use js::jsapi::{JSContext, JSObject, RootedValue};
 use js::jsapi::{JS_IsExceptionPending, JS_SetPendingException, JS_ReportPendingException};
 use js::jsapi::{JS_ReportErrorNumber1, JSErrorFormatString, JSExnType};
 use js::jsapi::{JS_SaveFrameChain, JS_RestoreFrameChain};
 use js::jsapi::JSAutoCompartment;
 use js::jsval::UndefinedValue;
 
 use libc;
 use std::ffi::CString;
 use std::ptr;
 use std::mem;
 
 /// DOM exceptions that can be thrown by a native DOM method.
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, HeapSizeOf)]
 pub enum Error {
     /// IndexSizeError DOMException
     IndexSize,
     /// NotFoundError DOMException
     NotFound,
     /// HierarchyRequestError DOMException
     HierarchyRequest,
     /// WrongDocumentError DOMException
--- a/servo/components/script/dom/bindings/global.rs
+++ b/servo/components/script/dom/bindings/global.rs
@@ -22,16 +22,18 @@ use net_traits::ResourceTask;
 use profile_traits::mem;
 
 use ipc_channel::ipc::IpcSender;
 use js::{JSCLASS_IS_GLOBAL, JSCLASS_IS_DOMJSCLASS};
 use js::jsapi::{GetGlobalForObjectCrossCompartment};
 use js::jsapi::{JSContext, JSObject, JS_GetClass, MutableHandleValue};
 use url::Url;
 
+use util::mem::HeapSizeOf;
+
 /// A freely-copyable reference to a rooted global object.
 #[derive(Copy, Clone)]
 pub enum GlobalRef<'a> {
     /// A reference to a `Window` object.
     Window(&'a window::Window),
     /// A reference to a `WorkerGlobalScope` object.
     Worker(&'a WorkerGlobalScope),
 }
@@ -42,17 +44,17 @@ pub enum GlobalRoot {
     /// A root for a `Window` object.
     Window(Root<window::Window>),
     /// A root for a `WorkerGlobalScope` object.
     Worker(Root<WorkerGlobalScope>),
 }
 
 /// A traced reference to a global object, for use in fields of traced Rust
 /// structures.
-#[derive(JSTraceable)]
+#[derive(JSTraceable, HeapSizeOf)]
 #[must_root]
 pub enum GlobalField {
     /// A field for a `Window` object.
     Window(JS<window::Window>),
     /// A field for a `WorkerGlobalScope` object.
     Worker(JS<WorkerGlobalScope>),
 }
 
--- a/servo/components/script/dom/bindings/js.rs
+++ b/servo/components/script/dom/bindings/js.rs
@@ -458,9 +458,8 @@ impl<T: Reflectable> PartialEq for Root<
     }
 }
 
 impl<T: Reflectable> Drop for Root<T> {
     fn drop(&mut self) {
         unsafe { (*self.root_list).unroot(self); }
     }
 }
-
--- a/servo/components/script/dom/bindings/str.rs
+++ b/servo/components/script/dom/bindings/str.rs
@@ -6,18 +6,20 @@
 
 use std::ascii::AsciiExt;
 use std::borrow::ToOwned;
 use std::hash::{Hash, Hasher};
 use std::ops;
 use std::str;
 use std::str::FromStr;
 
+use util::mem::HeapSizeOf;
+
 /// Encapsulates the IDL `ByteString` type.
-#[derive(JSTraceable,Clone,Eq,PartialEq)]
+#[derive(JSTraceable, Clone, Eq, PartialEq, HeapSizeOf)]
 pub struct ByteString(Vec<u8>);
 
 impl ByteString {
     /// Creates a new `ByteString`.
     pub fn new(value: Vec<u8>) -> ByteString {
         ByteString(value)
     }
 
--- a/servo/components/script/dom/blob.rs
+++ b/servo/components/script/dom/blob.rs
@@ -12,24 +12,25 @@ use dom::bindings::codegen::Bindings::Bl
 use std::sync::mpsc::Sender;
 use util::str::DOMString;
 use num::ToPrimitive;
 use std::ascii::AsciiExt;
 use std::borrow::ToOwned;
 use std::cmp::{min, max};
 use std::cell::{Cell};
 
-#[derive(JSTraceable)]
+#[derive(JSTraceable, HeapSizeOf)]
 pub enum BlobTypeId {
     Blob,
     File,
 }
 
 // http://dev.w3.org/2006/webapi/FileAPI/#blob
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct Blob {
     reflector_: Reflector,
     type_: BlobTypeId,
     bytes: Option<Vec<u8>>,
     typeString: DOMString,
     global: GlobalField,
     isClosed_: Cell<bool>
 }
--- a/servo/components/script/dom/canvasgradient.rs
+++ b/servo/components/script/dom/canvasgradient.rs
@@ -11,23 +11,24 @@ use dom::bindings::error::ErrorResult;
 use dom::bindings::global::GlobalRef;
 use dom::bindings::js::Root;
 use dom::bindings::num::Finite;
 use dom::bindings::utils::{Reflector, reflect_dom_object};
 use dom::canvasrenderingcontext2d::parse_color;
 
 // https://html.spec.whatwg.org/multipage/#canvasgradient
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct CanvasGradient {
     reflector_: Reflector,
     style: CanvasGradientStyle,
     stops: DOMRefCell<Vec<CanvasGradientStop>>,
 }
 
-#[derive(JSTraceable, Clone)]
+#[derive(JSTraceable, Clone, HeapSizeOf)]
 pub enum CanvasGradientStyle {
     Linear(LinearGradientStyle),
     Radial(RadialGradientStyle),
 }
 
 impl CanvasGradient {
     fn new_inherited(style: CanvasGradientStyle) -> CanvasGradient {
         CanvasGradient {
--- a/servo/components/script/dom/canvaspattern.rs
+++ b/servo/components/script/dom/canvaspattern.rs
@@ -7,16 +7,17 @@ use dom::bindings::codegen::Bindings::Ca
 use dom::bindings::global::GlobalRef;
 use dom::bindings::js::Root;
 use dom::bindings::utils::{Reflector, reflect_dom_object};
 use dom::canvasgradient::ToFillOrStrokeStyle;
 use euclid::size::Size2D;
 
 // https://html.spec.whatwg.org/multipage/#canvaspattern
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct CanvasPattern {
     reflector_: Reflector,
     surface_data: Vec<u8>,
     surface_size: Size2D<i32>,
     repeat_x: bool,
     repeat_y: bool,
 }
 
--- a/servo/components/script/dom/canvasrenderingcontext2d.rs
+++ b/servo/components/script/dom/canvasrenderingcontext2d.rs
@@ -46,37 +46,39 @@ use std::fmt;
 use std::cmp;
 use std::sync::mpsc::channel;
 
 use util::str::DOMString;
 use url::Url;
 use util::vec::byte_swap;
 
 #[must_root]
-#[derive(JSTraceable, Clone)]
+#[derive(JSTraceable, Clone, HeapSizeOf)]
 pub enum CanvasFillOrStrokeStyle {
     Color(RGBA),
     Gradient(JS<CanvasGradient>),
     // Pattern(JS<CanvasPattern>),  // https://github.com/servo/servo/pull/6157
 }
 
 // https://html.spec.whatwg.org/multipage/#canvasrenderingcontext2d
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct CanvasRenderingContext2D {
     reflector_: Reflector,
     global: GlobalField,
     renderer_id: usize,
+    #[ignore_heap_size_of = "Defined in ipc-channel"]
     ipc_renderer: IpcSender<CanvasMsg>,
     canvas: JS<HTMLCanvasElement>,
     state: RefCell<CanvasContextState>,
     saved_states: RefCell<Vec<CanvasContextState>>,
 }
 
 #[must_root]
-#[derive(JSTraceable, Clone)]
+#[derive(JSTraceable, Clone, HeapSizeOf)]
 struct CanvasContextState {
     global_alpha: f64,
     global_composition: CompositionOrBlending,
     image_smoothing_enabled: bool,
     fill_style: CanvasFillOrStrokeStyle,
     stroke_style: CanvasFillOrStrokeStyle,
     line_width: f64,
     line_cap: LineCapStyle,
--- a/servo/components/script/dom/closeevent.rs
+++ b/servo/components/script/dom/closeevent.rs
@@ -11,16 +11,17 @@ use dom::bindings::global::GlobalRef;
 use dom::bindings::js::Root;
 use dom::bindings::utils::reflect_dom_object;
 use dom::event::{Event, EventTypeId, EventBubbles, EventCancelable};
 use script_task::ScriptChan;
 
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct CloseEvent {
     event: Event,
     wasClean: bool,
     code: u16,
     reason: DOMString,
 }
 
 impl CloseEvent {
--- a/servo/components/script/dom/comment.rs
+++ b/servo/components/script/dom/comment.rs
@@ -11,16 +11,17 @@ use dom::bindings::js::Root;
 use dom::characterdata::{CharacterData, CharacterDataTypeId};
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 /// An HTML comment.
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct Comment {
     characterdata: CharacterData,
 }
 
 impl CommentDerived for EventTarget {
     fn is_comment(&self) -> bool {
         *self.type_id() == EventTargetTypeId::Node(NodeTypeId::CharacterData(CharacterDataTypeId::Comment))
     }
--- a/servo/components/script/dom/console.rs
+++ b/servo/components/script/dom/console.rs
@@ -8,16 +8,17 @@ use dom::bindings::global::{GlobalRef, G
 use dom::bindings::js::Root;
 use dom::bindings::utils::{Reflector, reflect_dom_object};
 use dom::window::WindowHelpers;
 use devtools_traits::{ConsoleMessage, LogLevel, ScriptToDevtoolsControlMsg};
 use util::str::DOMString;
 
 // https://developer.mozilla.org/en-US/docs/Web/API/Console
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct Console {
     reflector_: Reflector,
     global: GlobalField,
 }
 
 impl Console {
     fn new_inherited(global: GlobalRef) -> Console {
         Console {
--- a/servo/components/script/dom/crypto.rs
+++ b/servo/components/script/dom/crypto.rs
@@ -17,16 +17,17 @@ use std::ptr;
 use std::slice;
 
 use rand::{Rng, OsRng};
 
 no_jsmanaged_fields!(OsRng);
 
 // https://developer.mozilla.org/en-US/docs/Web/API/Crypto
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct Crypto {
     reflector_: Reflector,
     rng: DOMRefCell<OsRng>,
 }
 
 impl Crypto {
     fn new_inherited() -> Crypto {
         Crypto {
--- a/servo/components/script/dom/css.rs
+++ b/servo/components/script/dom/css.rs
@@ -5,16 +5,17 @@
 use dom::bindings::error::{Error, Fallible};
 use dom::bindings::global::GlobalRef;
 use dom::bindings::utils::Reflector;
 use util::str::DOMString;
 
 use cssparser::serialize_identifier;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct CSS {
     reflector_: Reflector,
 }
 
 impl CSS {
     // http://dev.w3.org/csswg/cssom/#serialize-an-identifier
     pub fn Escape(_: GlobalRef, ident: DOMString) -> Fallible<DOMString> {
         if ident.bytes().any(|b| b == b'\0') {
--- a/servo/components/script/dom/cssstyledeclaration.rs
+++ b/servo/components/script/dom/cssstyledeclaration.rs
@@ -20,24 +20,25 @@ use style::properties::{is_supported_pro
 use style::properties::PropertyDeclaration;
 
 use std::ascii::AsciiExt;
 use std::borrow::ToOwned;
 use std::cell::Ref;
 
 // http://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct CSSStyleDeclaration {
     reflector_: Reflector,
     owner: JS<HTMLElement>,
     readonly: bool,
     pseudo: Option<PseudoElement>,
 }
 
-#[derive(PartialEq)]
+#[derive(PartialEq, HeapSizeOf)]
 pub enum CSSModificationAccess {
     ReadWrite,
     Readonly
 }
 
 macro_rules! css_properties(
     ( $([$getter:ident, $setter:ident, $cssprop:expr]),* ) => (
         $(
--- a/servo/components/script/dom/customevent.rs
+++ b/servo/components/script/dom/customevent.rs
@@ -12,18 +12,20 @@ use dom::bindings::js::{Root, MutHeapJSV
 use dom::bindings::utils::reflect_dom_object;
 use dom::event::{Event, EventTypeId};
 use js::jsapi::{JSContext, HandleValue};
 use js::jsval::JSVal;
 use util::str::DOMString;
 
 // https://dom.spec.whatwg.org/#interface-customevent
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct CustomEvent {
     event: Event,
+    #[ignore_heap_size_of = "Defined in rust-mozjs"]
     detail: MutHeapJSVal,
 }
 
 impl CustomEventDerived for Event {
     fn is_customevent(&self) -> bool {
         *self.type_id() == EventTypeId::CustomEvent
     }
 }
--- a/servo/components/script/dom/dedicatedworkerglobalscope.rs
+++ b/servo/components/script/dom/dedicatedworkerglobalscope.rs
@@ -93,22 +93,27 @@ impl<'a> Drop for AutoWorkerReset<'a> {
 
 enum MixedMessage {
     FromWorker((TrustedWorkerAddress, ScriptMsg)),
     FromDevtools(DevtoolScriptControlMsg),
 }
 
 // https://html.spec.whatwg.org/multipage/#dedicatedworkerglobalscope
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct DedicatedWorkerGlobalScope {
     workerglobalscope: WorkerGlobalScope,
     id: PipelineId,
+    #[ignore_heap_size_of = "Defined in std"]
     receiver: Receiver<(TrustedWorkerAddress, ScriptMsg)>,
+    #[ignore_heap_size_of = "Defined in std"]
     own_sender: Sender<(TrustedWorkerAddress, ScriptMsg)>,
+    #[ignore_heap_size_of = "Trusted<T> has unclear ownership like JS<T>"]
     worker: DOMRefCell<Option<TrustedWorkerAddress>>,
+    #[ignore_heap_size_of = "Can't measure trait objects"]
     /// Sender to the parent thread.
     parent_sender: Box<ScriptChan+Send>,
 }
 
 impl DedicatedWorkerGlobalScope {
     fn new_inherited(init: WorkerGlobalScopeInit,
                      worker_url: Url,
                      id: PipelineId,
--- a/servo/components/script/dom/document.rs
+++ b/servo/components/script/dom/document.rs
@@ -100,17 +100,17 @@ use std::collections::hash_map::Entry::{
 use std::ascii::AsciiExt;
 use std::cell::{Cell, Ref, RefMut, RefCell};
 use std::default::Default;
 use std::ptr;
 use std::sync::mpsc::channel;
 use std::rc::Rc;
 use time;
 
-#[derive(JSTraceable, PartialEq)]
+#[derive(JSTraceable, PartialEq, HeapSizeOf)]
 pub enum IsHTMLDocument {
     HTMLDocument,
     NonHTMLDocument,
 }
 
 // https://dom.spec.whatwg.org/#document
 #[dom_struct]
 #[derive(HeapSizeOf)]
@@ -167,66 +167,66 @@ impl PartialEq for Document {
 }
 
 impl DocumentDerived for EventTarget {
     fn is_document(&self) -> bool {
         *self.type_id() == EventTargetTypeId::Node(NodeTypeId::Document)
     }
 }
 
-#[derive(JSTraceable)]
+#[derive(JSTraceable, HeapSizeOf)]
 struct ImagesFilter;
 impl CollectionFilter for ImagesFilter {
     fn filter(&self, elem: &Element, _root: &Node) -> bool {
         elem.is_htmlimageelement()
     }
 }
 
-#[derive(JSTraceable)]
+#[derive(JSTraceable, HeapSizeOf)]
 struct EmbedsFilter;
 impl CollectionFilter for EmbedsFilter {
     fn filter(&self, elem: &Element, _root: &Node) -> bool {
         elem.is_htmlembedelement()
     }
 }
 
-#[derive(JSTraceable)]
+#[derive(JSTraceable, HeapSizeOf)]
 struct LinksFilter;
 impl CollectionFilter for LinksFilter {
     fn filter(&self, elem: &Element, _root: &Node) -> bool {
         (elem.is_htmlanchorelement() || elem.is_htmlareaelement()) &&
             elem.has_attribute(&atom!("href"))
     }
 }
 
-#[derive(JSTraceable)]
+#[derive(JSTraceable, HeapSizeOf)]
 struct FormsFilter;
 impl CollectionFilter for FormsFilter {
     fn filter(&self, elem: &Element, _root: &Node) -> bool {
         elem.is_htmlformelement()
     }
 }
 
-#[derive(JSTraceable)]
+#[derive(JSTraceable, HeapSizeOf)]
 struct ScriptsFilter;
 impl CollectionFilter for ScriptsFilter {
     fn filter(&self, elem: &Element, _root: &Node) -> bool {
         elem.is_htmlscriptelement()
     }
 }
 
-#[derive(JSTraceable)]
+#[derive(JSTraceable, HeapSizeOf)]
 struct AnchorsFilter;
 impl CollectionFilter for AnchorsFilter {
     fn filter(&self, elem: &Element, _root: &Node) -> bool {
         elem.is_htmlanchorelement() && elem.has_attribute(&atom!("href"))
     }
 }
 
-#[derive(JSTraceable)]
+#[derive(JSTraceable, HeapSizeOf)]
 struct AppletsFilter;
 impl CollectionFilter for AppletsFilter {
     fn filter(&self, elem: &Element, _root: &Node) -> bool {
         elem.is_htmlappletelement()
     }
 }
 
 pub trait DocumentHelpers<'a> {
@@ -1049,24 +1049,25 @@ impl<'a> DocumentHelpers<'a> for &'a Doc
     /// Find an iframe element in the document.
     fn find_iframe(self, subpage_id: SubpageId) -> Option<Root<HTMLIFrameElement>> {
         NodeCast::from_ref(self).traverse_preorder()
             .filter_map(HTMLIFrameElementCast::to_root)
             .find(|node| node.r().subpage_id() == Some(subpage_id))
     }
 }
 
+#[derive(HeapSizeOf)]
 pub enum MouseEventType {
     Click,
     MouseDown,
     MouseUp,
 }
 
 
-#[derive(PartialEq)]
+#[derive(PartialEq, HeapSizeOf)]
 pub enum DocumentSource {
     FromParser,
     NotFromParser,
 }
 
 pub trait LayoutDocumentHelpers {
     #[allow(unsafe_code)]
     unsafe fn is_html_document_for_layout(&self) -> bool;
@@ -1823,17 +1824,17 @@ impl<'a> DocumentMethods for &'a Documen
     // https://html.spec.whatwg.org/multipage/#dom-document-bgcolor
     fn SetBgColor(self, value: DOMString) {
         self.set_body_attribute(&atom!("bgcolor"), value)
     }
 
     // https://html.spec.whatwg.org/multipage/#dom-tree-accessors:dom-document-nameditem-filter
     fn NamedGetter(self, _cx: *mut JSContext, name: DOMString, found: &mut bool)
                    -> *mut JSObject {
-        #[derive(JSTraceable)]
+        #[derive(JSTraceable, HeapSizeOf)]
         struct NamedElementFilter {
             name: Atom,
         }
         impl CollectionFilter for NamedElementFilter {
             fn filter(&self, elem: &Element, _root: &Node) -> bool {
                 filter_by_name(&self.name, NodeCast::from_ref(elem))
             }
         }
@@ -1914,16 +1915,17 @@ impl<'a> DocumentMethods for &'a Documen
     global_event_handlers!();
     event_handler!(readystatechange, GetOnreadystatechange, SetOnreadystatechange);
 }
 
 fn is_scheme_host_port_tuple(url: &Url) -> bool {
     url.host().is_some() && url.port_or_default().is_some()
 }
 
+#[derive(HeapSizeOf)]
 pub enum DocumentProgressTask {
     DOMContentLoaded,
     Load,
 }
 
 pub struct DocumentProgressHandler {
     addr: Trusted<Document>,
     task: DocumentProgressTask,
--- a/servo/components/script/dom/documentfragment.rs
+++ b/servo/components/script/dom/documentfragment.rs
@@ -16,16 +16,17 @@ use dom::element::Element;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::htmlcollection::HTMLCollection;
 use dom::node::{Node, NodeHelpers, NodeTypeId, window_from_node};
 use dom::nodelist::NodeList;
 use util::str::DOMString;
 
 // https://dom.spec.whatwg.org/#documentfragment
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct DocumentFragment {
     node: Node,
 }
 
 impl DocumentFragmentDerived for EventTarget {
     fn is_documentfragment(&self) -> bool {
         *self.type_id() == EventTargetTypeId::Node(NodeTypeId::DocumentFragment)
     }
--- a/servo/components/script/dom/documenttype.rs
+++ b/servo/components/script/dom/documenttype.rs
@@ -13,16 +13,17 @@ use dom::eventtarget::{EventTarget, Even
 use dom::node::{Node, NodeHelpers, NodeTypeId};
 use util::str::DOMString;
 
 use std::borrow::ToOwned;
 
 // https://dom.spec.whatwg.org/#documenttype
 /// The `DOCTYPE` tag.
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct DocumentType {
     node: Node,
     name: DOMString,
     public_id: DOMString,
     system_id: DOMString,
 }
 
 impl DocumentTypeDerived for EventTarget {
--- a/servo/components/script/dom/domexception.rs
+++ b/servo/components/script/dom/domexception.rs
@@ -8,17 +8,17 @@ use dom::bindings::codegen::Bindings::DO
 use dom::bindings::global::GlobalRef;
 use dom::bindings::js::Root;
 use dom::bindings::utils::{Reflector, reflect_dom_object};
 use util::str::DOMString;
 
 use std::borrow::ToOwned;
 
 #[repr(u16)]
-#[derive(JSTraceable, Copy, Clone, Debug)]
+#[derive(JSTraceable, Copy, Clone, Debug, HeapSizeOf)]
 pub enum DOMErrorName {
     IndexSizeError = DOMExceptionConstants::INDEX_SIZE_ERR,
     HierarchyRequestError = DOMExceptionConstants::HIERARCHY_REQUEST_ERR,
     WrongDocumentError = DOMExceptionConstants::WRONG_DOCUMENT_ERR,
     InvalidCharacterError = DOMExceptionConstants::INVALID_CHARACTER_ERR,
     NoModificationAllowedError = DOMExceptionConstants::NO_MODIFICATION_ALLOWED_ERR,
     NotFoundError = DOMExceptionConstants::NOT_FOUND_ERR,
     NotSupportedError = DOMExceptionConstants::NOT_SUPPORTED_ERR,
@@ -36,16 +36,17 @@ pub enum DOMErrorName {
     QuotaExceededError = DOMExceptionConstants::QUOTA_EXCEEDED_ERR,
     TimeoutError = DOMExceptionConstants::TIMEOUT_ERR,
     InvalidNodeTypeError = DOMExceptionConstants::INVALID_NODE_TYPE_ERR,
     DataCloneError = DOMExceptionConstants::DATA_CLONE_ERR,
     EncodingError
 }
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct DOMException {
     reflector_: Reflector,
     code: DOMErrorName,
 }
 
 impl DOMException {
     fn new_inherited(code: DOMErrorName) -> DOMException {
         DOMException {
--- a/servo/components/script/dom/domimplementation.rs
+++ b/servo/components/script/dom/domimplementation.rs
@@ -22,16 +22,17 @@ use dom::htmlhtmlelement::HTMLHtmlElemen
 use dom::htmltitleelement::HTMLTitleElement;
 use dom::text::Text;
 use util::str::DOMString;
 
 use std::borrow::ToOwned;
 
 // https://dom.spec.whatwg.org/#domimplementation
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct DOMImplementation {
     reflector_: Reflector,
     document: JS<Document>,
 }
 
 impl DOMImplementation {
     fn new_inherited(document: &Document) -> DOMImplementation {
         DOMImplementation {
--- a/servo/components/script/dom/domparser.rs
+++ b/servo/components/script/dom/domparser.rs
@@ -16,16 +16,17 @@ use dom::document::{Document, DocumentHe
 use dom::document::DocumentSource;
 use dom::window::{Window, WindowHelpers};
 use parse::html::{ParseContext, parse_html};
 use util::str::DOMString;
 
 use std::borrow::ToOwned;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct DOMParser {
     reflector_: Reflector,
     window: JS<Window>, //XXXjdm Document instead?
 }
 
 impl DOMParser {
     fn new_inherited(window: &Window) -> DOMParser {
         DOMParser {
--- a/servo/components/script/dom/dompoint.rs
+++ b/servo/components/script/dom/dompoint.rs
@@ -7,16 +7,17 @@ use dom::bindings::codegen::Bindings::DO
 use dom::bindings::error::Fallible;
 use dom::bindings::global::GlobalRef;
 use dom::bindings::js::Root;
 use dom::bindings::utils::reflect_dom_object;
 use dom::dompointreadonly::{DOMPointReadOnly, DOMPointWriteMethods};
 
 // http://dev.w3.org/fxtf/geometry/Overview.html#dompoint
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct DOMPoint {
     point: DOMPointReadOnly
 }
 
 impl DOMPoint {
     fn new_inherited(x: f64, y: f64, z: f64, w: f64) -> DOMPoint {
         DOMPoint {
             point: DOMPointReadOnly::new_inherited(x, y, z, w),
--- a/servo/components/script/dom/dompointreadonly.rs
+++ b/servo/components/script/dom/dompointreadonly.rs
@@ -6,16 +6,17 @@ use dom::bindings::codegen::Bindings::DO
 use dom::bindings::error::Fallible;
 use dom::bindings::global::GlobalRef;
 use dom::bindings::js::Root;
 use dom::bindings::utils::{Reflector, reflect_dom_object};
 use std::cell::Cell;
 
 // http://dev.w3.org/fxtf/geometry/Overview.html#dompointreadonly
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct DOMPointReadOnly {
     reflector_: Reflector,
     x: Cell<f64>,
     y: Cell<f64>,
     z: Cell<f64>,
     w: Cell<f64>,
 }
 
--- a/servo/components/script/dom/domrect.rs
+++ b/servo/components/script/dom/domrect.rs
@@ -7,16 +7,17 @@ use dom::bindings::codegen::Bindings::DO
 use dom::bindings::global::GlobalRef;
 use dom::bindings::js::Root;
 use dom::bindings::num::Finite;
 use dom::bindings::utils::{Reflector, reflect_dom_object};
 use dom::window::Window;
 use util::geometry::Au;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct DOMRect {
     reflector_: Reflector,
     top: f32,
     bottom: f32,
     left: f32,
     right: f32,
 }
 
--- a/servo/components/script/dom/domrectlist.rs
+++ b/servo/components/script/dom/domrectlist.rs
@@ -6,16 +6,17 @@ use dom::bindings::codegen::Bindings::DO
 use dom::bindings::codegen::Bindings::DOMRectListBinding::DOMRectListMethods;
 use dom::bindings::global::GlobalRef;
 use dom::bindings::js::{JS, Root};
 use dom::bindings::utils::{Reflector, reflect_dom_object};
 use dom::domrect::DOMRect;
 use dom::window::Window;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct DOMRectList {
     reflector_: Reflector,
     rects: Vec<JS<DOMRect>>,
 }
 
 impl DOMRectList {
     fn new_inherited<T>(rects: T) -> DOMRectList
                         where T: Iterator<Item=Root<DOMRect>> {
--- a/servo/components/script/dom/domstringmap.rs
+++ b/servo/components/script/dom/domstringmap.rs
@@ -8,16 +8,17 @@ use dom::bindings::error::ErrorResult;
 use dom::bindings::global::GlobalRef;
 use dom::bindings::js::{JS, Root};
 use dom::bindings::utils::{Reflector, reflect_dom_object};
 use dom::node::window_from_node;
 use dom::htmlelement::{HTMLElement, HTMLElementCustomAttributeHelpers};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct DOMStringMap {
     reflector_: Reflector,
     element: JS<HTMLElement>,
 }
 
 impl DOMStringMap {
     fn new_inherited(element: &HTMLElement) -> DOMStringMap {
         DOMStringMap {
--- a/servo/components/script/dom/domtokenlist.rs
+++ b/servo/components/script/dom/domtokenlist.rs
@@ -14,16 +14,17 @@ use dom::element::{Element, AttributeHan
 use dom::node::window_from_node;
 
 use util::str::{DOMString, HTML_SPACE_CHARACTERS, str_join};
 use string_cache::Atom;
 
 use std::borrow::ToOwned;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct DOMTokenList {
     reflector_: Reflector,
     element: JS<Element>,
     local_name: Atom,
 }
 
 impl DOMTokenList {
     pub fn new_inherited(element: &Element, local_name: Atom) -> DOMTokenList {
--- a/servo/components/script/dom/element.rs
+++ b/servo/components/script/dom/element.rs
@@ -87,16 +87,17 @@ use url::UrlParser;
 use std::ascii::AsciiExt;
 use std::borrow::{Cow, ToOwned};
 use std::cell::{Ref, RefMut};
 use std::default::Default;
 use std::mem;
 use std::sync::Arc;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct Element {
     node: Node,
     local_name: Atom,
     namespace: Namespace,
     prefix: Option<DOMString>,
     attrs: DOMRefCell<Vec<JS<Attr>>>,
     style_attribute: DOMRefCell<Option<PropertyDeclarationBlock>>,
     attr_list: MutNullableHeap<JS<NamedNodeMap>>,
@@ -120,17 +121,17 @@ impl PartialEq for Element {
 }
 
 #[derive(JSTraceable, Copy, Clone, PartialEq, Debug, HeapSizeOf)]
 pub enum ElementTypeId {
     HTMLElement(HTMLElementTypeId),
     Element,
 }
 
-#[derive(PartialEq)]
+#[derive(PartialEq, HeapSizeOf)]
 pub enum ElementCreator {
     ParserCreated,
     ScriptCreated,
 }
 
 //
 // Element methods
 //
@@ -557,17 +558,17 @@ impl LayoutElementHelpers for LayoutJS<E
             Some(input) => unsafe {
                 (*input.unsafe_get()).get_indeterminate_state_for_layout()
             },
             None => false,
         }
     }
 }
 
-#[derive(PartialEq, Eq, Copy, Clone)]
+#[derive(PartialEq, Eq, Copy, Clone, HeapSizeOf)]
 pub enum StylePriority {
     Important,
     Normal,
 }
 
 pub trait ElementHelpers<'a> {
     fn html_element_in_html_document(self) -> bool;
     fn local_name(self) -> &'a Atom;
--- a/servo/components/script/dom/errorevent.rs
+++ b/servo/components/script/dom/errorevent.rs
@@ -17,22 +17,24 @@ use dom::event::{Event, EventTypeId, Eve
 use util::str::DOMString;
 
 use dom::bindings::cell::DOMRefCell;
 use std::borrow::ToOwned;
 use std::cell::Cell;
 use js::jsval::JSVal;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct ErrorEvent {
     event: Event,
     message: DOMRefCell<DOMString>,
     filename: DOMRefCell<DOMString>,
     lineno: Cell<u32>,
     colno: Cell<u32>,
+    #[ignore_heap_size_of = "Defined in rust-mozjs"]
     error: MutHeapJSVal,
 }
 
 impl ErrorEventDerived for Event {
     fn is_errorevent(&self) -> bool {
         *self.type_id() == EventTypeId::ErrorEvent
     }
 }
--- a/servo/components/script/dom/event.rs
+++ b/servo/components/script/dom/event.rs
@@ -15,50 +15,52 @@ use util::str::DOMString;
 use std::borrow::ToOwned;
 use std::cell::Cell;
 use std::default::Default;
 
 use time;
 
 #[derive(JSTraceable, Copy, Clone)]
 #[repr(u16)]
+#[derive(HeapSizeOf)]
 pub enum EventPhase {
     None      = EventConstants::NONE,
     Capturing = EventConstants::CAPTURING_PHASE,
     AtTarget  = EventConstants::AT_TARGET,
     Bubbling  = EventConstants::BUBBLING_PHASE,
 }
 
-#[derive(JSTraceable, PartialEq)]
+#[derive(JSTraceable, PartialEq, HeapSizeOf)]
 pub enum EventTypeId {
     CustomEvent,
     HTMLEvent,
     KeyboardEvent,
     MessageEvent,
     MouseEvent,
     ProgressEvent,
     StorageEvent,
     UIEvent,
     ErrorEvent,
     CloseEvent
 }
 
-#[derive(PartialEq)]
+#[derive(PartialEq, HeapSizeOf)]
 pub enum EventBubbles {
     Bubbles,
     DoesNotBubble
 }
 
-#[derive(PartialEq)]
+#[derive(PartialEq, HeapSizeOf)]
 pub enum EventCancelable {
     Cancelable,
     NotCancelable
 }
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct Event {
     reflector_: Reflector,
     type_id: EventTypeId,
     current_target: MutNullableHeap<JS<EventTarget>>,
     target: MutNullableHeap<JS<EventTarget>>,
     type_: DOMRefCell<DOMString>,
     phase: Cell<EventPhase>,
     canceled: Cell<bool>,
--- a/servo/components/script/dom/file.rs
+++ b/servo/components/script/dom/file.rs
@@ -6,16 +6,17 @@ use dom::bindings::codegen::Bindings::Fi
 use dom::bindings::codegen::Bindings::FileBinding::FileMethods;
 use dom::bindings::global::GlobalRef;
 use dom::bindings::js::Root;
 use dom::bindings::utils::reflect_dom_object;
 use dom::blob::{Blob, BlobTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct File {
     blob: Blob,
     name: DOMString,
 }
 
 impl File {
     fn new_inherited(global: GlobalRef, type_: BlobTypeId,
                      _file_bits: &Blob, name: DOMString) -> File {
--- a/servo/components/script/dom/filelist.rs
+++ b/servo/components/script/dom/filelist.rs
@@ -7,16 +7,17 @@ use dom::bindings::codegen::Bindings::Fi
 use dom::bindings::global::GlobalRef;
 use dom::bindings::js::{JS, Root};
 use dom::bindings::utils::{Reflector, reflect_dom_object};
 use dom::file::File;
 use dom::window::Window;
 
 // https://w3c.github.io/FileAPI/#dfn-filelist
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct FileList {
     reflector_: Reflector,
     list: Vec<JS<File>>
 }
 
 impl FileList {
     fn new_inherited(files: Vec<JS<File>>) -> FileList {
         FileList {
--- a/servo/components/script/dom/filereader.rs
+++ b/servo/components/script/dom/filereader.rs
@@ -24,25 +24,25 @@ use hyper::mime::{Mime, Attr};
 use std::sync::mpsc;
 use script_task::{ScriptChan, ScriptMsg, Runnable, ScriptPort};
 use std::cell::{Cell, RefCell};
 use std::sync::mpsc::Receiver;
 use util::str::DOMString;
 use util::task::spawn_named;
 use rustc_serialize::base64::{Config, ToBase64, CharacterSet, Newline};
 
-#[derive(PartialEq, Clone, Copy, JSTraceable)]
+#[derive(PartialEq, Clone, Copy, JSTraceable, HeapSizeOf)]
 pub enum FileReaderFunction {
     ReadAsText,
     ReadAsDataUrl,
 }
 
 pub type TrustedFileReader = Trusted<FileReader>;
 
-#[derive(Clone)]
+#[derive(Clone, HeapSizeOf)]
 pub struct ReadMetaData {
     pub blobtype: DOMString,
     pub label: Option<DOMString>,
     pub function: FileReaderFunction
 }
 
 impl ReadMetaData {
     pub fn new(blobtype: DOMString,
@@ -50,28 +50,29 @@ impl ReadMetaData {
         ReadMetaData {
             blobtype: blobtype,
             label: label,
             function: function,
         }
     }
 }
 
-#[derive(PartialEq, Clone, Copy, JSTraceable)]
+#[derive(PartialEq, Clone, Copy, JSTraceable, HeapSizeOf)]
 pub struct GenerationId(u32);
 
 #[repr(u16)]
-#[derive(Copy, Clone, Debug, PartialEq, JSTraceable)]
+#[derive(Copy, Clone, Debug, PartialEq, JSTraceable, HeapSizeOf)]
 pub enum FileReaderReadyState {
     Empty = FileReaderConstants::EMPTY,
     Loading = FileReaderConstants::LOADING,
     Done = FileReaderConstants::DONE,
 }
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct FileReader {
     eventtarget: EventTarget,
     global: GlobalField,
     ready_state: Cell<FileReaderReadyState>,
     error: MutNullableHeap<JS<DOMException>>,
     result: RefCell<Option<DOMString>>,
     generation_id: Cell<GenerationId>,
 }
--- a/servo/components/script/dom/formdata.rs
+++ b/servo/components/script/dom/formdata.rs
@@ -18,22 +18,24 @@ use dom::htmlformelement::HTMLFormElemen
 use util::str::DOMString;
 
 use std::borrow::ToOwned;
 use std::collections::HashMap;
 use std::collections::hash_map::Entry::{Occupied, Vacant};
 
 #[derive(JSTraceable, Clone)]
 #[must_root]
+#[derive(HeapSizeOf)]
 pub enum FormDatum {
     StringData(DOMString),
     FileData(JS<File>)
 }
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct FormData {
     reflector_: Reflector,
     data: DOMRefCell<HashMap<DOMString, Vec<FormDatum>>>,
     global: GlobalField,
     form: Option<JS<HTMLFormElement>>
 }
 
 impl FormData {
--- a/servo/components/script/dom/htmlanchorelement.rs
+++ b/servo/components/script/dom/htmlanchorelement.rs
@@ -28,16 +28,17 @@ use util::str::DOMString;
 
 use num::ToPrimitive;
 use string_cache::Atom;
 use url::UrlParser;
 
 use std::default::Default;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLAnchorElement {
     htmlelement: HTMLElement,
     rel_list: MutNullableHeap<JS<DOMTokenList>>,
 }
 
 impl HTMLAnchorElementDerived for EventTarget {
     fn is_htmlanchorelement(&self) -> bool {
         *self.type_id() ==
--- a/servo/components/script/dom/htmlappletelement.rs
+++ b/servo/components/script/dom/htmlappletelement.rs
@@ -15,16 +15,17 @@ use dom::eventtarget::{EventTarget, Even
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use dom::virtualmethods::VirtualMethods;
 
 use string_cache::Atom;
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLAppletElement {
     htmlelement: HTMLElement
 }
 
 impl HTMLAppletElementDerived for EventTarget {
     fn is_htmlappletelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmlareaelement.rs
+++ b/servo/components/script/dom/htmlareaelement.rs
@@ -17,16 +17,17 @@ use dom::htmlelement::{HTMLElement, HTML
 use dom::node::{Node, NodeHelpers, NodeTypeId};
 use dom::virtualmethods::VirtualMethods;
 
 use std::default::Default;
 use string_cache::Atom;
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLAreaElement {
     htmlelement: HTMLElement,
     rel_list: MutNullableHeap<JS<DOMTokenList>>,
 }
 
 impl HTMLAreaElementDerived for EventTarget {
     fn is_htmlareaelement(&self) -> bool {
         *self.type_id() ==
--- a/servo/components/script/dom/htmlaudioelement.rs
+++ b/servo/components/script/dom/htmlaudioelement.rs
@@ -9,16 +9,17 @@ use dom::document::Document;
 use dom::element::ElementTypeId;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::htmlelement::HTMLElementTypeId;
 use dom::htmlmediaelement::{HTMLMediaElement, HTMLMediaElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLAudioElement {
     htmlmediaelement: HTMLMediaElement
 }
 
 impl HTMLAudioElementDerived for EventTarget {
     fn is_htmlaudioelement(&self) -> bool {
         *self.type_id() == EventTargetTypeId::Node(NodeTypeId::Element(
                                                    ElementTypeId::HTMLElement(
--- a/servo/components/script/dom/htmlbaseelement.rs
+++ b/servo/components/script/dom/htmlbaseelement.rs
@@ -14,16 +14,17 @@ use dom::element::{ElementTypeId, Attrib
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId, document_from_node};
 use dom::virtualmethods::VirtualMethods;
 use util::str::DOMString;
 
 use url::{Url, UrlParser};
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLBaseElement {
     htmlelement: HTMLElement
 }
 
 impl HTMLBaseElementDerived for EventTarget {
     fn is_htmlbaseelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmlbodyelement.rs
+++ b/servo/components/script/dom/htmlbodyelement.rs
@@ -30,16 +30,17 @@ use std::cell::Cell;
 use std::rc::Rc;
 use time;
 
 /// How long we should wait before performing the initial reflow after `<body>` is parsed, in
 /// nanoseconds.
 const INITIAL_REFLOW_DELAY: u64 = 200_000_000;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLBodyElement {
     htmlelement: HTMLElement,
     background_color: Cell<Option<RGBA>>,
     background: DOMRefCell<Option<Url>>
 }
 
 impl HTMLBodyElementDerived for EventTarget {
     fn is_htmlbodyelement(&self) -> bool {
--- a/servo/components/script/dom/htmlbrelement.rs
+++ b/servo/components/script/dom/htmlbrelement.rs
@@ -8,16 +8,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLBRElement {
     htmlelement: HTMLElement,
 }
 
 impl HTMLBRElementDerived for EventTarget {
     fn is_htmlbrelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmlbuttonelement.rs
+++ b/servo/components/script/dom/htmlbuttonelement.rs
@@ -24,24 +24,26 @@ use dom::virtualmethods::VirtualMethods;
 
 use std::ascii::AsciiExt;
 use std::borrow::ToOwned;
 use util::str::DOMString;
 use std::cell::Cell;
 
 #[derive(JSTraceable, PartialEq, Copy, Clone)]
 #[allow(dead_code)]
+#[derive(HeapSizeOf)]
 enum ButtonType {
     ButtonSubmit,
     ButtonReset,
     ButtonButton,
     ButtonMenu
 }
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLButtonElement {
     htmlelement: HTMLElement,
     button_type: Cell<ButtonType>
 }
 
 impl HTMLButtonElementDerived for EventTarget {
     fn is_htmlbuttonelement(&self) -> bool {
         *self.type_id() ==
--- a/servo/components/script/dom/htmlcanvaselement.rs
+++ b/servo/components/script/dom/htmlcanvaselement.rs
@@ -33,25 +33,26 @@ use euclid::size::Size2D;
 
 use std::cell::Cell;
 use std::default::Default;
 
 const DEFAULT_WIDTH: u32 = 300;
 const DEFAULT_HEIGHT: u32 = 150;
 
 #[must_root]
-#[derive(JSTraceable, Clone, Copy)]
+#[derive(JSTraceable, Clone, Copy, HeapSizeOf)]
 pub enum CanvasContext {
     Context2d(JS<CanvasRenderingContext2D>),
     WebGL(JS<WebGLRenderingContext>),
 }
 
 impl HeapGCValue for CanvasContext {}
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLCanvasElement {
     htmlelement: HTMLElement,
     context: MutNullableHeap<CanvasContext>,
     width: Cell<u32>,
     height: Cell<u32>,
 }
 
 impl PartialEq for HTMLCanvasElement {
--- a/servo/components/script/dom/htmlcollection.rs
+++ b/servo/components/script/dom/htmlcollection.rs
@@ -25,18 +25,20 @@ pub trait CollectionFilter : JSTraceable
 #[derive(JSTraceable)]
 #[must_root]
 pub enum CollectionTypeId {
     Static(Vec<JS<Element>>),
     Live(JS<Node>, Box<CollectionFilter+'static>)
 }
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLCollection {
     reflector_: Reflector,
+    #[ignore_heap_size_of = "Contains a trait object; can't measure due to #6870"]
     collection: CollectionTypeId,
 }
 
 impl HTMLCollection {
     fn new_inherited(collection: CollectionTypeId) -> HTMLCollection {
         HTMLCollection {
             reflector_: Reflector::new(),
             collection: collection,
@@ -52,17 +54,17 @@ impl HTMLCollection {
 impl HTMLCollection {
     pub fn create(window: &Window, root: &Node,
                   filter: Box<CollectionFilter+'static>) -> Root<HTMLCollection> {
         HTMLCollection::new(window, CollectionTypeId::Live(JS::from_ref(root), filter))
     }
 
     fn all_elements(window: &Window, root: &Node,
                     namespace_filter: Option<Namespace>) -> Root<HTMLCollection> {
-        #[derive(JSTraceable)]
+        #[derive(JSTraceable, HeapSizeOf)]
         struct AllElementFilter {
             namespace_filter: Option<Namespace>
         }
         impl CollectionFilter for AllElementFilter {
             fn filter(&self, elem: &Element, _root: &Node) -> bool {
                 match self.namespace_filter {
                     None => true,
                     Some(ref namespace) => *elem.namespace() == *namespace
@@ -74,17 +76,17 @@ impl HTMLCollection {
     }
 
     pub fn by_tag_name(window: &Window, root: &Node, tag: DOMString)
                        -> Root<HTMLCollection> {
         if tag == "*" {
             return HTMLCollection::all_elements(window, root, None);
         }
 
-        #[derive(JSTraceable)]
+        #[derive(JSTraceable, HeapSizeOf)]
         struct TagNameFilter {
             tag: Atom,
             ascii_lower_tag: Atom,
         }
         impl CollectionFilter for TagNameFilter {
             fn filter(&self, elem: &Element, _root: &Node) -> bool {
                 if elem.html_element_in_html_document() {
                     *elem.local_name() == self.ascii_lower_tag
@@ -105,17 +107,17 @@ impl HTMLCollection {
         let namespace_filter = match maybe_ns {
             Some(ref namespace) if namespace == &"*" => None,
             ns => Some(namespace_from_domstring(ns)),
         };
 
         if tag == "*" {
             return HTMLCollection::all_elements(window, root, namespace_filter);
         }
-        #[derive(JSTraceable)]
+        #[derive(JSTraceable, HeapSizeOf)]
         struct TagNameNSFilter {
             tag: Atom,
             namespace_filter: Option<Namespace>
         }
         impl CollectionFilter for TagNameNSFilter {
             fn filter(&self, elem: &Element, _root: &Node) -> bool {
                 let ns_match = match self.namespace_filter {
                     Some(ref namespace) => {
@@ -130,17 +132,17 @@ impl HTMLCollection {
             tag: Atom::from_slice(&tag),
             namespace_filter: namespace_filter
         };
         HTMLCollection::create(window, root, box filter)
     }
 
     pub fn by_class_name(window: &Window, root: &Node, classes: DOMString)
                          -> Root<HTMLCollection> {
-        #[derive(JSTraceable)]
+        #[derive(JSTraceable, HeapSizeOf)]
         struct ClassNameFilter {
             classes: Vec<Atom>
         }
         impl CollectionFilter for ClassNameFilter {
             fn filter(&self, elem: &Element, _root: &Node) -> bool {
                 self.classes.iter().all(|class| elem.has_class(class))
             }
         }
@@ -148,17 +150,17 @@ impl HTMLCollection {
             classes: split_html_space_chars(&classes).map(|class| {
                          Atom::from_slice(class)
                      }).collect()
         };
         HTMLCollection::create(window, root, box filter)
     }
 
     pub fn children(window: &Window, root: &Node) -> Root<HTMLCollection> {
-        #[derive(JSTraceable)]
+        #[derive(JSTraceable, HeapSizeOf)]
         struct ElementChildFilter;
         impl CollectionFilter for ElementChildFilter {
             fn filter(&self, elem: &Element, root: &Node) -> bool {
                 root.is_parent_of(NodeCast::from_ref(elem))
             }
         }
         HTMLCollection::create(window, root, box ElementChildFilter)
     }
--- a/servo/components/script/dom/htmldataelement.rs
+++ b/servo/components/script/dom/htmldataelement.rs
@@ -8,16 +8,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLDataElement {
     htmlelement: HTMLElement
 }
 
 impl HTMLDataElementDerived for EventTarget {
     fn is_htmldataelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmldatalistelement.rs
+++ b/servo/components/script/dom/htmldatalistelement.rs
@@ -12,16 +12,17 @@ use dom::element::Element;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::htmlcollection::{HTMLCollection, CollectionFilter};
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId, window_from_node};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLDataListElement {
     htmlelement: HTMLElement
 }
 
 impl HTMLDataListElementDerived for EventTarget {
     fn is_htmldatalistelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
@@ -46,17 +47,17 @@ impl HTMLDataListElement {
         let element = HTMLDataListElement::new_inherited(localName, prefix, document);
         Node::reflect_node(box element, document, HTMLDataListElementBinding::Wrap)
     }
 }
 
 impl<'a> HTMLDataListElementMethods for &'a HTMLDataListElement {
     // https://html.spec.whatwg.org/multipage/#dom-datalist-options
     fn Options(self) -> Root<HTMLCollection> {
-        #[derive(JSTraceable)]
+        #[derive(JSTraceable, HeapSizeOf)]
         struct HTMLDataListOptionsFilter;
         impl CollectionFilter for HTMLDataListOptionsFilter {
             fn filter(&self, elem: &Element, _root: &Node) -> bool {
                 elem.is_htmloptionelement()
             }
         }
         let node = NodeCast::from_ref(self);
         let filter = box HTMLDataListOptionsFilter;
--- a/servo/components/script/dom/htmldialogelement.rs
+++ b/servo/components/script/dom/htmldialogelement.rs
@@ -13,16 +13,17 @@ use dom::eventtarget::{EventTarget, Even
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 
 use util::str::DOMString;
 
 use std::borrow::ToOwned;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLDialogElement {
     htmlelement: HTMLElement,
     return_value: DOMRefCell<DOMString>,
 }
 
 impl HTMLDialogElementDerived for EventTarget {
     fn is_htmldialogelement(&self) -> bool {
         *self.type_id() ==
--- a/servo/components/script/dom/htmldirectoryelement.rs
+++ b/servo/components/script/dom/htmldirectoryelement.rs
@@ -8,16 +8,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::element::ElementTypeId;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLDirectoryElement {
     htmlelement: HTMLElement
 }
 
 impl HTMLDirectoryElementDerived for EventTarget {
     fn is_htmldirectoryelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmldivelement.rs
+++ b/servo/components/script/dom/htmldivelement.rs
@@ -8,16 +8,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::element::ElementTypeId;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLDivElement {
     htmlelement: HTMLElement
 }
 
 impl HTMLDivElementDerived for EventTarget {
     fn is_htmldivelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmldlistelement.rs
+++ b/servo/components/script/dom/htmldlistelement.rs
@@ -8,16 +8,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::element::ElementTypeId;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLDListElement {
     htmlelement: HTMLElement
 }
 
 impl HTMLDListElementDerived for EventTarget {
     fn is_htmldlistelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmlelement.rs
+++ b/servo/components/script/dom/htmlelement.rs
@@ -35,16 +35,17 @@ use util::str::DOMString;
 use string_cache::Atom;
 
 use std::borrow::ToOwned;
 use std::default::Default;
 use std::intrinsics;
 use std::rc::Rc;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLElement {
     element: Element,
     style_decl: MutNullableHeap<JS<CSSStyleDeclaration>>,
     dataset: MutNullableHeap<JS<DOMStringMap>>,
 }
 
 impl PartialEq for HTMLElement {
     fn eq(&self, other: &HTMLElement) -> bool {
--- a/servo/components/script/dom/htmlembedelement.rs
+++ b/servo/components/script/dom/htmlembedelement.rs
@@ -8,16 +8,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::element::ElementTypeId;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLEmbedElement {
     htmlelement: HTMLElement
 }
 
 impl HTMLEmbedElementDerived for EventTarget {
     fn is_htmlembedelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmlfieldsetelement.rs
+++ b/servo/components/script/dom/htmlfieldsetelement.rs
@@ -17,16 +17,17 @@ use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{DisabledStateHelpers, Node, NodeHelpers, NodeTypeId, window_from_node};
 use dom::validitystate::ValidityState;
 use dom::virtualmethods::VirtualMethods;
 
 use util::str::{DOMString, StaticStringVec};
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLFieldSetElement {
     htmlelement: HTMLElement
 }
 
 impl HTMLFieldSetElementDerived for EventTarget {
     fn is_htmlfieldsetelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
@@ -51,17 +52,17 @@ impl HTMLFieldSetElement {
         let element = HTMLFieldSetElement::new_inherited(localName, prefix, document);
         Node::reflect_node(box element, document, HTMLFieldSetElementBinding::Wrap)
     }
 }
 
 impl<'a> HTMLFieldSetElementMethods for &'a HTMLFieldSetElement {
     // https://www.whatwg.org/html/#dom-fieldset-elements
     fn Elements(self) -> Root<HTMLCollection> {
-        #[derive(JSTraceable)]
+        #[derive(JSTraceable, HeapSizeOf)]
         struct ElementsFilter;
         impl CollectionFilter for ElementsFilter {
             fn filter<'a>(&self, elem: &'a Element, _root: &'a Node) -> bool {
                 static TAG_NAMES: StaticStringVec = &["button", "fieldset", "input",
                     "keygen", "object", "output", "select", "textarea"];
                 TAG_NAMES.iter().any(|&tag_name| tag_name == &**elem.local_name())
             }
         }
--- a/servo/components/script/dom/htmlfontelement.rs
+++ b/servo/components/script/dom/htmlfontelement.rs
@@ -14,16 +14,17 @@ use dom::htmlelement::{HTMLElement, HTML
 use dom::node::{Node, NodeTypeId};
 use dom::virtualmethods::VirtualMethods;
 use util::str::{self, DOMString};
 
 use cssparser::RGBA;
 use std::cell::Cell;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLFontElement {
     htmlelement: HTMLElement,
     color: Cell<Option<RGBA>>,
 }
 
 impl HTMLFontElementDerived for EventTarget {
     fn is_htmlfontelement(&self) -> bool {
         *self.type_id() ==
--- a/servo/components/script/dom/htmlformelement.rs
+++ b/servo/components/script/dom/htmlformelement.rs
@@ -38,16 +38,17 @@ use script_task::{ScriptChan, ScriptMsg}
 use url::UrlParser;
 use url::form_urlencoded::serialize;
 use string_cache::Atom;
 
 use std::borrow::ToOwned;
 use std::cell::Cell;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLFormElement {
     htmlelement: HTMLElement,
     marked_for_reset: Cell<bool>,
 }
 
 impl PartialEq for HTMLFormElement {
     fn eq(&self, other: &HTMLFormElement) -> bool {
         self as *const HTMLFormElement == &*other
@@ -144,23 +145,23 @@ impl<'a> HTMLFormElementMethods for &'a 
     }
 
     // https://html.spec.whatwg.org/multipage/#dom-form-reset
     fn Reset(self) {
         self.reset(ResetFrom::FromFormResetMethod);
     }
 }
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, HeapSizeOf)]
 pub enum SubmittedFrom {
     FromFormSubmitMethod,
     NotFromFormSubmitMethod
 }
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, HeapSizeOf)]
 pub enum ResetFrom {
     FromFormResetMethod,
     NotFromFormResetMethod
 }
 
 pub trait HTMLFormElementHelpers {
     // https://html.spec.whatwg.org/multipage/#concept-form-submit
     fn submit(self, submit_method_flag: SubmittedFrom, submitter: FormSubmitter);
@@ -410,37 +411,38 @@ impl<'a> HTMLFormElementHelpers for &'a 
                 _ => {}
             }
         };
         self.marked_for_reset.set(false);
     }
 }
 
 // TODO: add file support
+#[derive(HeapSizeOf)]
 pub struct FormDatum {
     pub ty: DOMString,
     pub name: DOMString,
     pub value: DOMString
 }
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, HeapSizeOf)]
 pub enum FormEncType {
     TextPlainEncoded,
     UrlEncoded,
     FormDataEncoded
 }
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, HeapSizeOf)]
 pub enum FormMethod {
     FormGet,
     FormPost,
     FormDialog
 }
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, HeapSizeOf)]
 pub enum FormSubmitter<'a> {
     FormElement(&'a HTMLFormElement),
     InputElement(&'a HTMLInputElement),
     ButtonElement(&'a HTMLButtonElement)
     // TODO: image submit, etc etc
 }
 
 impl<'a> FormSubmitter<'a> {
--- a/servo/components/script/dom/htmlframeelement.rs
+++ b/servo/components/script/dom/htmlframeelement.rs
@@ -8,16 +8,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLFrameElement {
     htmlelement: HTMLElement
 }
 
 impl HTMLFrameElementDerived for EventTarget {
     fn is_htmlframeelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmlframesetelement.rs
+++ b/servo/components/script/dom/htmlframesetelement.rs
@@ -8,16 +8,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLFrameSetElement {
     htmlelement: HTMLElement
 }
 
 impl HTMLFrameSetElementDerived for EventTarget {
     fn is_htmlframesetelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmlheadelement.rs
+++ b/servo/components/script/dom/htmlheadelement.rs
@@ -10,16 +10,17 @@ use dom::eventtarget::{EventTarget, Even
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use dom::userscripts::load_script;
 use dom::virtualmethods::VirtualMethods;
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLHeadElement {
     htmlelement: HTMLElement
 }
 
 impl HTMLHeadElementDerived for EventTarget {
     fn is_htmlheadelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmlheadingelement.rs
+++ b/servo/components/script/dom/htmlheadingelement.rs
@@ -7,27 +7,28 @@ use dom::bindings::codegen::InheritTypes
 use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
-#[derive(JSTraceable)]
+#[derive(JSTraceable, HeapSizeOf)]
 pub enum HeadingLevel {
     Heading1,
     Heading2,
     Heading3,
     Heading4,
     Heading5,
     Heading6,
 }
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLHeadingElement {
     htmlelement: HTMLElement,
     level: HeadingLevel,
 }
 
 impl HTMLHeadingElementDerived for EventTarget {
     fn is_htmlheadingelement(&self) -> bool {
         *self.type_id() ==
--- a/servo/components/script/dom/htmlhrelement.rs
+++ b/servo/components/script/dom/htmlhrelement.rs
@@ -8,16 +8,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLHRElement {
     htmlelement: HTMLElement,
 }
 
 impl HTMLHRElementDerived for EventTarget {
     fn is_htmlhrelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmlhtmlelement.rs
+++ b/servo/components/script/dom/htmlhtmlelement.rs
@@ -8,16 +8,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLHtmlElement {
     htmlelement: HTMLElement
 }
 
 impl HTMLHtmlElementDerived for EventTarget {
     fn is_htmlhtmlelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmliframeelement.rs
+++ b/servo/components/script/dom/htmliframeelement.rs
@@ -38,27 +38,29 @@ use string_cache::Atom;
 use std::ascii::AsciiExt;
 use std::borrow::ToOwned;
 use std::cell::Cell;
 use url::{Url, UrlParser};
 use util::str::{self, LengthOrPercentageOrAuto};
 use js::jsapi::{RootedValue, JSAutoRequest, JSAutoCompartment};
 use js::jsval::UndefinedValue;
 
+#[derive(HeapSizeOf)]
 enum SandboxAllowance {
     AllowNothing = 0x00,
     AllowSameOrigin = 0x01,
     AllowTopNavigation = 0x02,
     AllowForms = 0x04,
     AllowScripts = 0x08,
     AllowPointerLock = 0x10,
     AllowPopups = 0x20
 }
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLIFrameElement {
     htmlelement: HTMLElement,
     subpage_id: Cell<Option<SubpageId>>,
     containing_page_pipeline_id: Cell<Option<PipelineId>>,
     sandbox: Cell<Option<u8>>,
 }
 
 impl HTMLIFrameElementDerived for EventTarget {
--- a/servo/components/script/dom/htmlimageelement.rs
+++ b/servo/components/script/dom/htmlimageelement.rs
@@ -32,16 +32,17 @@ use ipc_channel::router::ROUTER;
 use net_traits::image::base::Image;
 use net_traits::image_cache_task::{ImageResponder, ImageResponse};
 use url::{Url, UrlParser};
 
 use std::borrow::ToOwned;
 use std::sync::Arc;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLImageElement {
     htmlelement: HTMLElement,
     url: DOMRefCell<Option<Url>>,
     image: DOMRefCell<Option<Arc<Image>>>,
 }
 
 impl HTMLImageElementDerived for EventTarget {
     fn is_htmlimageelement(&self) -> bool {
--- a/servo/components/script/dom/htmlinputelement.rs
+++ b/servo/components/script/dom/htmlinputelement.rs
@@ -41,50 +41,54 @@ use string_cache::Atom;
 use std::borrow::ToOwned;
 use std::cell::Cell;
 
 const DEFAULT_SUBMIT_VALUE: &'static str = "Submit";
 const DEFAULT_RESET_VALUE: &'static str = "Reset";
 
 #[derive(JSTraceable, PartialEq, Copy, Clone)]
 #[allow(dead_code)]
+#[derive(HeapSizeOf)]
 enum InputType {
     InputSubmit,
     InputReset,
     InputButton,
     InputText,
     InputFile,
     InputImage,
     InputCheckbox,
     InputRadio,
     InputPassword
 }
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLInputElement {
     htmlelement: HTMLElement,
     input_type: Cell<InputType>,
     checked: Cell<bool>,
     checked_changed: Cell<bool>,
     placeholder: DOMRefCell<DOMString>,
     indeterminate: Cell<bool>,
     value_changed: Cell<bool>,
     size: Cell<u32>,
+    #[ignore_heap_size_of = "#7193"]
     textinput: DOMRefCell<TextInput<ConstellationChan>>,
     activation_state: DOMRefCell<InputActivationState>,
 }
 
 impl PartialEq for HTMLInputElement {
     fn eq(&self, other: &HTMLInputElement) -> bool {
         self as *const HTMLInputElement == &*other
     }
 }
 
 #[derive(JSTraceable)]
 #[must_root]
+#[derive(HeapSizeOf)]
 struct InputActivationState {
     indeterminate: bool,
     checked: bool,
     checked_changed: bool,
     checked_radio: Option<JS<HTMLInputElement>>,
     // In case mutability changed
     was_mutable: bool,
     // In case the type changed
--- a/servo/components/script/dom/htmllabelelement.rs
+++ b/servo/components/script/dom/htmllabelelement.rs
@@ -8,16 +8,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLLabelElement {
     htmlelement: HTMLElement,
 }
 
 impl HTMLLabelElementDerived for EventTarget {
     fn is_htmllabelelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmllegendelement.rs
+++ b/servo/components/script/dom/htmllegendelement.rs
@@ -8,16 +8,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLLegendElement {
     htmlelement: HTMLElement,
 }
 
 impl HTMLLegendElementDerived for EventTarget {
     fn is_htmllegendelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmllielement.rs
+++ b/servo/components/script/dom/htmllielement.rs
@@ -8,16 +8,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLLIElement {
     htmlelement: HTMLElement,
 }
 
 impl HTMLLIElementDerived for EventTarget {
     fn is_htmllielement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmllinkelement.rs
+++ b/servo/components/script/dom/htmllinkelement.rs
@@ -34,16 +34,17 @@ use cssparser::Parser as CssParser;
 
 use std::ascii::AsciiExt;
 use std::borrow::ToOwned;
 use std::default::Default;
 use url::UrlParser;
 use string_cache::Atom;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLLinkElement {
     htmlelement: HTMLElement,
     rel_list: MutNullableHeap<JS<DOMTokenList>>,
 }
 
 impl HTMLLinkElementDerived for EventTarget {
     fn is_htmllinkelement(&self) -> bool {
         *self.type_id() ==
--- a/servo/components/script/dom/htmlmapelement.rs
+++ b/servo/components/script/dom/htmlmapelement.rs
@@ -8,16 +8,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLMapElement {
     htmlelement: HTMLElement
 }
 
 impl HTMLMapElementDerived for EventTarget {
     fn is_htmlmapelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmlmediaelement.rs
+++ b/servo/components/script/dom/htmlmediaelement.rs
@@ -6,16 +6,17 @@ use dom::bindings::codegen::InheritTypes
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::NodeTypeId;
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLMediaElement {
     htmlelement: HTMLElement,
 }
 
 impl HTMLMediaElementDerived for EventTarget {
     fn is_htmlmediaelement(&self) -> bool {
         match *self.type_id() {
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmlmetaelement.rs
+++ b/servo/components/script/dom/htmlmetaelement.rs
@@ -9,16 +9,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLMetaElement {
     htmlelement: HTMLElement,
 }
 
 impl HTMLMetaElementDerived for EventTarget {
     fn is_htmlmetaelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmlmeterelement.rs
+++ b/servo/components/script/dom/htmlmeterelement.rs
@@ -8,16 +8,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLMeterElement {
     htmlelement: HTMLElement
 }
 
 impl HTMLMeterElementDerived for EventTarget {
     fn is_htmlmeterelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmlmodelement.rs
+++ b/servo/components/script/dom/htmlmodelement.rs
@@ -8,16 +8,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLModElement {
     htmlelement: HTMLElement
 }
 
 impl HTMLModElementDerived for EventTarget {
     fn is_htmlmodelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmlobjectelement.rs
+++ b/servo/components/script/dom/htmlobjectelement.rs
@@ -20,16 +20,17 @@ use dom::node::{Node, NodeTypeId, NodeHe
 use dom::validitystate::ValidityState;
 use dom::virtualmethods::VirtualMethods;
 
 use net_traits::image::base::Image;
 use util::str::DOMString;
 use std::sync::Arc;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLObjectElement {
     htmlelement: HTMLElement,
     image: DOMRefCell<Option<Arc<Image>>>,
 }
 
 impl HTMLObjectElementDerived for EventTarget {
     fn is_htmlobjectelement(&self) -> bool {
         *self.type_id() ==
--- a/servo/components/script/dom/htmlolistelement.rs
+++ b/servo/components/script/dom/htmlolistelement.rs
@@ -8,16 +8,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLOListElement {
     htmlelement: HTMLElement,
 }
 
 impl HTMLOListElementDerived for EventTarget {
     fn is_htmlolistelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmloptgroupelement.rs
+++ b/servo/components/script/dom/htmloptgroupelement.rs
@@ -15,16 +15,17 @@ use dom::eventtarget::{EventTarget, Even
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{DisabledStateHelpers, Node, NodeHelpers, NodeTypeId};
 use dom::virtualmethods::VirtualMethods;
 
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLOptGroupElement {
     htmlelement: HTMLElement
 }
 
 impl HTMLOptGroupElementDerived for EventTarget {
     fn is_htmloptgroupelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmloptionelement.rs
+++ b/servo/components/script/dom/htmloptionelement.rs
@@ -18,16 +18,17 @@ use dom::eventtarget::{EventTarget, Even
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{DisabledStateHelpers, Node, NodeHelpers, NodeTypeId};
 use dom::virtualmethods::VirtualMethods;
 
 use util::str::{DOMString, split_html_space_chars};
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLOptionElement {
     htmlelement: HTMLElement
 }
 
 impl HTMLOptionElementDerived for EventTarget {
     fn is_htmloptionelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmloutputelement.rs
+++ b/servo/components/script/dom/htmloutputelement.rs
@@ -10,16 +10,17 @@ use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId, window_from_node};
 use dom::validitystate::ValidityState;
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLOutputElement {
     htmlelement: HTMLElement
 }
 
 impl HTMLOutputElementDerived for EventTarget {
     fn is_htmloutputelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmlparagraphelement.rs
+++ b/servo/components/script/dom/htmlparagraphelement.rs
@@ -8,16 +8,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLParagraphElement {
     htmlelement: HTMLElement
 }
 
 impl HTMLParagraphElementDerived for EventTarget {
     fn is_htmlparagraphelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmlparamelement.rs
+++ b/servo/components/script/dom/htmlparamelement.rs
@@ -8,16 +8,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLParamElement {
     htmlelement: HTMLElement
 }
 
 impl HTMLParamElementDerived for EventTarget {
     fn is_htmlparamelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmlpreelement.rs
+++ b/servo/components/script/dom/htmlpreelement.rs
@@ -8,16 +8,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLPreElement {
     htmlelement: HTMLElement,
 }
 
 impl HTMLPreElementDerived for EventTarget {
     fn is_htmlpreelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmlprogresselement.rs
+++ b/servo/components/script/dom/htmlprogresselement.rs
@@ -8,16 +8,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLProgressElement {
     htmlelement: HTMLElement,
 }
 
 impl HTMLProgressElementDerived for EventTarget {
     fn is_htmlprogresselement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmlquoteelement.rs
+++ b/servo/components/script/dom/htmlquoteelement.rs
@@ -8,16 +8,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLQuoteElement {
     htmlelement: HTMLElement,
 }
 
 impl HTMLQuoteElementDerived for EventTarget {
     fn is_htmlquoteelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmlscriptelement.rs
+++ b/servo/components/script/dom/htmlscriptelement.rs
@@ -47,16 +47,17 @@ use util::str::{DOMString, HTML_SPACE_CH
 use html5ever::tree_builder::NextParserState;
 use std::cell::{RefCell, Cell};
 use std::mem;
 use std::sync::{Arc, Mutex};
 use string_cache::Atom;
 use url::{Url, UrlParser};
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLScriptElement {
     htmlelement: HTMLElement,
 
     /// https://html.spec.whatwg.org/multipage/#already-started
     already_started: Cell<bool>,
 
     /// https://html.spec.whatwg.org/multipage/#parser-inserted
     parser_inserted: Cell<bool>,
@@ -69,16 +70,17 @@ pub struct HTMLScriptElement {
     /// https://html.spec.whatwg.org/multipage/#ready-to-be-parser-executed
     ///
     /// (currently unused)
     ready_to_be_parser_executed: Cell<bool>,
 
     /// Document of the parser that created this element
     parser_document: JS<Document>,
 
+    #[ignore_heap_size_of = "Defined in rust-encoding"]
     /// https://html.spec.whatwg.org/multipage/#concept-script-encoding
     block_character_encoding: DOMRefCell<EncodingRef>,
 }
 
 impl HTMLScriptElementDerived for EventTarget {
     fn is_htmlscriptelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
@@ -155,16 +157,17 @@ static SCRIPT_JS_MIMES: StaticStringVec 
     "text/javascript1.4",
     "text/javascript1.5",
     "text/jscript",
     "text/livescript",
     "text/x-ecmascript",
     "text/x-javascript",
 ];
 
+#[derive(HeapSizeOf)]
 pub enum ScriptOrigin {
     Internal(String, Url),
     External(Result<(Metadata, Vec<u8>), String>),
 }
 
 /// The context required for asynchronously loading an external script source.
 struct ScriptContext {
     /// The element that initiated the request.
--- a/servo/components/script/dom/htmlselectelement.rs
+++ b/servo/components/script/dom/htmlselectelement.rs
@@ -20,16 +20,17 @@ use dom::validitystate::ValidityState;
 use dom::virtualmethods::VirtualMethods;
 
 use util::str::DOMString;
 use string_cache::Atom;
 
 use std::borrow::ToOwned;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLSelectElement {
     htmlelement: HTMLElement
 }
 
 impl HTMLSelectElementDerived for EventTarget {
     fn is_htmlselectelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmlsourceelement.rs
+++ b/servo/components/script/dom/htmlsourceelement.rs
@@ -8,16 +8,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLSourceElement {
     htmlelement: HTMLElement
 }
 
 impl HTMLSourceElementDerived for EventTarget {
     fn is_htmlsourceelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmlspanelement.rs
+++ b/servo/components/script/dom/htmlspanelement.rs
@@ -8,16 +8,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLSpanElement {
     htmlelement: HTMLElement
 }
 
 impl HTMLSpanElementDerived for EventTarget {
     fn is_htmlspanelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmlstyleelement.rs
+++ b/servo/components/script/dom/htmlstyleelement.rs
@@ -17,16 +17,17 @@ use dom::virtualmethods::VirtualMethods;
 use dom::window::WindowHelpers;
 use layout_interface::{LayoutChan, Msg};
 use util::str::DOMString;
 use style::stylesheets::{Origin, Stylesheet};
 use style::media_queries::parse_media_query_list;
 use cssparser::Parser as CssParser;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLStyleElement {
     htmlelement: HTMLElement,
 }
 
 impl HTMLStyleElementDerived for EventTarget {
     fn is_htmlstyleelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmltablecaptionelement.rs
+++ b/servo/components/script/dom/htmltablecaptionelement.rs
@@ -8,16 +8,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLTableCaptionElement {
     htmlelement: HTMLElement
 }
 
 impl HTMLTableCaptionElementDerived for EventTarget {
     fn is_htmltablecaptionelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmltablecellelement.rs
+++ b/servo/components/script/dom/htmltablecellelement.rs
@@ -31,16 +31,17 @@ pub enum HTMLTableCellElementTypeId {
 impl PartialEq for HTMLTableCellElementTypeId {
     #[inline]
     fn eq(&self, other: &HTMLTableCellElementTypeId) -> bool {
         (*self as u8) == (*other as u8)
     }
 }
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLTableCellElement {
     htmlelement: HTMLElement,
     background_color: Cell<Option<RGBA>>,
     colspan: Cell<Option<u32>>,
     width: Cell<LengthOrPercentageOrAuto>,
 }
 
 impl HTMLTableCellElementDerived for EventTarget {
--- a/servo/components/script/dom/htmltablecolelement.rs
+++ b/servo/components/script/dom/htmltablecolelement.rs
@@ -8,16 +8,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLTableColElement {
     htmlelement: HTMLElement,
 }
 
 impl HTMLTableColElementDerived for EventTarget {
     fn is_htmltablecolelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmltabledatacellelement.rs
+++ b/servo/components/script/dom/htmltabledatacellelement.rs
@@ -9,16 +9,17 @@ use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::element::ElementTypeId;
 use dom::htmlelement::HTMLElementTypeId;
 use dom::htmltablecellelement::{HTMLTableCellElement, HTMLTableCellElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLTableDataCellElement {
     htmltablecellelement: HTMLTableCellElement,
 }
 
 impl HTMLTableDataCellElementDerived for EventTarget {
     fn is_htmltabledatacellelement(&self) -> bool {
         *self.type_id() == EventTargetTypeId::Node(NodeTypeId::Element(
                                                    ElementTypeId::HTMLElement(
--- a/servo/components/script/dom/htmltableelement.rs
+++ b/servo/components/script/dom/htmltableelement.rs
@@ -22,16 +22,17 @@ use dom::virtualmethods::VirtualMethods;
 use util::str::{self, DOMString, LengthOrPercentageOrAuto};
 
 use cssparser::RGBA;
 use string_cache::Atom;
 
 use std::cell::Cell;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLTableElement {
     htmlelement: HTMLElement,
     background_color: Cell<Option<RGBA>>,
     border: Cell<Option<u32>>,
     cellspacing: Cell<Option<u32>>,
     width: Cell<LengthOrPercentageOrAuto>,
 }
 
--- a/servo/components/script/dom/htmltableheadercellelement.rs
+++ b/servo/components/script/dom/htmltableheadercellelement.rs
@@ -9,16 +9,17 @@ use dom::document::Document;
 use dom::element::ElementTypeId;
 use dom::htmlelement::HTMLElementTypeId;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::htmltablecellelement::{HTMLTableCellElement, HTMLTableCellElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLTableHeaderCellElement {
     htmltablecellelement: HTMLTableCellElement,
 }
 
 impl HTMLTableHeaderCellElementDerived for EventTarget {
     fn is_htmltableheadercellelement(&self) -> bool {
         *self.type_id() == EventTargetTypeId::Node(NodeTypeId::Element(
                                                    ElementTypeId::HTMLElement(
--- a/servo/components/script/dom/htmltablerowelement.rs
+++ b/servo/components/script/dom/htmltablerowelement.rs
@@ -13,16 +13,17 @@ use dom::htmlelement::{HTMLElement, HTML
 use dom::node::{Node, NodeTypeId};
 use dom::virtualmethods::VirtualMethods;
 
 use cssparser::RGBA;
 use util::str::{self, DOMString};
 use std::cell::Cell;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLTableRowElement {
     htmlelement: HTMLElement,
     background_color: Cell<Option<RGBA>>,
 }
 
 impl HTMLTableRowElementDerived for EventTarget {
     fn is_htmltablerowelement(&self) -> bool {
         *self.type_id() ==
--- a/servo/components/script/dom/htmltablesectionelement.rs
+++ b/servo/components/script/dom/htmltablesectionelement.rs
@@ -13,16 +13,17 @@ use dom::htmlelement::{HTMLElement, HTML
 use dom::node::{Node, NodeTypeId};
 use dom::virtualmethods::VirtualMethods;
 
 use cssparser::RGBA;
 use util::str::{self, DOMString};
 use std::cell::Cell;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLTableSectionElement {
     htmlelement: HTMLElement,
     background_color: Cell<Option<RGBA>>,
 }
 
 impl HTMLTableSectionElementDerived for EventTarget {
     fn is_htmltablesectionelement(&self) -> bool {
         *self.type_id() ==
--- a/servo/components/script/dom/htmltemplateelement.rs
+++ b/servo/components/script/dom/htmltemplateelement.rs
@@ -8,16 +8,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLTemplateElement {
     htmlelement: HTMLElement,
 }
 
 impl HTMLTemplateElementDerived for EventTarget {
     fn is_htmltemplateelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmltextareaelement.rs
+++ b/servo/components/script/dom/htmltextareaelement.rs
@@ -33,18 +33,20 @@ use msg::constellation_msg::Constellatio
 
 use util::str::DOMString;
 use string_cache::Atom;
 
 use std::borrow::ToOwned;
 use std::cell::Cell;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLTextAreaElement {
     htmlelement: HTMLElement,
+    #[ignore_heap_size_of = "#7193"]
     textinput: DOMRefCell<TextInput<ConstellationChan>>,
     cols: Cell<u32>,
     rows: Cell<u32>,
     // https://html.spec.whatwg.org/multipage/#concept-textarea-dirty
     value_changed: Cell<bool>,
 }
 
 impl HTMLTextAreaElementDerived for EventTarget {
--- a/servo/components/script/dom/htmltimeelement.rs
+++ b/servo/components/script/dom/htmltimeelement.rs
@@ -8,16 +8,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLTimeElement {
     htmlelement: HTMLElement
 }
 
 impl HTMLTimeElementDerived for EventTarget {
     fn is_htmltimeelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmltitleelement.rs
+++ b/servo/components/script/dom/htmltitleelement.rs
@@ -14,16 +14,17 @@ use dom::eventtarget::{EventTarget, Even
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{ChildrenMutation, Node, NodeHelpers, NodeTypeId};
 use dom::text::Text;
 use dom::virtualmethods::VirtualMethods;
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLTitleElement {
     htmlelement: HTMLElement,
 }
 
 impl HTMLTitleElementDerived for EventTarget {
     fn is_htmltitleelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmltrackelement.rs
+++ b/servo/components/script/dom/htmltrackelement.rs
@@ -8,16 +8,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLTrackElement {
     htmlelement: HTMLElement,
 }
 
 impl HTMLTrackElementDerived for EventTarget {
     fn is_htmltrackelement(&self) -> bool {
         *self.type_id() == EventTargetTypeId::Node(
             NodeTypeId::Element(
--- a/servo/components/script/dom/htmlulistelement.rs
+++ b/servo/components/script/dom/htmlulistelement.rs
@@ -8,16 +8,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::element::ElementTypeId;
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLUListElement {
     htmlelement: HTMLElement
 }
 
 impl HTMLUListElementDerived for EventTarget {
     fn is_htmlulistelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmlunknownelement.rs
+++ b/servo/components/script/dom/htmlunknownelement.rs
@@ -8,16 +8,17 @@ use dom::bindings::js::Root;
 use dom::document::Document;
 use dom::element::ElementTypeId;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLUnknownElement {
     htmlelement: HTMLElement
 }
 
 impl HTMLUnknownElementDerived for EventTarget {
     fn is_htmlunknownelement(&self) -> bool {
         *self.type_id() ==
             EventTargetTypeId::Node(
--- a/servo/components/script/dom/htmlvideoelement.rs
+++ b/servo/components/script/dom/htmlvideoelement.rs
@@ -9,16 +9,17 @@ use dom::document::Document;
 use dom::element::ElementTypeId;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::htmlelement::HTMLElementTypeId;
 use dom::htmlmediaelement::{HTMLMediaElement, HTMLMediaElementTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct HTMLVideoElement {
     htmlmediaelement: HTMLMediaElement
 }
 
 impl HTMLVideoElementDerived for EventTarget {
     fn is_htmlvideoelement(&self) -> bool {
         *self.type_id() == EventTargetTypeId::Node(NodeTypeId::Element(
                                                    ElementTypeId::HTMLElement(
--- a/servo/components/script/dom/imagedata.rs
+++ b/servo/components/script/dom/imagedata.rs
@@ -13,16 +13,17 @@ use js::jsapi::{JS_NewUint8ClampedArray,
 use libc::uint8_t;
 use std::vec::Vec;
 use std::slice;
 use std::ptr;
 use std::default::Default;
 
 #[dom_struct]
 #[allow(raw_pointer_derive)]
+#[derive(HeapSizeOf)]
 pub struct ImageData {
     reflector_: Reflector,
     width: u32,
     height: u32,
     data: Heap<*mut JSObject>,
 }
 
 impl ImageData {
--- a/servo/components/script/dom/keyboardevent.rs
+++ b/servo/components/script/dom/keyboardevent.rs
@@ -19,16 +19,17 @@ use msg::constellation_msg::{SHIFT, CONT
 use util::str::DOMString;
 
 use std::borrow::ToOwned;
 use std::cell::{RefCell, Cell};
 
 no_jsmanaged_fields!(Key);
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct KeyboardEvent {
     uievent: UIEvent,
     key: Cell<Option<Key>>,
     key_string: RefCell<DOMString>,
     code: RefCell<DOMString>,
     location: Cell<u32>,
     ctrl: Cell<bool>,
     alt: Cell<bool>,
@@ -741,16 +742,17 @@ fn key_keycode(key: Key) -> u32 {
         Key::Y |
         Key::Z => key as u32 - Key::A as u32 + 'A' as u32,
 
         //ยง B.2.1.8
         _ => 0
     }
 }
 
+#[derive(HeapSizeOf)]
 pub struct KeyEventProperties {
     pub key_string: &'static str,
     pub code: &'static str,
     pub location: u32,
     pub char_code: Option<u32>,
     pub key_code: u32,
 }
 
--- a/servo/components/script/dom/location.rs
+++ b/servo/components/script/dom/location.rs
@@ -11,16 +11,17 @@ use dom::bindings::utils::{Reflector, re
 use dom::urlhelper::UrlHelper;
 use dom::window::Window;
 use dom::window::WindowHelpers;
 
 use util::str::DOMString;
 use url::{Url, UrlParser};
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct Location {
     reflector_: Reflector,
     window: JS<Window>,
 }
 
 impl Location {
     fn new_inherited(window: &Window) -> Location {
         Location {
--- a/servo/components/script/dom/messageevent.rs
+++ b/servo/components/script/dom/messageevent.rs
@@ -17,16 +17,17 @@ use util::str::DOMString;
 
 use js::jsapi::{JSContext, Heap, HandleValue};
 use js::jsval::JSVal;
 
 use std::borrow::ToOwned;
 use std::default::Default;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct MessageEvent {
     event: Event,
     data: Heap<JSVal>,
     origin: DOMString,
     lastEventId: DOMString,
 }
 
 impl MessageEventDerived for Event {
--- a/servo/components/script/dom/mouseevent.rs
+++ b/servo/components/script/dom/mouseevent.rs
@@ -15,16 +15,17 @@ use dom::eventtarget::EventTarget;
 use dom::uievent::UIEvent;
 use dom::window::Window;
 use util::opts;
 use util::str::DOMString;
 use std::cell::Cell;
 use std::default::Default;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct MouseEvent {
     uievent: UIEvent,
     screen_x: Cell<i32>,
     screen_y: Cell<i32>,
     client_x: Cell<i32>,
     client_y: Cell<i32>,
     ctrl_key: Cell<bool>,
     shift_key: Cell<bool>,
--- a/servo/components/script/dom/namednodemap.rs
+++ b/servo/components/script/dom/namednodemap.rs
@@ -11,16 +11,17 @@ use dom::bindings::js::{JS, Root};
 use dom::bindings::utils::{namespace_from_domstring, Reflector, reflect_dom_object};
 use dom::element::{AttributeHandlers, Element, ElementHelpers};
 use dom::window::Window;
 use util::str::DOMString;
 
 use string_cache::Atom;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct NamedNodeMap {
     reflector_: Reflector,
     owner: JS<Element>,
 }
 
 impl NamedNodeMap {
     fn new_inherited(elem: &Element) -> NamedNodeMap {
         NamedNodeMap {
--- a/servo/components/script/dom/navigator.rs
+++ b/servo/components/script/dom/navigator.rs
@@ -7,16 +7,17 @@ use dom::bindings::codegen::Bindings::Na
 use dom::bindings::global::GlobalRef;
 use dom::bindings::js::Root;
 use dom::bindings::utils::{Reflector, reflect_dom_object};
 use dom::navigatorinfo;
 use dom::window::Window;
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct Navigator {
     reflector_: Reflector,
 }
 
 impl Navigator {
     fn new_inherited() -> Navigator {
         Navigator {
             reflector_: Reflector::new()
--- a/servo/components/script/dom/node.rs
+++ b/servo/components/script/dom/node.rs
@@ -198,17 +198,17 @@ impl Drop for Node {
     fn drop(&mut self) {
         self.layout_data.dispose(self);
     }
 }
 
 /// suppress observers flag
 /// https://dom.spec.whatwg.org/#concept-node-insert
 /// https://dom.spec.whatwg.org/#concept-node-remove
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, HeapSizeOf)]
 enum SuppressObserver {
     Suppressed,
     Unsuppressed
 }
 
 /// Layout data that is shared between the script and layout tasks.
 #[derive(HeapSizeOf)]
 pub struct SharedLayoutData {
@@ -1450,17 +1450,17 @@ impl Iterator for TreeIterator {
         }
         debug_assert!(self.depth == 0);
         self.current = None;
         Some(current)
     }
 }
 
 /// Specifies whether children must be recursively cloned or not.
-#[derive(Copy, Clone, PartialEq)]
+#[derive(Copy, Clone, PartialEq, HeapSizeOf)]
 pub enum CloneChildrenFlag {
     CloneChildren,
     DoNotCloneChildren
 }
 
 fn as_uintptr<T>(t: &T) -> uintptr_t { t as *const T as uintptr_t }
 
 impl Node {
@@ -2643,17 +2643,17 @@ impl<'a> DisabledStateHelpers for &'a No
         let elem = ElementCast::to_ref(self).unwrap();
         let has_disabled_attrib = elem.has_attribute(&atom!("disabled"));
         self.set_disabled_state(has_disabled_attrib);
         self.set_enabled_state(!has_disabled_attrib);
     }
 }
 
 /// A summary of the changes that happened to a node.
-#[derive(Copy, Clone, PartialEq)]
+#[derive(Copy, Clone, PartialEq, HeapSizeOf)]
 pub enum NodeDamage {
     /// The node's `style` attribute changed.
     NodeStyleDamaged,
     /// Other parts of a node changed; attributes, text content, etc.
     OtherNodeDamage,
 }
 
 pub enum ChildrenMutation<'a> {
--- a/servo/components/script/dom/nodeiterator.rs
+++ b/servo/components/script/dom/nodeiterator.rs
@@ -14,22 +14,25 @@ use dom::bindings::js::{JS, MutHeap, Roo
 use dom::bindings::utils::{Reflector, reflect_dom_object};
 use dom::document::{Document, DocumentHelpers};
 use dom::node::{Node, NodeHelpers};
 
 use std::cell::Cell;
 use std::rc::Rc;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct NodeIterator {
     reflector_: Reflector,
     root_node: JS<Node>,
+    #[ignore_heap_size_of = "Defined in rust-mozjs"]
     reference_node: MutHeap<JS<Node>>,
     pointer_before_reference_node: Cell<bool>,
     what_to_show: u32,
+    #[ignore_heap_size_of = "Can't measure due to #6870"]
     filter: Filter,
 }
 
 impl NodeIterator {
     fn new_inherited(root_node: &Node,
                      what_to_show: u32,
                      filter: Filter) -> NodeIterator {
         NodeIterator {
--- a/servo/components/script/dom/nodelist.rs
+++ b/servo/components/script/dom/nodelist.rs
@@ -8,25 +8,26 @@ use dom::bindings::codegen::Bindings::No
 use dom::bindings::global::GlobalRef;
 use dom::bindings::js::{JS, MutNullableHeap, Root};
 use dom::bindings::utils::{Reflector, reflect_dom_object};
 use dom::node::{ChildrenMutation, Node, NodeHelpers};
 use dom::window::Window;
 
 use std::cell::Cell;
 
-#[derive(JSTraceable)]
+#[derive(JSTraceable, HeapSizeOf)]
 #[must_root]
 pub enum NodeListType {
     Simple(Vec<JS<Node>>),
     Children(ChildrenList),
 }
 
 // https://dom.spec.whatwg.org/#interface-nodelist
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct NodeList {
     reflector_: Reflector,
     list_type: NodeListType,
 }
 
 impl NodeList {
     fn new_inherited(list_type: NodeListType) -> NodeList {
         NodeList {
@@ -88,20 +89,21 @@ impl<'a> NodeListHelpers<'a> for &'a Nod
         if let NodeListType::Children(ref list) = self.list_type {
             list
         } else {
             panic!("called as_children_list() on a simple node list")
         }
     }
 }
 
-#[derive(JSTraceable)]
+#[derive(JSTraceable, HeapSizeOf)]
 #[must_root]
 pub struct ChildrenList {
     node: JS<Node>,
+    #[ignore_heap_size_of = "Defined in rust-mozjs"]
     last_visited: MutNullableHeap<JS<Node>>,
     last_index: Cell<u32>,
 }
 
 impl ChildrenList {
     fn new(node: &Node) -> ChildrenList {
         let last_visited = node.GetFirstChild();
         ChildrenList {
--- a/servo/components/script/dom/performance.rs
+++ b/servo/components/script/dom/performance.rs
@@ -10,16 +10,17 @@ use dom::bindings::num::Finite;
 use dom::bindings::utils::{Reflector, reflect_dom_object};
 use dom::performancetiming::{PerformanceTiming, PerformanceTimingHelpers};
 use dom::window::Window;
 use time;
 
 pub type DOMHighResTimeStamp = Finite<f64>;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct Performance {
     reflector_: Reflector,
     timing: JS<PerformanceTiming>,
 }
 
 impl Performance {
     fn new_inherited(window: &Window,
                      navigation_start: u64,
--- a/servo/components/script/dom/performancetiming.rs
+++ b/servo/components/script/dom/performancetiming.rs
@@ -5,16 +5,17 @@
 use dom::bindings::codegen::Bindings::PerformanceTimingBinding;
 use dom::bindings::codegen::Bindings::PerformanceTimingBinding::PerformanceTimingMethods;
 use dom::bindings::global::GlobalRef;
 use dom::bindings::js::Root;
 use dom::bindings::utils::{Reflector, reflect_dom_object};
 use dom::window::Window;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct PerformanceTiming {
     reflector_: Reflector,
     navigationStart: u64,
     navigationStartPrecise: f64,
 }
 
 impl PerformanceTiming {
     fn new_inherited(navStart: u64, navStartPrecise: f64)
--- a/servo/components/script/dom/processinginstruction.rs
+++ b/servo/components/script/dom/processinginstruction.rs
@@ -9,16 +9,17 @@ use dom::bindings::js::Root;
 use dom::characterdata::{CharacterData, CharacterDataTypeId};
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::node::{Node, NodeTypeId};
 use util::str::DOMString;
 
 /// An HTML processing instruction node.
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct ProcessingInstruction {
     characterdata: CharacterData,
     target: DOMString,
 }
 
 impl ProcessingInstructionDerived for EventTarget {
     fn is_processinginstruction(&self) -> bool {
         *self.type_id() ==
--- a/servo/components/script/dom/progressevent.rs
+++ b/servo/components/script/dom/progressevent.rs
@@ -9,16 +9,17 @@ use dom::bindings::codegen::InheritTypes
 use dom::bindings::error::Fallible;
 use dom::bindings::global::GlobalRef;
 use dom::bindings::js::Root;
 use dom::bindings::utils::reflect_dom_object;
 use dom::event::{Event, EventTypeId, EventBubbles, EventCancelable};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct ProgressEvent {
     event: Event,
     length_computable: bool,
     loaded: u64,
     total: u64
 }
 
 impl ProgressEventDerived for Event {
--- a/servo/components/script/dom/range.rs
+++ b/servo/components/script/dom/range.rs
@@ -21,16 +21,17 @@ use dom::document::{Document, DocumentHe
 use dom::documentfragment::DocumentFragment;
 use dom::node::{Node, NodeHelpers, NodeTypeId};
 
 use std::cell::RefCell;
 use std::cmp::{Ord, Ordering, PartialEq, PartialOrd};
 use std::rc::Rc;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct Range {
     reflector_: Reflector,
     inner: Rc<RefCell<RangeInner>>,
 }
 
 impl Range {
     fn new_inherited(start_container: &Node, start_offset: u32,
                      end_container: &Node, end_offset: u32) -> Range {
@@ -677,16 +678,17 @@ impl<'a> RangeMethods for &'a Range {
 
         Ok(())
     }
 }
 
 #[derive(JSTraceable)]
 #[must_root]
 #[privatize]
+#[derive(HeapSizeOf)]
 pub struct RangeInner {
     start: BoundaryPoint,
     end: BoundaryPoint,
 }
 
 impl RangeInner {
     fn new(start: BoundaryPoint, end: BoundaryPoint) -> RangeInner {
         RangeInner { start: start, end: end }
@@ -811,16 +813,17 @@ impl RangeInner {
         // Step 6.
         Ok(Ordering::Equal)
     }
 }
 
 #[derive(JSTraceable)]
 #[must_root]
 #[privatize]
+#[derive(HeapSizeOf)]
 pub struct BoundaryPoint {
     node: JS<Node>,
     offset: u32,
 }
 
 impl BoundaryPoint {
     fn new(node: &Node, offset: u32) -> BoundaryPoint {
         debug_assert!(!node.is_doctype());
--- a/servo/components/script/dom/screen.rs
+++ b/servo/components/script/dom/screen.rs
@@ -5,16 +5,17 @@
 use dom::bindings::codegen::Bindings::ScreenBinding;
 use dom::bindings::codegen::Bindings::ScreenBinding::ScreenMethods;
 use dom::bindings::global::GlobalRef;
 use dom::bindings::js::Root;
 use dom::bindings::utils::{Reflector, reflect_dom_object};
 use dom::window::Window;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct Screen {
     reflector_: Reflector,
 }
 
 impl Screen {
     fn new_inherited() -> Screen {
         Screen {
             reflector_: Reflector::new(),
--- a/servo/components/script/dom/servohtmlparser.rs
+++ b/servo/components/script/dom/servohtmlparser.rs
@@ -31,17 +31,17 @@ use url::Url;
 use js::jsapi::JSTracer;
 use html5ever::tokenizer;
 use html5ever::tree_builder;
 use html5ever::tree_builder::{TreeBuilder, TreeBuilderOpts};
 use hyper::header::ContentType;
 use hyper::mime::{Mime, TopLevel, SubLevel};
 
 #[must_root]
-#[derive(JSTraceable)]
+#[derive(JSTraceable, HeapSizeOf)]
 pub struct Sink {
     pub base_url: Option<Url>,
     pub document: JS<Document>,
 }
 
 /// FragmentContext is used only to pass this group of related values
 /// into functions.
 #[derive(Copy, Clone)]
@@ -152,18 +152,20 @@ impl AsyncResponseListener for ParserCon
         parser.r().parse_sync();
     }
 }
 
 impl PreInvoke for ParserContext {
 }
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct ServoHTMLParser {
     reflector_: Reflector,
+    #[ignore_heap_size_of = "Defined in html5ever"]
     tokenizer: DOMRefCell<Tokenizer>,
     /// Input chunks received but not yet passed to the parser.
     pending_input: DOMRefCell<Vec<String>>,
     /// The document associated with this parser.
     document: JS<Document>,
     /// True if this parser should avoid passing any further data to the tokenizer.
     suspended: Cell<bool>,
     /// Whether to expect any further input from the associated network request.
--- a/servo/components/script/dom/storage.rs
+++ b/servo/components/script/dom/storage.rs
@@ -19,16 +19,17 @@ use page::IterablePage;
 use net_traits::storage_task::{StorageTask, StorageTaskMsg, StorageType};
 use std::borrow::ToOwned;
 use std::sync::mpsc::channel;
 use url::Url;
 
 use script_task::{ScriptTask, ScriptMsg, MainThreadRunnable};
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct Storage {
     reflector_: Reflector,
     global: GlobalField,
     storage_type: StorageType
 }
 
 impl Storage {
     fn new_inherited(global: &GlobalRef, storage_type: StorageType) -> Storage {
--- a/servo/components/script/dom/storageevent.rs
+++ b/servo/components/script/dom/storageevent.rs
@@ -12,16 +12,17 @@ use dom::bindings::error::Fallible;
 use dom::bindings::global::GlobalRef;
 use dom::bindings::js::{JS, MutNullableHeap, Root, RootedReference};
 use dom::bindings::utils::{reflect_dom_object};
 use dom::event::{Event, EventTypeId, EventBubbles, EventCancelable};
 use dom::storage::Storage;
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct StorageEvent {
     event: Event,
     key: DOMRefCell<Option<DOMString>>,
     oldValue: DOMRefCell<Option<DOMString>>,
     newValue: DOMRefCell<Option<DOMString>>,
     url: DOMRefCell<DOMString>,
     storageArea: MutNullableHeap<JS<Storage>>
 }
--- a/servo/components/script/dom/testbinding.rs
+++ b/servo/components/script/dom/testbinding.rs
@@ -25,16 +25,17 @@ use util::str::DOMString;
 use js::jsapi::{JSContext, JSObject, HandleValue};
 use js::jsval::{JSVal, NullValue};
 
 use std::borrow::ToOwned;
 use std::ptr;
 use std::rc::Rc;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct TestBinding {
     reflector_: Reflector,
     global: GlobalField,
 }
 
 impl<'a> TestBindingMethods for &'a TestBinding {
     fn BooleanAttribute(self) -> bool { false }
     fn SetBooleanAttribute(self, _: bool) {}
--- a/servo/components/script/dom/testbindingproxy.rs
+++ b/servo/components/script/dom/testbindingproxy.rs
@@ -5,16 +5,17 @@
 // check-tidy: no specs after this line
 
 use dom::bindings::codegen::Bindings::TestBindingProxyBinding::TestBindingProxyMethods;
 use dom::bindings::utils::Reflector;
 use util::str::DOMString;
 
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct TestBindingProxy {
     reflector_: Reflector
 }
 
 impl<'a> TestBindingProxyMethods for &'a TestBindingProxy {
 
     fn GetNamedItem(self, _: DOMString) -> DOMString {"".to_owned()}
     fn SetNamedItem(self, _: DOMString, _: DOMString) -> () {}
--- a/servo/components/script/dom/text.rs
+++ b/servo/components/script/dom/text.rs
@@ -16,16 +16,17 @@ use dom::bindings::js::Root;
 use dom::characterdata::{CharacterData, CharacterDataHelpers, CharacterDataTypeId};
 use dom::document::Document;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::node::{Node, NodeHelpers, NodeTypeId};
 use util::str::DOMString;
 
 /// An HTML text node.
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct Text {
     characterdata: CharacterData,
 }
 
 impl TextDerived for EventTarget {
     fn is_text(&self) -> bool {
         *self.type_id() == EventTargetTypeId::Node(NodeTypeId::CharacterData(CharacterDataTypeId::Text))
     }
--- a/servo/components/script/dom/textdecoder.rs
+++ b/servo/components/script/dom/textdecoder.rs
@@ -19,18 +19,20 @@ use encoding::label::encoding_from_whatw
 use js::jsapi::{JSContext, JSObject};
 use js::jsapi::JS_GetObjectAsArrayBufferView;
 
 use std::borrow::ToOwned;
 use std::ptr;
 use std::slice;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct TextDecoder {
     reflector_: Reflector,
+    #[ignore_heap_size_of = "Defined in rust-encoding"]
     encoding: EncodingRef,
     fatal: bool,
 }
 
 impl TextDecoder {
     fn new_inherited(encoding: EncodingRef, fatal: bool) -> TextDecoder {
         TextDecoder {
             reflector_: Reflector::new(),
--- a/servo/components/script/dom/textencoder.rs
+++ b/servo/components/script/dom/textencoder.rs
@@ -20,19 +20,21 @@ use encoding::types::EncodingRef;
 use encoding::{Encoding, EncoderTrap};
 use encoding::label::encoding_from_whatwg_label;
 
 use libc::uint8_t;
 use js::jsapi::{JSContext, JSObject};
 use js::jsapi::{JS_NewUint8Array, JS_GetUint8ArrayData};
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct TextEncoder {
     reflector_: Reflector,
     encoding: DOMString,
+    #[ignore_heap_size_of = "Defined in rust-encoding"]
     encoder: EncodingRef,
 }
 
 impl TextEncoder {
     fn new_inherited(encoding: DOMString, encoder: EncodingRef) -> TextEncoder {
         TextEncoder {
             reflector_: Reflector::new(),
             encoding: encoding,
--- a/servo/components/script/dom/uievent.rs
+++ b/servo/components/script/dom/uievent.rs
@@ -16,16 +16,17 @@ use dom::event::{Event, EventTypeId, Eve
 use dom::window::Window;
 use util::str::DOMString;
 
 use std::cell::Cell;
 use std::default::Default;
 
 // https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#interface-UIEvent
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct UIEvent {
     event: Event,
     view: MutNullableHeap<JS<Window>>,
     detail: Cell<i32>
 }
 
 impl UIEventDerived for Event {
     fn is_uievent(&self) -> bool {
--- a/servo/components/script/dom/url.rs
+++ b/servo/components/script/dom/url.rs
@@ -12,16 +12,17 @@ use dom::urlhelper::UrlHelper;
 
 use url::{Host, Url, UrlParser};
 use util::str::DOMString;
 
 use std::borrow::ToOwned;
 
 // https://url.spec.whatwg.org/#url
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct URL {
     reflector_: Reflector,
 
     // https://url.spec.whatwg.org/#concept-urlutils-url
     url: Url,
 }
 
 impl URL {
--- a/servo/components/script/dom/urlhelper.rs
+++ b/servo/components/script/dom/urlhelper.rs
@@ -4,16 +4,17 @@
 
 use dom::bindings::str::USVString;
 
 use url::{Url, SchemeData};
 
 use std::borrow::ToOwned;
 use std::fmt::Write;
 
+#[derive(HeapSizeOf)]
 pub struct UrlHelper;
 
 impl UrlHelper {
     // https://url.spec.whatwg.org/#dom-urlutils-hash
     pub fn Hash(url: &Url) -> USVString {
         USVString(match url.fragment {
             None => "".to_owned(),
             Some(ref hash) if hash.is_empty() => "".to_owned(),
--- a/servo/components/script/dom/urlsearchparams.rs
+++ b/servo/components/script/dom/urlsearchparams.rs
@@ -13,16 +13,17 @@ use dom::bindings::js::Root;
 use dom::bindings::utils::{Reflector, reflect_dom_object};
 
 use encoding::types::EncodingRef;
 use url::form_urlencoded::{parse, serialize_with_encoding};
 use util::str::DOMString;
 
 // https://url.spec.whatwg.org/#interface-urlsearchparams
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct URLSearchParams {
     reflector_: Reflector,
     // https://url.spec.whatwg.org/#concept-urlsearchparams-list
     list: DOMRefCell<Vec<(DOMString, DOMString)>>,
 }
 
 impl URLSearchParams {
     fn new_inherited() -> URLSearchParams {
--- a/servo/components/script/dom/validitystate.rs
+++ b/servo/components/script/dom/validitystate.rs
@@ -5,16 +5,17 @@
 use dom::bindings::codegen::Bindings::ValidityStateBinding;
 use dom::bindings::global::GlobalRef;
 use dom::bindings::js::Root;
 use dom::bindings::utils::{Reflector, reflect_dom_object};
 use dom::window::Window;
 
 // https://html.spec.whatwg.org/#validitystate
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct ValidityState {
     reflector_: Reflector,
     state: u8,
 }
 
 impl ValidityState {
     fn new_inherited() -> ValidityState {
         ValidityState {
--- a/servo/components/script/dom/webglactiveinfo.rs
+++ b/servo/components/script/dom/webglactiveinfo.rs
@@ -6,16 +6,17 @@
 use dom::bindings::codegen::Bindings::WebGLActiveInfoBinding;
 use dom::bindings::codegen::Bindings::WebGLActiveInfoBinding::WebGLActiveInfoMethods;
 use dom::bindings::global::GlobalRef;
 use dom::bindings::js::Root;
 use dom::bindings::utils::{Reflector,reflect_dom_object};
 use util::str::DOMString;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct WebGLActiveInfo {
     reflector_: Reflector,
     size: i32,
     // NOTE: `ty` stands for `type`, which is a reserved keyword
     ty: u32,
     name: String,
 }
 
--- a/servo/components/script/dom/webglbuffer.rs
+++ b/servo/components/script/dom/webglbuffer.rs
@@ -9,20 +9,22 @@ use dom::bindings::js::Root;
 use dom::bindings::utils::reflect_dom_object;
 use dom::webglobject::WebGLObject;
 
 use canvas_traits::{CanvasMsg, CanvasWebGLMsg};
 use ipc_channel::ipc::{self, IpcSender};
 use std::cell::Cell;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct WebGLBuffer {
     webgl_object: WebGLObject,
     id: u32,
     is_deleted: Cell<bool>,
+    #[ignore_heap_size_of = "Defined in ipc-channel"]
     renderer: IpcSender<CanvasMsg>,
 }
 
 impl WebGLBuffer {
     fn new_inherited(renderer: IpcSender<CanvasMsg>, id: u32) -> WebGLBuffer {
         WebGLBuffer {
             webgl_object: WebGLObject::new_inherited(),
             id: id,
--- a/servo/components/script/dom/webglframebuffer.rs
+++ b/servo/components/script/dom/webglframebuffer.rs
@@ -9,20 +9,22 @@ use dom::bindings::js::Root;
 use dom::bindings::utils::reflect_dom_object;
 use dom::webglobject::WebGLObject;
 
 use canvas_traits::{CanvasMsg, CanvasWebGLMsg, WebGLFramebufferBindingRequest};
 use ipc_channel::ipc::{self, IpcSender};
 use std::cell::Cell;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct WebGLFramebuffer {
     webgl_object: WebGLObject,
     id: u32,
     is_deleted: Cell<bool>,
+    #[ignore_heap_size_of = "Defined in ipc-channel"]
     renderer: IpcSender<CanvasMsg>,
 }
 
 impl WebGLFramebuffer {
     fn new_inherited(renderer: IpcSender<CanvasMsg>, id: u32) -> WebGLFramebuffer {
         WebGLFramebuffer {
             webgl_object: WebGLObject::new_inherited(),
             id: id,
--- a/servo/components/script/dom/webglobject.rs
+++ b/servo/components/script/dom/webglobject.rs
@@ -4,16 +4,17 @@
 
 // https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl
 use dom::bindings::codegen::Bindings::WebGLObjectBinding;
 use dom::bindings::global::GlobalRef;
 use dom::bindings::utils::{Reflector, reflect_dom_object};
 use dom::bindings::js::Root;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct WebGLObject {
     reflector_: Reflector,
 }
 
 impl WebGLObject {
     pub fn new_inherited() -> WebGLObject {
         WebGLObject {
             reflector_: Reflector::new(),
--- a/servo/components/script/dom/webglprogram.rs
+++ b/servo/components/script/dom/webglprogram.rs
@@ -13,22 +13,24 @@ use dom::webglrenderingcontext::MAX_UNIF
 
 use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
 
 use canvas_traits::{CanvasMsg, CanvasWebGLMsg, WebGLResult, WebGLError};
 use ipc_channel::ipc::{self, IpcSender};
 use std::cell::Cell;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct WebGLProgram {
     webgl_object: WebGLObject,
     id: u32,
     is_deleted: Cell<bool>,
     fragment_shader: MutNullableHeap<JS<WebGLShader>>,
     vertex_shader: MutNullableHeap<JS<WebGLShader>>,
+    #[ignore_heap_size_of = "Defined in ipc-channel"]
     renderer: IpcSender<CanvasMsg>,
 }
 
 impl WebGLProgram {
     fn new_inherited(renderer: IpcSender<CanvasMsg>, id: u32) -> WebGLProgram {
         WebGLProgram {
             webgl_object: WebGLObject::new_inherited(),
             id: id,
--- a/servo/components/script/dom/webglrenderbuffer.rs
+++ b/servo/components/script/dom/webglrenderbuffer.rs
@@ -9,20 +9,22 @@ use dom::bindings::js::Root;
 use dom::bindings::utils::reflect_dom_object;
 use dom::webglobject::WebGLObject;
 
 use canvas_traits::{CanvasMsg, CanvasWebGLMsg};
 use ipc_channel::ipc::{self, IpcSender};
 use std::cell::Cell;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct WebGLRenderbuffer {
     webgl_object: WebGLObject,
     id: u32,
     is_deleted: Cell<bool>,
+    #[ignore_heap_size_of = "Defined in ipc-channel"]
     renderer: IpcSender<CanvasMsg>,
 }
 
 impl WebGLRenderbuffer {
     fn new_inherited(renderer: IpcSender<CanvasMsg>, id: u32) -> WebGLRenderbuffer {
         WebGLRenderbuffer {
             webgl_object: WebGLObject::new_inherited(),
             id: id,
--- a/servo/components/script/dom/webglrenderingcontext.rs
+++ b/servo/components/script/dom/webglrenderingcontext.rs
@@ -45,20 +45,22 @@ macro_rules! handle_potential_webgl_erro
                 $context.handle_webgl_error(error);
                 $return_on_error
             }
         }
     }
 }
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct WebGLRenderingContext {
     reflector_: Reflector,
     global: GlobalField,
     renderer_id: usize,
+    #[ignore_heap_size_of = "Defined in ipc-channel"]
     ipc_renderer: IpcSender<CanvasMsg>,
     canvas: JS<HTMLCanvasElement>,
     last_error: Cell<Option<WebGLError>>,
 }
 
 impl WebGLRenderingContext {
     fn new_inherited(global: GlobalRef,
                      canvas: &HTMLCanvasElement,
--- a/servo/components/script/dom/webglshader.rs
+++ b/servo/components/script/dom/webglshader.rs
@@ -12,23 +12,25 @@ use dom::webglobject::WebGLObject;
 use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
 
 use canvas_traits::{CanvasMsg, CanvasWebGLMsg, WebGLResult, WebGLError, WebGLShaderParameter};
 use ipc_channel::ipc::{self, IpcSender};
 use std::cell::Cell;
 use std::cell::RefCell;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct WebGLShader {
     webgl_object: WebGLObject,
     id: u32,
     gl_type: u32,
     source: RefCell<Option<String>>,
     is_deleted: Cell<bool>,
     // TODO(ecoal95): Evaluate moving this to `WebGLObject`
+    #[ignore_heap_size_of = "Defined in ipc-channel"]
     renderer: IpcSender<CanvasMsg>,
 }
 
 impl WebGLShader {
     fn new_inherited(renderer: IpcSender<CanvasMsg>, id: u32, shader_type: u32) -> WebGLShader {
         WebGLShader {
             webgl_object: WebGLObject::new_inherited(),
             id: id,
--- a/servo/components/script/dom/webglshaderprecisionformat.rs
+++ b/servo/components/script/dom/webglshaderprecisionformat.rs
@@ -5,16 +5,17 @@
 // https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl
 use dom::bindings::codegen::Bindings::WebGLShaderPrecisionFormatBinding;
 use dom::bindings::codegen::Bindings::WebGLShaderPrecisionFormatBinding::WebGLShaderPrecisionFormatMethods;
 use dom::bindings::global::GlobalRef;
 use dom::bindings::js::Root;
 use dom::bindings::utils::{Reflector,reflect_dom_object};
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct WebGLShaderPrecisionFormat {
     reflector_: Reflector,
     range_min: i32,
     range_max: i32,
     precision: i32,
 }
 
 impl WebGLShaderPrecisionFormat {
--- a/servo/components/script/dom/webgltexture.rs
+++ b/servo/components/script/dom/webgltexture.rs
@@ -9,20 +9,22 @@ use dom::bindings::js::Root;
 use dom::bindings::utils::reflect_dom_object;
 use dom::webglobject::WebGLObject;
 
 use canvas_traits::{CanvasMsg, CanvasWebGLMsg};
 use ipc_channel::ipc::{self, IpcSender};
 use std::cell::Cell;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct WebGLTexture {
     webgl_object: WebGLObject,
     id: u32,
     is_deleted: Cell<bool>,
+    #[ignore_heap_size_of = "Defined in ipc-channel"]
     renderer: IpcSender<CanvasMsg>,
 }
 
 impl WebGLTexture {
     fn new_inherited(renderer: IpcSender<CanvasMsg>, id: u32) -> WebGLTexture {
         WebGLTexture {
             webgl_object: WebGLObject::new_inherited(),
             id: id,
--- a/servo/components/script/dom/webgluniformlocation.rs
+++ b/servo/components/script/dom/webgluniformlocation.rs
@@ -4,16 +4,17 @@
 
 // https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl
 use dom::bindings::codegen::Bindings::WebGLUniformLocationBinding;
 use dom::bindings::global::GlobalRef;
 use dom::bindings::js::Root;
 use dom::bindings::utils::{Reflector,reflect_dom_object};
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct WebGLUniformLocation {
     reflector_: Reflector,
     id: i32,
 }
 
 impl WebGLUniformLocation {
     fn new_inherited(id: i32) -> WebGLUniformLocation {
         WebGLUniformLocation {
--- a/servo/components/script/dom/websocket.rs
+++ b/servo/components/script/dom/websocket.rs
@@ -43,37 +43,40 @@ use websocket::header::Origin;
 use websocket::result::WebSocketResult;
 use websocket::ws::receiver::Receiver as WSReceiver;
 use websocket::ws::util::url::parse_url;
 
 use std::borrow::ToOwned;
 use std::cell::{Cell, RefCell};
 use std::sync::{Arc, Mutex};
 
-#[derive(JSTraceable, PartialEq, Copy, Clone, Debug)]
+#[derive(JSTraceable, PartialEq, Copy, Clone, Debug, HeapSizeOf)]
 enum WebSocketRequestState {
     Connecting = 0,
     Open = 1,
     Closing = 2,
     Closed = 3,
 }
 
 no_jsmanaged_fields!(Sender<WebSocketStream>);
 
+#[derive(HeapSizeOf)]
 enum MessageData {
     Text(String),
     Binary(Vec<u8>),
 }
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct WebSocket {
     eventtarget: EventTarget,
     url: Url,
     global: GlobalField,
     ready_state: Cell<WebSocketRequestState>,
+    #[ignore_heap_size_of = "Defined in std"]
     sender: RefCell<Option<Arc<Mutex<Sender<WebSocketStream>>>>>,
     failed: Cell<bool>, //Flag to tell if websocket was closed due to failure
     full: Cell<bool>, //Flag to tell if websocket queue is full
     clean_close: Cell<bool>, //Flag to tell if the websocket closed cleanly (not due to full or fail)
     code: Cell<u16>, //Closing code
     reason: DOMRefCell<DOMString>, //Closing reason
     data: DOMRefCell<DOMString>, //Data from send - TODO: Remove after buffer is added.
 }
--- a/servo/components/script/dom/window.rs
+++ b/servo/components/script/dom/window.rs
@@ -83,17 +83,17 @@ use time;
 /// Current state of the window object
 #[derive(JSTraceable, Copy, Clone, Debug, PartialEq, HeapSizeOf)]
 enum WindowState {
     Alive,
     Zombie,     // Pipeline is closed, but the window hasn't been GCed yet.
 }
 
 /// Extra information concerning the reason for reflowing.
-#[derive(Debug)]
+#[derive(Debug, HeapSizeOf)]
 pub enum ReflowReason {
     CachedPageNeededReflow,
     RefreshTick,
     FirstLoad,
     KeyEvent,
     MouseEvent,
     Query,
     Timer,
--- a/servo/components/script/dom/worker.rs
+++ b/servo/components/script/dom/worker.rs
@@ -35,19 +35,21 @@ use url::UrlParser;
 
 use std::borrow::ToOwned;
 use std::sync::mpsc::{channel, Sender};
 
 pub type TrustedWorkerAddress = Trusted<Worker>;
 
 // https://html.spec.whatwg.org/multipage/#worker
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct Worker {
     eventtarget: EventTarget,
     global: GlobalField,
+    #[ignore_heap_size_of = "Defined in std"]
     /// Sender to the Receiver associated with the DedicatedWorkerGlobalScope
     /// this Worker created.
     sender: Sender<(TrustedWorkerAddress, ScriptMsg)>,
 }
 
 impl Worker {
     fn new_inherited(global: GlobalRef, sender: Sender<(TrustedWorkerAddress, ScriptMsg)>) -> Worker {
         Worker {
--- a/servo/components/script/dom/workerglobalscope.rs
+++ b/servo/components/script/dom/workerglobalscope.rs
@@ -48,43 +48,51 @@ pub struct WorkerGlobalScopeInit {
     pub devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
     pub devtools_sender: Option<IpcSender<DevtoolScriptControlMsg>>,
     pub constellation_chan: ConstellationChan,
     pub worker_id: WorkerId,
 }
 
 // https://html.spec.whatwg.org/multipage/#the-workerglobalscope-common-interface
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct WorkerGlobalScope {
     eventtarget: EventTarget,
     worker_id: WorkerId,
     worker_url: Url,
+    #[ignore_heap_size_of = "Defined in std"]
     runtime: Rc<Runtime>,
     next_worker_id: Cell<WorkerId>,
+    #[ignore_heap_size_of = "Defined in std"]
     resource_task: ResourceTask,
     location: MutNullableHeap<JS<WorkerLocation>>,
     navigator: MutNullableHeap<JS<WorkerNavigator>>,
     console: MutNullableHeap<JS<Console>>,
     crypto: MutNullableHeap<JS<Crypto>>,
     timers: TimerManager,
+    #[ignore_heap_size_of = "Defined in std"]
     mem_profiler_chan: mem::ProfilerChan,
+    #[ignore_heap_size_of = "Defined in ipc-channel"]
     devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
 
+    #[ignore_heap_size_of = "Defined in ipc-channel"]
     /// Optional `IpcSender` for sending the `DevtoolScriptControlMsg`
     /// to the server from within the worker
     devtools_sender: Option<IpcSender<DevtoolScriptControlMsg>>,
 
+    #[ignore_heap_size_of = "Defined in std"]
     /// This `Receiver` will be ignored later if the corresponding
     /// `IpcSender` doesn't exist
     devtools_receiver: Receiver<DevtoolScriptControlMsg>,
 
     /// A flag to indicate whether the developer tools has requested live updates
     /// from the worker
     devtools_wants_updates: Cell<bool>,
 
+    #[ignore_heap_size_of = "Defined in std"]
     constellation_chan: ConstellationChan,
 }
 
 impl WorkerGlobalScope {
     pub fn new_inherited(type_id: WorkerGlobalScopeTypeId,
                          init: WorkerGlobalScopeInit,
                          worker_url: Url,
                          runtime: Rc<Runtime>,
--- a/servo/components/script/dom/workerlocation.rs
+++ b/servo/components/script/dom/workerlocation.rs
@@ -11,16 +11,17 @@ use dom::bindings::utils::{Reflector, re
 use dom::urlhelper::UrlHelper;
 use dom::workerglobalscope::WorkerGlobalScope;
 
 use url::Url;
 use util::str::DOMString;
 
 // https://html.spec.whatwg.org/multipage/#worker-locations
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct WorkerLocation {
     reflector_: Reflector,
     url: Url,
 }
 
 impl WorkerLocation {
     fn new_inherited(url: Url) -> WorkerLocation {
         WorkerLocation {
--- a/servo/components/script/dom/workernavigator.rs
+++ b/servo/components/script/dom/workernavigator.rs
@@ -8,16 +8,17 @@ use dom::bindings::global::GlobalRef;
 use dom::bindings::js::Root;
 use dom::bindings::utils::{Reflector, reflect_dom_object};
 use dom::navigatorinfo;
 use dom::workerglobalscope::WorkerGlobalScope;
 use util::str::DOMString;
 
 // https://html.spec.whatwg.org/multipage/#workernavigator
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct WorkerNavigator {
     reflector_: Reflector,
 }
 
 impl WorkerNavigator {
     fn new_inherited() -> WorkerNavigator {
         WorkerNavigator {
             reflector_: Reflector::new(),
--- a/servo/components/script/dom/xmlhttprequest.rs
+++ b/servo/components/script/dom/xmlhttprequest.rs
@@ -44,16 +44,17 @@ use js::jsapi::{JS_ParseJSON, JSContext,
 use js::jsapi::JS_ClearPendingException;
 use js::jsval::{JSVal, NullValue, UndefinedValue};
 
 use net_traits::ControlMsg::Load;
 use net_traits::{ResourceTask, ResourceCORSData, LoadData, LoadConsumer};
 use net_traits::{AsyncResponseListener, AsyncResponseTarget, Metadata};
 use cors::{allow_cross_origin_request, CORSRequest, RequestMode, AsyncCORSResponseListener};
 use cors::CORSResponse;
+use util::mem::HeapSizeOf;
 use util::str::DOMString;
 use util::task::spawn_named;
 
 use ipc_channel::ipc;
 use ipc_channel::router::ROUTER;
 use std::ascii::AsciiExt;
 use std::borrow::ToOwned;
 use std::cell::{RefCell, Cell};
@@ -64,26 +65,26 @@ use std::thread::sleep_ms;
 use time;
 use url::{Url, UrlParser};
 
 use dom::bindings::codegen::UnionTypes::StringOrURLSearchParams;
 use dom::bindings::codegen::UnionTypes::StringOrURLSearchParams::{eString, eURLSearchParams};
 
 pub type SendParam = StringOrURLSearchParams;
 
-#[derive(JSTraceable, PartialEq, Copy, Clone)]
+#[derive(JSTraceable, PartialEq, Copy, Clone, HeapSizeOf)]
 enum XMLHttpRequestState {
     Unsent = 0,
     Opened = 1,
     HeadersReceived = 2,
     Loading = 3,
     Done = 4,
 }
 
-#[derive(JSTraceable, PartialEq, Clone, Copy)]
+#[derive(JSTraceable, PartialEq, Clone, Copy, HeapSizeOf)]
 pub struct GenerationId(u32);
 
 /// Closure of required data for each async network event that comprises the
 /// XHR's response.
 struct XHRContext {
     xhr: TrustedXHRAddress,
     gen_id: GenerationId,
     cors_request: Option<CORSRequest>,
@@ -110,43 +111,48 @@ impl XHRProgress {
             XHRProgress::Loading(id, _) |
             XHRProgress::Done(id) |
             XHRProgress::Errored(id, _) => id
         }
     }
 }
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct XMLHttpRequest {
     eventtarget: XMLHttpRequestEventTarget,
     ready_state: Cell<XMLHttpRequestState>,
     timeout: Cell<u32>,
     with_credentials: Cell<bool>,
     upload: JS<XMLHttpRequestUpload>,
     response_url: DOMString,
     status: Cell<u16>,
     status_text: DOMRefCell<ByteString>,
     response: DOMRefCell<ByteString>,
     response_type: Cell<XMLHttpRequestResponseType>,
     response_xml: MutNullableHeap<JS<Document>>,
+    #[ignore_heap_size_of = "Defined in hyper"]
     response_headers: DOMRefCell<Headers>,
 
     // Associated concepts
     request_method: DOMRefCell<Method>,
     request_url: DOMRefCell<Option<Url>>,
+    #[ignore_heap_size_of = "Defined in hyper"]
     request_headers: DOMRefCell<Headers>,
     request_body_len: Cell<usize>,
     sync: Cell<bool>,
     upload_complete: Cell<bool>,
     upload_events: Cell<bool>,
     send_flag: Cell<bool>,
 
     global: GlobalField,
+    #[ignore_heap_size_of = "Defined in std"]
     timeout_cancel: DOMRefCell<Option<Sender<()>>>,
     fetch_time: Cell<i64>,
+    #[ignore_heap_size_of = "Cannot calculate Heap size"]
     timeout_target: DOMRefCell<Option<Box<ScriptChan+Send>>>,
     generation_id: Cell<GenerationId>,
     response_status: Cell<Result<(), ()>>,
 }
 
 impl XMLHttpRequest {
     fn new_inherited(global: GlobalRef) -> XMLHttpRequest {
         XMLHttpRequest {
@@ -1049,17 +1055,17 @@ impl<'a> PrivateXMLHttpRequestHelpers fo
     fn filter_response_headers(self) -> Headers {
         // https://fetch.spec.whatwg.org/#concept-response-header-list
         use std::fmt;
         use hyper::header::{Header, HeaderFormat};
         use hyper::header::SetCookie;
         use hyper::error::Result;
 
         // a dummy header so we can use headers.remove::<SetCookie2>()
-        #[derive(Clone, Debug)]
+        #[derive(Clone, Debug, HeapSizeOf)]
         struct SetCookie2;
         impl Header for SetCookie2 {
             fn header_name() -> &'static str {
                 "set-cookie2"
             }
 
             fn parse_header(_: &[Vec<u8>]) -> Result<SetCookie2> {
                 unimplemented!()
--- a/servo/components/script/dom/xmlhttprequesteventtarget.rs
+++ b/servo/components/script/dom/xmlhttprequesteventtarget.rs
@@ -10,16 +10,17 @@ use dom::eventtarget::{EventTarget, Even
 
 #[derive(JSTraceable, Copy, Clone, PartialEq, HeapSizeOf)]
 pub enum XMLHttpRequestEventTargetTypeId {
     XMLHttpRequest,
     XMLHttpRequestUpload,
 }
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct XMLHttpRequestEventTarget {
     eventtarget: EventTarget,
 }
 
 impl XMLHttpRequestEventTarget {
     pub fn new_inherited(type_id: XMLHttpRequestEventTargetTypeId) -> XMLHttpRequestEventTarget {
         XMLHttpRequestEventTarget {
             eventtarget: EventTarget::new_inherited(EventTargetTypeId::XMLHttpRequestEventTarget(type_id))
--- a/servo/components/script/dom/xmlhttprequestupload.rs
+++ b/servo/components/script/dom/xmlhttprequestupload.rs
@@ -7,16 +7,17 @@ use dom::bindings::codegen::Bindings::XM
 use dom::bindings::global::GlobalRef;
 use dom::bindings::js::Root;
 use dom::bindings::utils::reflect_dom_object;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
 use dom::xmlhttprequesteventtarget::XMLHttpRequestEventTarget;
 use dom::xmlhttprequesteventtarget::XMLHttpRequestEventTargetTypeId;
 
 #[dom_struct]
+#[derive(HeapSizeOf)]
 pub struct XMLHttpRequestUpload {
     eventtarget: XMLHttpRequestEventTarget
 }
 
 impl XMLHttpRequestUpload {
     fn new_inherited() -> XMLHttpRequestUpload {
         XMLHttpRequestUpload {
             eventtarget: XMLHttpRequestEventTarget::new_inherited(
--- a/servo/components/script/lib.rs
+++ b/servo/components/script/lib.rs
@@ -61,16 +61,17 @@ extern crate time;
 extern crate canvas;
 extern crate canvas_traits;
 extern crate rand;
 #[macro_use]
 extern crate profile_traits;
 extern crate script_traits;
 extern crate selectors;
 extern crate smallvec;
+#[macro_use]
 extern crate util;
 extern crate websocket;
 #[macro_use]
 extern crate style;
 extern crate unicase;
 extern crate url;
 extern crate uuid;
 extern crate string_cache;
--- a/servo/components/script/mem.rs
+++ b/servo/components/script/mem.rs
@@ -1,16 +1,20 @@
 /* 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::bindings::codegen::InheritTypes::*;
+use dom::element::ElementTypeId;
 use dom::eventtarget::{EventTarget, EventTargetTypeId};
+use dom::htmlelement::HTMLElementTypeId;
+use dom::htmlmediaelement::HTMLMediaElementTypeId::{HTMLAudioElement, HTMLVideoElement};
+use dom::htmltablecellelement::HTMLTableCellElementTypeId::{HTMLTableDataCellElement, HTMLTableHeaderCellElement};
 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
@@ -24,13 +28,222 @@ pub fn heap_size_of_eventtarget(target: 
     //      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,
+        &EventTargetTypeId::Node(NodeTypeId::Element(ElementTypeId::Element)) =>
+            heap_size_of_self_and_children(ElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLElement))) =>
+            heap_size_of_self_and_children(HTMLElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLAnchorElement))) =>
+            heap_size_of_self_and_children(HTMLAnchorElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLAppletElement))) =>
+            heap_size_of_self_and_children(HTMLAppletElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLAreaElement))) =>
+            heap_size_of_self_and_children(HTMLAreaElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLBaseElement))) =>
+            heap_size_of_self_and_children(HTMLBaseElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLBRElement))) =>
+            heap_size_of_self_and_children(HTMLBRElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLBodyElement))) =>
+            heap_size_of_self_and_children(HTMLBodyElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLButtonElement))) =>
+            heap_size_of_self_and_children(HTMLButtonElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLCanvasElement))) =>
+            heap_size_of_self_and_children(HTMLCanvasElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLDataElement))) =>
+            heap_size_of_self_and_children(HTMLDataElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLDataListElement))) =>
+            heap_size_of_self_and_children(HTMLDataListElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLDialogElement))) =>
+            heap_size_of_self_and_children(HTMLDialogElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLDirectoryElement))) =>
+            heap_size_of_self_and_children(HTMLDirectoryElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLDListElement))) =>
+            heap_size_of_self_and_children(HTMLDListElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLDivElement))) =>
+            heap_size_of_self_and_children(HTMLDivElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLEmbedElement))) =>
+            heap_size_of_self_and_children(HTMLEmbedElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLFieldSetElement))) =>
+            heap_size_of_self_and_children(HTMLFieldSetElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLFontElement))) =>
+            heap_size_of_self_and_children(HTMLFontElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLFormElement))) =>
+            heap_size_of_self_and_children(HTMLFormElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLFrameElement))) =>
+            heap_size_of_self_and_children(HTMLFrameElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLFrameSetElement))) =>
+            heap_size_of_self_and_children(HTMLFrameSetElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLHRElement))) =>
+            heap_size_of_self_and_children(HTMLHRElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLHeadElement))) =>
+            heap_size_of_self_and_children(HTMLHeadElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLHeadingElement))) =>
+            heap_size_of_self_and_children(HTMLHeadingElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLHtmlElement))) =>
+            heap_size_of_self_and_children(HTMLHtmlElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLIFrameElement))) =>
+            heap_size_of_self_and_children(HTMLIFrameElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLImageElement))) =>
+            heap_size_of_self_and_children(HTMLImageElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLInputElement))) =>
+            heap_size_of_self_and_children(HTMLInputElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLLabelElement))) =>
+            heap_size_of_self_and_children(HTMLLabelElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLLegendElement))) =>
+            heap_size_of_self_and_children(HTMLLegendElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLLinkElement))) =>
+            heap_size_of_self_and_children(HTMLLinkElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLLIElement))) =>
+            heap_size_of_self_and_children(HTMLLIElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLMapElement))) =>
+            heap_size_of_self_and_children(HTMLMapElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(ElementTypeId::HTMLElement(
+        HTMLElementTypeId::HTMLMediaElement(HTMLAudioElement)))) =>
+            heap_size_of_self_and_children(HTMLAudioElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(ElementTypeId::HTMLElement(
+        HTMLElementTypeId::HTMLMediaElement(HTMLVideoElement)))) =>
+            heap_size_of_self_and_children(HTMLVideoElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLMetaElement))) =>
+            heap_size_of_self_and_children(HTMLMetaElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLMeterElement))) =>
+            heap_size_of_self_and_children(HTMLMeterElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLModElement))) =>
+            heap_size_of_self_and_children(HTMLModElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLObjectElement))) =>
+            heap_size_of_self_and_children(HTMLObjectElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOListElement))) =>
+            heap_size_of_self_and_children(HTMLOListElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOptGroupElement))) =>
+            heap_size_of_self_and_children(HTMLOptGroupElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOptionElement))) =>
+            heap_size_of_self_and_children(HTMLOptionElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOutputElement))) =>
+            heap_size_of_self_and_children(HTMLOutputElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLParagraphElement))) =>
+            heap_size_of_self_and_children(HTMLParagraphElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLParamElement))) =>
+            heap_size_of_self_and_children(HTMLParamElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLPreElement))) =>
+            heap_size_of_self_and_children(HTMLPreElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLProgressElement))) =>
+            heap_size_of_self_and_children(HTMLProgressElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLQuoteElement))) =>
+            heap_size_of_self_and_children(HTMLQuoteElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLScriptElement))) =>
+            heap_size_of_self_and_children(HTMLScriptElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLSelectElement))) =>
+            heap_size_of_self_and_children(HTMLSelectElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLSourceElement))) =>
+            heap_size_of_self_and_children(HTMLSourceElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLSpanElement))) =>
+            heap_size_of_self_and_children(HTMLSpanElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLStyleElement))) =>
+            heap_size_of_self_and_children(HTMLStyleElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableElement))) =>
+            heap_size_of_self_and_children(HTMLTableElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableCaptionElement))) =>
+            heap_size_of_self_and_children(HTMLTableCaptionElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(ElementTypeId::HTMLElement(
+        HTMLElementTypeId::HTMLTableCellElement(HTMLTableDataCellElement)))) =>
+            heap_size_of_self_and_children(HTMLTableDataCellElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(ElementTypeId::HTMLElement(
+        HTMLElementTypeId::HTMLTableCellElement(HTMLTableHeaderCellElement)))) =>
+            heap_size_of_self_and_children(HTMLTableHeaderCellElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableColElement))) =>
+            heap_size_of_self_and_children(HTMLTableColElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableRowElement))) =>
+            heap_size_of_self_and_children(HTMLTableRowElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTableSectionElement))) =>
+            heap_size_of_self_and_children(HTMLTableSectionElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTemplateElement))) =>
+            heap_size_of_self_and_children(HTMLTemplateElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTextAreaElement))) =>
+            heap_size_of_self_and_children(HTMLTextAreaElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTimeElement))) =>
+            heap_size_of_self_and_children(HTMLTimeElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTitleElement))) =>
+            heap_size_of_self_and_children(HTMLTitleElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTrackElement))) =>
+            heap_size_of_self_and_children(HTMLTrackElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLUListElement))) =>
+            heap_size_of_self_and_children(HTMLUListElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::Element(
+        ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLUnknownElement))) =>
+            heap_size_of_self_and_children(HTMLUnknownElementCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::WebSocket => 0,
+        &EventTargetTypeId::Worker => 0,
+        &EventTargetTypeId::FileReader => 0,
+        &EventTargetTypeId::WorkerGlobalScope(_) => 0,
+        &EventTargetTypeId::XMLHttpRequestEventTarget(_) => 0,
+        &EventTargetTypeId::Node(NodeTypeId::DocumentType) =>
+            heap_size_of_self_and_children(DocumentTypeCast::to_ref(target).unwrap()),
+        &EventTargetTypeId::Node(NodeTypeId::DocumentFragment) =>
+            heap_size_of_self_and_children(DocumentFragmentCast::to_ref(target).unwrap()),
     }
 }
--- a/servo/components/script/textinput.rs
+++ b/servo/components/script/textinput.rs
@@ -3,48 +3,50 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 //! Common handling of keyboard input and state management for text input controls
 
 use clipboard_provider::ClipboardProvider;
 use dom::keyboardevent::{KeyboardEvent, KeyboardEventHelpers, key_value};
 use msg::constellation_msg::{SHIFT, CONTROL, ALT, SUPER};
 use msg::constellation_msg::{Key, KeyModifiers};
+use util::mem::HeapSizeOf;
 use util::str::{DOMString, slice_chars};
 
 use std::borrow::ToOwned;
 use std::cmp::{min, max};
 use std::default::Default;
 
 
 #[derive(Copy, Clone, PartialEq)]
 pub enum Selection {
     Selected,
     NotSelected
 }
 
-#[derive(JSTraceable, Copy, Clone)]
+#[derive(JSTraceable, Copy, Clone, HeapSizeOf)]
 pub struct TextPoint {
     /// 0-based line number
     pub line: usize,
     /// 0-based column number
     pub index: usize,
 }
 
 /// Encapsulated state for handling keyboard input in a single or multiline text input control.
-#[derive(JSTraceable)]
+#[derive(JSTraceable, HeapSizeOf)]
 pub struct TextInput<T: ClipboardProvider> {
     /// Current text input content, split across lines without trailing '\n'
     lines: Vec<DOMString>,
     /// Current cursor input point
     pub edit_point: TextPoint,
     /// Beginning of selection range with edit_point as end that can span multiple lines.
     selection_begin: Option<TextPoint>,
     /// Is this a multiline input?
     multiline: bool,
+    #[ignore_heap_size_of = "Can't easily measure this generic type"]
     clipboard_provider: T,
 }
 
 /// Resulting action to be taken by the owner of a text input that is handling an event.
 pub enum KeyReaction {
     TriggerDefaultAction,
     DispatchInput,
     Nothing,
--- a/servo/components/servo/Cargo.lock
+++ b/servo/components/servo/Cargo.lock
@@ -125,18 +125,20 @@ version = "0.0.1"
 dependencies = [
  "azure 0.1.0 (git+https://github.com/servo/rust-azure)",
  "cssparser 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "gfx_traits 0.0.1",
  "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",
  "serde 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_macros 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "util 0.0.1",
 ]
 
 [[package]]
 name = "cgl"
 version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "gleam 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -297,16 +299,17 @@ dependencies = [
 [[package]]
 name = "devtools_traits"
 version = "0.0.1"
 dependencies = [
  "bitflags 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "hyper 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)",
  "msg 0.0.1",
+ "plugins 0.0.1",
  "rustc-serialize 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_macros 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
 ]
 
@@ -959,16 +962,17 @@ dependencies = [
 name = "net_traits"
 version = "0.0.1"
 dependencies = [
  "euclid 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "hyper 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)",
  "log 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "msg 0.0.1",
+ "plugins 0.0.1",
  "png 0.1.0 (git+https://github.com/servo/rust-png)",
  "regex 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex_macros 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_macros 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "stb_image 0.1.0 (git+https://github.com/servo/rust-stb-image)",
  "url 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
  "util 0.0.1",
@@ -1548,27 +1552,29 @@ name = "util"
 version = "0.0.1"
 dependencies = [
  "azure 0.1.0 (git+https://github.com/servo/rust-azure)",
  "bitflags 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "getopts 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "html5ever 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "hyper 0.6.8 (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.14 (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)",
  "num 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "plugins 0.0.1",
  "rand 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-serialize 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
+ "selectors 0.1.0 (git+https://github.com/servo/rust-selectors)",
  "serde 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_macros 0.5.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.11 (registry+https://github.com/rust-lang/crates.io-index)",
  "url 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
--- a/servo/components/style/properties.mako.rs
+++ b/servo/components/style/properties.mako.rs
@@ -5484,19 +5484,21 @@ mod property_bit_field {
             % endif
         % endfor
     }
 }
 
 
 /// Declarations are stored in reverse order.
 /// Overridden declarations are skipped.
-#[derive(Debug, PartialEq)]
+#[derive(Debug, PartialEq, HeapSizeOf)]
 pub struct PropertyDeclarationBlock {
+    #[ignore_heap_size_of = "#7038"]
     pub important: Arc<Vec<PropertyDeclaration>>,
+    #[ignore_heap_size_of = "#7038"]
     pub normal: Arc<Vec<PropertyDeclaration>>,
 }
 
 
 pub fn parse_style_attribute(input: &str, base_url: &Url) -> PropertyDeclarationBlock {
     let context = ParserContext::new(Origin::Author, base_url);
     parse_property_declaration_list(&context, &mut Parser::new(input))
 }
--- a/servo/components/util/Cargo.toml
+++ b/servo/components/util/Cargo.toml
@@ -33,24 +33,28 @@ features = [ "serde-serialization" ]
 
 [dependencies.ipc-channel]
 git = "https://github.com/pcwalton/ipc-channel"
 
 [dependencies.url]
 version = "0.2"
 features = [ "serde_serialization" ]
 
+[dependencies.selectors]
+git = "https://github.com/servo/rust-selectors"
+
 [dependencies]
 log = "0.3"
 bitflags = "0.3"
 html5ever = { version = "0.2.1", features = ["unstable"] }
 libc = "0.1"
 rand = "0.3"
 rustc-serialize = "0.3"
 smallvec = "0.1"
 num_cpus = "0.2.2"
 num = "0.1.24"
 euclid = "0.1"
 serde = "0.5"
 serde_macros = "0.5"
 string_cache = "0.1"
 lazy_static = "0.1"
 getopts = "0.2.11"
+hyper = "0.6"
--- a/servo/components/util/lib.rs
+++ b/servo/components/util/lib.rs
@@ -26,24 +26,26 @@
 
 extern crate azure;
 extern crate alloc;
 #[macro_use] extern crate bitflags;
 #[macro_use] extern crate cssparser;
 extern crate euclid;
 extern crate getopts;
 extern crate html5ever;
+extern crate hyper;
 extern crate ipc_channel;
 extern crate js;
 extern crate layers;
 extern crate libc;
 extern crate num as num_lib;
 extern crate num_cpus;
 extern crate rand;
 extern crate rustc_serialize;
+extern crate selectors;
 extern crate serde;
 extern crate smallvec;
 extern crate string_cache;
 extern crate url;
 
 use std::sync::Arc;
 
 pub mod bezier;
--- a/servo/components/util/mem.rs
+++ b/servo/components/util/mem.rs
@@ -6,35 +6,43 @@
 
 use libc::{c_void, size_t};
 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 std::result::Result;
 
 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 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 str::LengthOrPercentageOrAuto;
 use string_cache::atom::Atom;
+use string_cache::namespace::Namespace;
 use url;
+use hyper::method::Method;
+use hyper::http::RawStatus;
+use hyper::header::ContentType;
+use hyper::mime::{Mime, TopLevel, SubLevel, Attr, Value};
+use selectors::parser::{PseudoElement, Selector, CompoundSelector, SimpleSelector, Combinator};
+use rand::OsRng;
 
 extern {
     // Get the size of a heap block.
     //
     // Ideally Rust would expose a function like this in std::rt::heap, which would avoid the
     // jemalloc dependence.
     //
     // The C prototype is `je_malloc_usable_size(JEMALLOC_USABLE_SIZE_CONST void *ptr)`. On some
@@ -280,25 +288,132 @@ macro_rules! known_heap_size(
             fn heap_size_of_children(&self) -> usize {
                 $size
             }
         }
         )+
     );
 );
 
+// 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
+    }
+}
+
+impl HeapSizeOf for Method {
+    fn heap_size_of_children(&self) -> usize {
+        match self {
+            &Method::Extension(ref str) => str.heap_size_of_children(),
+            _ => 0
+        }
+    }
+}
+
+impl<T: HeapSizeOf, U: HeapSizeOf> HeapSizeOf for Result<T, U> {
+    fn heap_size_of_children(&self) -> usize {
+        match self {
+            &Result::Ok(ref ok) => ok.heap_size_of_children(),
+            &Result::Err(ref err) => err.heap_size_of_children()
+        }
+    }
+}
+
+impl HeapSizeOf for () {
+    fn heap_size_of_children(&self) -> usize {
+        0
+    }
+}
+
+impl HeapSizeOf for Selector {
+    fn heap_size_of_children(&self) -> usize {
+        let &Selector { ref compound_selectors, ref pseudo_element, ref specificity } = self;
+        compound_selectors.heap_size_of_children() + pseudo_element.heap_size_of_children() +
+        specificity.heap_size_of_children()
+    }
+}
+
+impl HeapSizeOf for CompoundSelector {
+    fn heap_size_of_children(&self) -> usize {
+        let &CompoundSelector { ref simple_selectors, ref next } = self;
+        simple_selectors.heap_size_of_children() + next.heap_size_of_children()
+    }
+}
+
+impl HeapSizeOf for SimpleSelector {
+    fn heap_size_of_children(&self) -> usize {
+        match self {
+            &SimpleSelector::Negation(ref vec) => vec.heap_size_of_children(),
+            &SimpleSelector::AttrIncludes(_, ref str) | &SimpleSelector::AttrPrefixMatch(_, ref str) |
+            &SimpleSelector::AttrSubstringMatch(_, ref str) | &SimpleSelector::AttrSuffixMatch(_, ref str)
+            => str.heap_size_of_children(),
+            &SimpleSelector::AttrEqual(_, ref str, _) => str.heap_size_of_children(),
+            &SimpleSelector::AttrDashMatch(_, ref first, ref second) => first.heap_size_of_children()
+            + second.heap_size_of_children(),
+            // All other types come down to Atom, enum or i32, all 0
+            _ => 0
+        }
+    }
+}
+
+impl HeapSizeOf for ContentType {
+    fn heap_size_of_children(&self) -> usize {
+        let &ContentType(ref mime) = self;
+        mime.heap_size_of_children()
+    }
+}
+
+impl HeapSizeOf for Mime {
+    fn heap_size_of_children(&self) -> usize {
+        let &Mime(ref top_level, ref sub_level, ref vec) = self;
+        top_level.heap_size_of_children() + sub_level.heap_size_of_children() +
+        vec.heap_size_of_children()
+    }
+}
+
+impl HeapSizeOf for TopLevel {
+    fn heap_size_of_children(&self) -> usize {
+        match self {
+            &TopLevel::Ext(ref str) => str.heap_size_of_children(),
+            _ => 0
+        }
+    }
+}
+
+impl HeapSizeOf for SubLevel {
+    fn heap_size_of_children(&self) -> usize {
+        match self {
+            &SubLevel::Ext(ref str) => str.heap_size_of_children(),
+            _ => 0
+        }
+    }
+}
+
+impl HeapSizeOf for Attr {
+    fn heap_size_of_children(&self) -> usize {
+        match self {
+            &Attr::Ext(ref str) => str.heap_size_of_children(),
+            _ => 0
+        }
+    }
+}
+
+impl HeapSizeOf for Value {
+    fn heap_size_of_children(&self) -> usize {
+        match self {
+            &Value::Ext(ref str) => str.heap_size_of_children(),
+            _ => 0
+        }
+    }
+}
 
 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>, Range<T>);
 known_heap_size!(0, Length<T, U>, ScaleFactor<T, U, V>);
 
-known_heap_size!(0, Au, WritingMode, CSSParserColor, Color, RGBA, Cursor, Matrix4, Atom);
-known_heap_size!(0, JSVal, PagePx, ViewportPx, DevicePixel, QuirksMode);
+known_heap_size!(0, Au, WritingMode, CSSParserColor, Color, RGBA, Cursor, Matrix4, Atom, Namespace);
+known_heap_size!(0, JSVal, PagePx, ViewportPx, DevicePixel, QuirksMode, OsRng, RawStatus, LengthOrPercentageOrAuto);
 
-// 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
-    }
-}
+known_heap_size!(0, PseudoElement, Combinator, str);