Backed out 4 changesets (bug 1519454) for api.rs build bustage CLOSED TREE
authorBogdan Tara <btara@mozilla.com>
Sat, 12 Jan 2019 21:54:54 +0200
changeset 453660 5d2e7b3ecb63f0770d409abd397b93af5c0b3fd7
parent 453659 21d74c03c00a986914f5dc6ad44e5027b186f049
child 453661 d5e192fd022fd4ced320499ba7d2f0229b9fa9f2
push id111117
push userdvarga@mozilla.com
push dateSun, 13 Jan 2019 10:12:56 +0000
treeherdermozilla-inbound@1218e374fbc7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1519454
milestone66.0a1
backs out21d74c03c00a986914f5dc6ad44e5027b186f049
054028a8d4a75083599eda3791913d0d66aa1b8d
e9b1d04247debbf9506351b855091546ce59c4d1
f3ef205b4f632c18d20eb83e7b5f6a0e3ca77b21
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 4 changesets (bug 1519454) for api.rs build bustage CLOSED TREE Backed out changeset 21d74c03c00a (bug 1519454) Backed out changeset 054028a8d4a7 (bug 1519454) Backed out changeset e9b1d04247de (bug 1519454) Backed out changeset f3ef205b4f63 (bug 1519454)
Cargo.lock
gfx/thebes/gfxPlatform.cpp
gfx/webrender_bindings/webrender_ffi.h
gfx/webrender_bindings/webrender_ffi_generated.h
gfx/wr/Cargo.lock
gfx/wr/webrender/Cargo.toml
gfx/wr/webrender/src/border.rs
gfx/wr/webrender/src/box_shadow.rs
gfx/wr/webrender/src/clip.rs
gfx/wr/webrender/src/clip_scroll_tree.rs
gfx/wr/webrender/src/freelist.rs
gfx/wr/webrender/src/glyph_rasterizer/mod.rs
gfx/wr/webrender/src/gpu_cache.rs
gfx/wr/webrender/src/gpu_types.rs
gfx/wr/webrender/src/hit_test.rs
gfx/wr/webrender/src/intern.rs
gfx/wr/webrender/src/lib.rs
gfx/wr/webrender/src/prim_store/borders.rs
gfx/wr/webrender/src/prim_store/gradient.rs
gfx/wr/webrender/src/prim_store/image.rs
gfx/wr/webrender/src/prim_store/line_dec.rs
gfx/wr/webrender/src/prim_store/mod.rs
gfx/wr/webrender/src/prim_store/picture.rs
gfx/wr/webrender/src/prim_store/text_run.rs
gfx/wr/webrender/src/render_backend.rs
gfx/wr/webrender/src/render_task.rs
gfx/wr/webrender/src/renderer.rs
gfx/wr/webrender/src/resource_cache.rs
gfx/wr/webrender/src/scene_builder.rs
gfx/wr/webrender/src/util.rs
gfx/wr/webrender_api/Cargo.toml
gfx/wr/webrender_api/src/api.rs
gfx/wr/webrender_api/src/color.rs
gfx/wr/webrender_api/src/display_item.rs
gfx/wr/webrender_api/src/font.rs
gfx/wr/webrender_api/src/image.rs
gfx/wr/webrender_api/src/lib.rs
gfx/wr/webrender_api/src/units.rs
gfx/wr/wr_malloc_size_of/Cargo.toml
gfx/wr/wr_malloc_size_of/LICENSE-APACHE
gfx/wr/wr_malloc_size_of/LICENSE-MIT
gfx/wr/wr_malloc_size_of/lib.rs
servo/components/malloc_size_of/lib.rs
servo/components/malloc_size_of_derive/Cargo.toml
servo/components/malloc_size_of_derive/LICENSE-APACHE
servo/components/malloc_size_of_derive/LICENSE-MIT
servo/components/malloc_size_of_derive/lib.rs
servo/components/style/Cargo.toml
servo/components/style_traits/Cargo.toml
third_party/rust/malloc_size_of_derive/.cargo-checksum.json
third_party/rust/malloc_size_of_derive/Cargo.toml
third_party/rust/malloc_size_of_derive/LICENSE-APACHE
third_party/rust/malloc_size_of_derive/LICENSE-MIT
third_party/rust/malloc_size_of_derive/README.md
third_party/rust/malloc_size_of_derive/lib.rs
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1471,18 +1471,17 @@ dependencies = [
  "smallbitvec 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "thin-slice 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "malloc_size_of_derive"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
+version = "0.0.1"
 dependencies = [
  "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "syn 0.15.24 (registry+https://github.com/rust-lang/crates.io-index)",
  "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "matches"
@@ -2427,17 +2426,17 @@ dependencies = [
  "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "hashglobe 0.1.0",
  "indexmap 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "itertools 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "malloc_size_of 0.0.1",
- "malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "malloc_size_of_derive 0.0.1",
  "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "new_debug_unreachable 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "nsstring 0.1.0",
  "num-derive 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ordered-float 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2477,17 +2476,17 @@ dependencies = [
 name = "style_traits"
 version = "0.0.1"
 dependencies = [
  "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.19.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "malloc_size_of 0.0.1",
- "malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "malloc_size_of_derive 0.0.1",
  "selectors 0.21.0",
  "servo_arc 0.1.1",
 ]
 
 [[package]]
 name = "stylo_tests"
 version = "0.0.1"
 dependencies = [
@@ -2991,49 +2990,45 @@ dependencies = [
  "core-text 13.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "dwrote 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "plane-split 0.13.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
  "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "thread_profiler 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "webrender_api 0.58.0",
  "webrender_build 0.0.1",
- "wr_malloc_size_of 0.0.1",
 ]
 
 [[package]]
 name = "webrender_api"
 version = "0.58.0"
 dependencies = [
  "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "dwrote 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.19.4 (registry+https://github.com/rust-lang/crates.io-index)",
- "malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.80 (git+https://github.com/servo/serde?branch=deserialize_from_enums9)",
  "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
- "wr_malloc_size_of 0.0.1",
 ]
 
 [[package]]
 name = "webrender_bindings"
 version = "0.1.0"
 dependencies = [
  "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -3109,24 +3104,16 @@ dependencies = [
 name = "winreg"
 version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "winapi 0.3.6 (git+https://github.com/froydnj/winapi-rs?branch=aarch64)",
 ]
 
 [[package]]
-name = "wr_malloc_size_of"
-version = "0.0.1"
-dependencies = [
- "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.19.4 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
 name = "ws2_32-sys"
 version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
@@ -3319,17 +3306,16 @@ dependencies = [
 "checksum libudev 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea626d3bdf40a1c5aee3bcd4f40826970cae8d80a8fec934c82a63840094dcfe"
 "checksum libz-sys 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "3fdd64ef8ee652185674455c1d450b83cbc8ad895625d543b5324d923f82e4d8"
 "checksum linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70fb39025bc7cdd76305867c4eccf2f2dcf6e9a57f5b21a93e1c2d86cd03ec9e"
 "checksum lmdb-rkv 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "07d8d72d709440ac7a19b71e04fb66684ec7547b3831817872454b01fdaefe23"
 "checksum lmdb-sys 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d5b392838cfe8858e86fac37cf97a0e8c55cc60ba0a18365cadc33092f128ce9"
 "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c"
 "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
 "checksum log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fcce5fa49cc693c312001daf1d13411c4a5283796bac1084299ea3e567113f"
-"checksum malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "35adee9ed962cf7d07d62cb58bc45029f3227f5b5b86246caa8632f06c187bc3"
 "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"
 "checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a"
 "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
 "checksum memmap 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "46f3c7359028b31999287dae4e5047ddfe90a23b7dca2282ce759b491080c99b"
 "checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff"
 "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
 "checksum miniz_oxide 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aaa2d3ad070f428fffbd7d3ca2ea20bb0d8cffe9024405c44e1840bc1418b398"
 "checksum miniz_oxide_c_api 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "92d98fdbd6145645828069b37ea92ca3de225e000d80702da25c20d3584b38a5"
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -675,27 +675,16 @@ struct WebRenderMemoryReporterHelper {
 static void FinishAsyncMemoryReport() {
   nsCOMPtr<nsIMemoryReporterManager> imgr =
       do_GetService("@mozilla.org/memory-reporter-manager;1");
   if (imgr) {
     imgr->EndReport();
   }
 }
 
-// clang-format off
-// (For some reason, clang-format gets the second macro right, but totally mangles the first).
-#define REPORT_INTERNER(id)                      \
-  helper.Report(aReport.interning.id##_interner, \
-                "interning/" #id "/interners");
-// clang-format on
-
-#define REPORT_DATA_STORE(id)                      \
-  helper.Report(aReport.interning.id##_data_store, \
-                "interning/" #id "/data-stores");
-
 NS_IMPL_ISUPPORTS(WebRenderMemoryReporter, nsIMemoryReporter)
 
 NS_IMETHODIMP
 WebRenderMemoryReporter::CollectReports(nsIHandleReportCallback* aHandleReport,
                                         nsISupports* aData, bool aAnonymize) {
   MOZ_ASSERT(XRE_IsParentProcess());
   MOZ_ASSERT(NS_IsMainThread());
   layers::CompositorManagerChild* manager =
@@ -704,29 +693,29 @@ WebRenderMemoryReporter::CollectReports(
     FinishAsyncMemoryReport();
     return NS_OK;
   }
 
   WebRenderMemoryReporterHelper helper(aHandleReport, aData);
   manager->SendReportMemory(
       [=](wr::MemoryReport aReport) {
         // CPU Memory.
+        helper.Report(aReport.primitive_stores, "primitive-stores");
         helper.Report(aReport.clip_stores, "clip-stores");
         helper.Report(aReport.gpu_cache_metadata, "gpu-cache/metadata");
         helper.Report(aReport.gpu_cache_cpu_mirror, "gpu-cache/cpu-mirror");
         helper.Report(aReport.render_tasks, "render-tasks");
         helper.Report(aReport.hit_testers, "hit-testers");
         helper.Report(aReport.fonts, "resource-cache/fonts");
         helper.Report(aReport.images, "resource-cache/images");
         helper.Report(aReport.rasterized_blobs,
                       "resource-cache/rasterized-blobs");
         helper.Report(aReport.shader_cache, "shader-cache");
-
-        WEBRENDER_FOR_EACH_INTERNER(REPORT_INTERNER);
-        WEBRENDER_FOR_EACH_INTERNER(REPORT_DATA_STORE);
+        helper.Report(aReport.data_stores, "interning/data-stores");
+        helper.Report(aReport.interners, "interning/interners");
 
         // GPU Memory.
         helper.ReportTexture(aReport.gpu_cache_textures, "gpu-cache");
         helper.ReportTexture(aReport.vertex_data_textures, "vertex-data");
         helper.ReportTexture(aReport.render_target_textures, "render-targets");
         helper.ReportTexture(aReport.texture_cache_textures, "texture-cache");
         helper.ReportTexture(aReport.depth_target_textures, "depth-targets");
         helper.ReportTexture(aReport.swap_chain, "swap-chains");
@@ -735,19 +724,16 @@ WebRenderMemoryReporter::CollectReports(
       },
       [](mozilla::ipc::ResponseRejectReason&& aReason) {
         FinishAsyncMemoryReport();
       });
 
   return NS_OK;
 }
 
-#undef REPORT_INTERNER
-#undef REPORT_DATA_STORE
-
 static const char* const WR_ROLLOUT_PREF = "gfx.webrender.all.qualified";
 static const char* const WR_ROLLOUT_PREF_DEFAULT =
     "gfx.webrender.all.qualified.default";
 static const char* const WR_ROLLOUT_PREF_OVERRIDE =
     "gfx.webrender.all.qualified.gfxPref-default-override";
 static const char* const WR_ROLLOUT_HW_QUALIFIED_OVERRIDE =
     "gfx.webrender.all.qualified.hardware-override";
 static const char* const PROFILE_BEFORE_CHANGE_TOPIC = "profile-before-change";
--- a/gfx/webrender_bindings/webrender_ffi.h
+++ b/gfx/webrender_bindings/webrender_ffi.h
@@ -29,46 +29,20 @@ void gecko_printf_stderr_output(const ch
 void* get_proc_address_from_glcontext(void* glcontext_ptr,
                                       const char* procname);
 void gecko_profiler_register_thread(const char* threadname);
 void gecko_profiler_unregister_thread();
 
 void gecko_profiler_start_marker(const char* name);
 void gecko_profiler_end_marker(const char* name);
 
-// IMPORTANT: Keep this synchronized with enumerate_interners in
-// gfx/wr/webrender_api
-#define WEBRENDER_FOR_EACH_INTERNER(macro) \
-  macro(clip);                             \
-  macro(prim);                             \
-  macro(normal_border);                    \
-  macro(image_border);                     \
-  macro(image);                            \
-  macro(yuv_image);                        \
-  macro(line_decoration);                  \
-  macro(linear_grad);                      \
-  macro(radial_grad);                      \
-  macro(picture);                          \
-  macro(text_run);
-
 // Prelude of types necessary before including webrender_ffi_generated.h
 namespace mozilla {
 namespace wr {
 
-// Because this struct is macro-generated on the Rust side, cbindgen can't see
-// it for some reason. Work around that by re-declaring it here.
-#define DECLARE_MEMBERS(id) \
-  uintptr_t id##_interner;  \
-  uintptr_t id##_data_store;
-struct InterningMemoryReport {
-  WEBRENDER_FOR_EACH_INTERNER(DECLARE_MEMBERS)
-};
-
-#undef DECLARE_MEMBERS
-
 struct FontInstanceFlags {
   uint32_t bits;
 
   bool operator==(const FontInstanceFlags& aOther) const {
     return bits == aOther.bits;
   }
 
   FontInstanceFlags& operator=(uint32_t aBits) {
--- a/gfx/webrender_bindings/webrender_ffi_generated.h
+++ b/gfx/webrender_bindings/webrender_ffi_generated.h
@@ -506,32 +506,55 @@ struct WrPipelineInfo {
   bool operator==(const WrPipelineInfo& aOther) const {
     return epochs == aOther.epochs &&
            removed_pipelines == aOther.removed_pipelines;
   }
 };
 
 /// Collection of heap sizes, in bytes.
 struct MemoryReport {
+  uintptr_t primitive_stores;
   uintptr_t clip_stores;
   uintptr_t gpu_cache_metadata;
   uintptr_t gpu_cache_cpu_mirror;
   uintptr_t render_tasks;
   uintptr_t hit_testers;
   uintptr_t fonts;
   uintptr_t images;
   uintptr_t rasterized_blobs;
   uintptr_t shader_cache;
-  InterningMemoryReport interning;
+  uintptr_t data_stores;
+  uintptr_t interners;
   uintptr_t gpu_cache_textures;
   uintptr_t vertex_data_textures;
   uintptr_t render_target_textures;
   uintptr_t texture_cache_textures;
   uintptr_t depth_target_textures;
   uintptr_t swap_chain;
+
+  bool operator==(const MemoryReport& aOther) const {
+    return primitive_stores == aOther.primitive_stores &&
+           clip_stores == aOther.clip_stores &&
+           gpu_cache_metadata == aOther.gpu_cache_metadata &&
+           gpu_cache_cpu_mirror == aOther.gpu_cache_cpu_mirror &&
+           render_tasks == aOther.render_tasks &&
+           hit_testers == aOther.hit_testers &&
+           fonts == aOther.fonts &&
+           images == aOther.images &&
+           rasterized_blobs == aOther.rasterized_blobs &&
+           shader_cache == aOther.shader_cache &&
+           data_stores == aOther.data_stores &&
+           interners == aOther.interners &&
+           gpu_cache_textures == aOther.gpu_cache_textures &&
+           vertex_data_textures == aOther.vertex_data_textures &&
+           render_target_textures == aOther.render_target_textures &&
+           texture_cache_textures == aOther.texture_cache_textures &&
+           depth_target_textures == aOther.depth_target_textures &&
+           swap_chain == aOther.swap_chain;
+  }
 };
 
 template<typename T, typename U>
 struct TypedSize2D {
   T width;
   T height;
 
   bool operator==(const TypedSize2D& aOther) const {
--- a/gfx/wr/Cargo.lock
+++ b/gfx/wr/Cargo.lock
@@ -753,26 +753,16 @@ source = "registry+https://github.com/ru
 name = "malloc_buf"
 version = "0.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
-name = "malloc_size_of_derive"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.15.17 (registry+https://github.com/rust-lang/crates.io-index)",
- "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
 name = "matches"
 version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "memchr"
 version = "2.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1326,27 +1316,16 @@ version = "0.15.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
-name = "synstructure"
-version = "0.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
- "syn 0.15.17 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
 name = "tempfile"
 version = "3.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
  "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "redox_syscall 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
  "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1569,17 +1548,16 @@ dependencies = [
  "dwrote 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "freetype 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "gleam 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "image 0.20.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.42 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "mozangle 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "pathfinder_font_renderer 0.5.0 (git+https://github.com/pcwalton/pathfinder?branch=webrender)",
  "pathfinder_gfx_utils 0.2.0 (git+https://github.com/pcwalton/pathfinder?branch=webrender)",
  "pathfinder_partitioner 0.2.0 (git+https://github.com/pcwalton/pathfinder?branch=webrender)",
  "pathfinder_path_utils 0.2.0 (git+https://github.com/pcwalton/pathfinder?branch=webrender)",
  "plane-split 0.13.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "png 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1589,17 +1567,16 @@ dependencies = [
  "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_json 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "thread_profiler 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
  "webrender_api 0.58.0",
  "webrender_build 0.0.1",
- "wr_malloc_size_of 0.0.1",
  "ws 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "webrender-examples"
 version = "0.1.0"
 dependencies = [
  "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1620,22 +1597,20 @@ dependencies = [
  "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "dwrote 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.19.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "ipc-channel 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "serde_derive 1.0.80 (git+https://github.com/servo/serde?branch=deserialize_from_enums9)",
  "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)",
- "wr_malloc_size_of 0.0.1",
 ]
 
 [[package]]
 name = "webrender_build"
 version = "0.0.1"
 dependencies = [
  "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)",
  "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1695,24 +1670,16 @@ dependencies = [
  "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "smithay-client-toolkit 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "wayland-client 0.20.10 (registry+https://github.com/rust-lang/crates.io-index)",
  "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "x11-dl 2.17.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
-name = "wr_malloc_size_of"
-version = "0.0.1"
-dependencies = [
- "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "euclid 0.19.4 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
-[[package]]
 name = "wrench"
 version = "0.3.0"
 dependencies = [
  "app_units 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "bincode 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
  "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1889,17 +1856,16 @@ dependencies = [
 "checksum linked-hash-map 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6d262045c5b87c0861b3f004610afd0e2c851e2908d08b6c870cbb9d5f494ecd"
 "checksum lock_api 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "949826a5ccf18c1b3a7c3d57692778d21768b79e46eb9dd07bfc4c2160036c54"
 "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
 "checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2"
 "checksum lyon_geom 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "216bfb2b880554865fa9deaa14671ab9f1368b942e7007cc8c97c083ac8a7f45"
 "checksum lyon_path 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e9dc8e0746b7cca11960b602f7fe037bb067746a01eab4aa502fed1494544843"
 "checksum lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084"
 "checksum malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
-"checksum malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "35adee9ed962cf7d07d62cb58bc45029f3227f5b5b86246caa8632f06c187bc3"
 "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"
 "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d"
 "checksum memmap 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e2ffa2c986de11a9df78620c01eeaaf27d94d3ff02bf81bfcca953102dd0c6ff"
 "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3"
 "checksum mio 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "75f72a93f046f1517e3cfddc0a096eb756a2ba727d36edc8227dee769a50a9b0"
 "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
 "checksum mozangle 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1f0583e6792917f498bb3a7440f777a59353102063445ab7f5e9d1dc4ed593aa"
 "checksum net2 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)" = "9044faf1413a1057267be51b5afba8eb1090bd2231c693664aa1db716fe1eae0"
@@ -1954,17 +1920,16 @@ dependencies = [
 "checksum sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b4d8bfd0e469f417657573d8451fb33d16cfe0989359b93baf3a1ffc639543d"
 "checksum shared_library 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8254bf098ce4d8d7cc7cc6de438c5488adc5297e5b7ffef88816c0a91bd289c1"
 "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23"
 "checksum smallvec 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "26df3bb03ca5eac2e64192b723d51f56c1b1e0860e7c766281f4598f181acdc8"
 "checksum smithay-client-toolkit 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "428d6c019bb92753be9670367e3f483e4fcef396180a9b59e813b69b20014881"
 "checksum stable_deref_trait 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ffbc596e092fe5f598b12ef46cc03754085ac2f4d8c739ad61c4ae266cc3b3fa"
 "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
 "checksum syn 0.15.17 (registry+https://github.com/rust-lang/crates.io-index)" = "3391038ebc3e4ab24eb028cb0ef2f2dc4ba0cbf72ee895ed6a6fad730640b5bc"
-"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
 "checksum tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "47776f63b85777d984a50ce49d6b9e58826b6a3766a449fc95bc66cd5663c15b"
 "checksum termcolor 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "adc4587ead41bf016f11af03e55a624c06568b5a19db4e90fde573d805074f83"
 "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
 "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693"
 "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963"
 "checksum thread_profiler 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5920e77802b177479ab5795767fa48e68f61b2f516c2ac0041e2978dd8efe483"
 "checksum tiff 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a2cc6c4fd13cb1cfd20abdb196e794ceccb29371855b7e7f575945f920a5b3c2"
 "checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b"
--- a/gfx/wr/webrender/Cargo.toml
+++ b/gfx/wr/webrender/Cargo.toml
@@ -29,31 +29,29 @@ bincode = "1.0"
 bitflags = "1.0"
 byteorder = "1.0"
 cfg-if = "0.1.2"
 fxhash = "0.2.1"
 gleam = "0.6.8"
 image = { optional = true, version = "0.20" }
 lazy_static = "1"
 log = "0.4"
-malloc_size_of_derive = "0.1"
 num-traits = "0.2"
 plane-split = "0.13.3"
 png = { optional = true, version = "0.12" }
 rayon = "1"
 ron = { optional = true, version = "0.1.7" }
 serde = { optional = true, version = "1.0", features = ["serde_derive"] }
 serde_json = { optional = true, version = "1.0" }
 sha2 = "0.8"
 smallvec = "0.6"
 thread_profiler = "0.1.1"
 time = "0.1"
 webrender_api = { version = "0.58.0", path = "../webrender_api" }
 webrender_build = { version = "0.0.1", path = "../webrender_build" }
-wr_malloc_size_of = { version = "0.0.1", path = "../wr_malloc_size_of" }
 ws = { optional = true, version = "0.7.3" }
 
 [dependencies.pathfinder_font_renderer]
 git = "https://github.com/pcwalton/pathfinder"
 branch = "webrender"
 optional = true
 # Uncomment to test FreeType on macOS:
 # features = ["freetype"]
--- a/gfx/wr/webrender/src/border.rs
+++ b/gfx/wr/webrender/src/border.rs
@@ -29,17 +29,17 @@ pub const MAX_BORDER_RESOLUTION: u32 = 2
 /// a list of per-dot information in the first place.
 pub const MAX_DASH_COUNT: u32 = 2048;
 
 // TODO(gw): Perhaps there is a better way to store
 //           the border cache key than duplicating
 //           all the border structs with hashable
 //           variants...
 
-#[derive(Clone, Debug, Hash, MallocSizeOf, PartialEq, Eq)]
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct BorderRadiusAu {
     pub top_left: LayoutSizeAu,
     pub top_right: LayoutSizeAu,
     pub bottom_left: LayoutSizeAu,
     pub bottom_right: LayoutSizeAu,
 }
@@ -61,17 +61,17 @@ impl From<BorderRadiusAu> for BorderRadi
             top_left: LayoutSize::from_au(radius.top_left),
             top_right: LayoutSize::from_au(radius.top_right),
             bottom_right: LayoutSize::from_au(radius.bottom_right),
             bottom_left: LayoutSize::from_au(radius.bottom_left),
         }
     }
 }
 
-#[derive(Clone, Debug, Hash, MallocSizeOf, PartialEq, Eq)]
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct BorderSideAu {
     pub color: ColorU,
     pub style: BorderStyle,
 }
 
 impl From<BorderSide> for BorderSideAu {
@@ -89,17 +89,17 @@ impl From<BorderSideAu> for BorderSide {
             color: side.color.into(),
             style: side.style,
         }
     }
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Debug, Clone, Hash, Eq, MallocSizeOf, PartialEq)]
+#[derive(Debug, Clone, Hash, Eq, PartialEq)]
 pub struct NormalBorderAu {
     pub left: BorderSideAu,
     pub right: BorderSideAu,
     pub top: BorderSideAu,
     pub bottom: BorderSideAu,
     pub radius: BorderRadiusAu,
     /// Whether to apply anti-aliasing on the border corners.
     ///
@@ -143,17 +143,17 @@ impl From<NormalBorderAu> for ApiNormalB
             radius: border.radius.into(),
             do_aa: border.do_aa,
         }
     }
 }
 
 /// Cache key that uniquely identifies a border
 /// segment in the render task cache.
-#[derive(Clone, Debug, Hash, MallocSizeOf, PartialEq, Eq)]
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct BorderSegmentCacheKey {
     pub size: LayoutSizeAu,
     pub radius: LayoutSizeAu,
     pub side0: BorderSideAu,
     pub side1: BorderSideAu,
     pub segment: BorderSegment,
--- a/gfx/wr/webrender/src/box_shadow.rs
+++ b/gfx/wr/webrender/src/box_shadow.rs
@@ -7,17 +7,17 @@ use api::{LayoutRect, LayoutSize, Layout
 use clip::ClipItemKey;
 use display_list_flattener::DisplayListFlattener;
 use gpu_cache::GpuCacheHandle;
 use gpu_types::BoxShadowStretchMode;
 use prim_store::{ScrollNodeAndClipChain, PrimitiveKeyKind};
 use render_task::RenderTaskCacheEntryHandle;
 use util::RectHelpers;
 
-#[derive(Debug, Clone, MallocSizeOf)]
+#[derive(Debug, Clone)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct BoxShadowClipSource {
     // Parameters that define the shadow and are constant.
     pub shadow_radius: BorderRadius,
     pub blur_radius: f32,
     pub clip_mode: BoxShadowClipMode,
     pub stretch_mode_x: BoxShadowStretchMode,
@@ -46,17 +46,17 @@ pub struct BoxShadowClipSource {
 }
 
 // The blur shader samples BLUR_SAMPLE_SCALE * blur_radius surrounding texels.
 pub const BLUR_SAMPLE_SCALE: f32 = 3.0;
 
 // A cache key that uniquely identifies a minimally sized
 // and blurred box-shadow rect that can be stored in the
 // texture cache and applied to clip-masks.
-#[derive(Debug, Clone, Eq, Hash, MallocSizeOf, PartialEq)]
+#[derive(Debug, Clone, Eq, Hash, PartialEq)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct BoxShadowCacheKey {
     pub blur_radius_dp: i32,
     pub clip_mode: BoxShadowClipMode,
     // NOTE(emilio): Only the original allocation size needs to be in the cache
     // key, since the actual size is derived from that.
     pub original_alloc_size: DeviceIntSize,
--- a/gfx/wr/webrender/src/clip.rs
+++ b/gfx/wr/webrender/src/clip.rs
@@ -1,32 +1,33 @@
 /* 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 api::{BorderRadius, ClipMode, ComplexClipRegion, DeviceIntRect, DevicePixelScale, ImageMask};
 use api::{ImageRendering, LayoutRect, LayoutSize, LayoutPoint, LayoutVector2D};
 use api::{BoxShadowClipMode, LayoutToWorldScale, PicturePixel, WorldPixel};
 use api::{PictureRect, LayoutPixel, WorldPoint, WorldSize, WorldRect, LayoutToWorldTransform};
-use api::{ImageKey};
+use api::{VoidPtrToSizeFn, ImageKey};
 use app_units::Au;
 use border::{ensure_no_corner_overlap, BorderRadiusAu};
 use box_shadow::{BLUR_SAMPLE_SCALE, BoxShadowClipSource, BoxShadowCacheKey};
 use clip_scroll_tree::{ClipScrollTree, ROOT_SPATIAL_NODE_INDEX, SpatialNodeIndex};
 use ellipse::Ellipse;
 use gpu_cache::{GpuCache, GpuCacheHandle, ToGpuBlocks};
 use gpu_types::{BoxShadowStretchMode};
 use image::{self, Repetition};
 use intern;
 use internal_types::FastHashSet;
 use prim_store::{ClipData, ImageMaskData, SpaceMapper, VisibleMaskImageTile};
 use prim_store::{PointKey, PrimitiveInstance, SizeKey, RectangleKey};
 use render_task::to_cache_size;
 use resource_cache::{ImageRequest, ResourceCache};
 use std::{cmp, u32};
+use std::os::raw::c_void;
 use util::{extract_inner_rect_safe, project_rect, ScaleOffset};
 
 /*
 
  Module Overview
 
  There are a number of data structures involved in the clip module:
 
@@ -101,17 +102,17 @@ use util::{extract_inner_rect_safe, proj
     | ...              | ...              | ...              | ...              | ...              |
     +------------------+------------------+------------------+------------------+------------------+
 
  */
 
 // Type definitions for interning clip nodes.
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
+#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
 pub struct ClipDataMarker;
 
 pub type ClipDataStore = intern::DataStore<ClipItemKey, ClipNode, ClipDataMarker>;
 pub type ClipDataHandle = intern::Handle<ClipDataMarker>;
 pub type ClipDataUpdateList = intern::UpdateList<ClipItemKey>;
 pub type ClipDataInterner = intern::Interner<ClipItemKey, (), ClipDataMarker>;
 
 // Result of comparing a clip node instance against a local rect.
@@ -128,17 +129,16 @@ enum ClipResult {
 
 // A clip node is a single clip source, along with some
 // positioning information and implementation details
 // that control where the GPU data for this clip source
 // can be found.
 #[derive(Debug)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(MallocSizeOf)]
 pub struct ClipNode {
     pub item: ClipItem,
     pub gpu_cache_handle: GpuCacheHandle,
 }
 
 // Convert from an interning key for a clip item
 // to a clip node, which is cached in the document.
 // TODO(gw): These enums are a bit messy - we should
@@ -181,55 +181,54 @@ impl From<ClipItemKey> for ClipNode {
         }
     }
 }
 
 // Flags that are attached to instances of clip nodes.
 bitflags! {
     #[cfg_attr(feature = "capture", derive(Serialize))]
     #[cfg_attr(feature = "replay", derive(Deserialize))]
-    #[derive(MallocSizeOf)]
     pub struct ClipNodeFlags: u8 {
         const SAME_SPATIAL_NODE = 0x1;
         const SAME_COORD_SYSTEM = 0x2;
     }
 }
 
 // Identifier for a clip chain. Clip chains are stored
 // in a contiguous array in the clip store. They are
 // identified by a simple index into that array.
-#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Hash)]
+#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
 pub struct ClipChainId(pub u32);
 
 // The root of each clip chain is the NONE id. The
 // value is specifically set to u32::MAX so that if
 // any code accidentally tries to access the root
 // node, a bounds error will occur.
 impl ClipChainId {
     pub const NONE: Self = ClipChainId(u32::MAX);
     pub const INVALID: Self = ClipChainId(0xDEADBEEF);
 }
 
 // A clip chain node is an id for a range of clip sources,
 // and a link to a parent clip chain node, or ClipChainId::NONE.
-#[derive(Clone, Debug, MallocSizeOf)]
+#[derive(Clone, Debug)]
 pub struct ClipChainNode {
     pub handle: ClipDataHandle,
     pub local_pos: LayoutPoint,
     pub spatial_node_index: SpatialNodeIndex,
     pub parent_clip_chain_id: ClipChainId,
 }
 
 // When a clip node is found to be valid for a
 // clip chain instance, it's stored in an index
 // buffer style structure. This struct contains
 // an index to the node data itself, as well as
 // some flags describing how this clip node instance
 // is positioned.
-#[derive(Debug, MallocSizeOf)]
+#[derive(Debug)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct ClipNodeInstance {
     pub handle: ClipDataHandle,
     pub flags: ClipNodeFlags,
     pub spatial_node_index: SpatialNodeIndex,
     pub local_pos: LayoutPoint,
 
@@ -246,26 +245,25 @@ pub struct ClipNodeRange {
     pub count: u32,
 }
 
 // A helper struct for converting between coordinate systems
 // of clip sources and primitives.
 // todo(gw): optimize:
 //  separate arrays for matrices
 //  cache and only build as needed.
-#[derive(Debug, MallocSizeOf)]
+#[derive(Debug)]
 enum ClipSpaceConversion {
     Local,
     ScaleOffset(ScaleOffset),
     Transform(LayoutToWorldTransform),
 }
 
 // Temporary information that is cached and reused
 // during building of a clip chain instance.
-#[derive(MallocSizeOf)]
 struct ClipNodeInfo {
     conversion: ClipSpaceConversion,
     handle: ClipDataHandle,
     local_pos: LayoutPoint,
     spatial_node_index: SpatialNodeIndex,
 }
 
 impl ClipNodeInfo {
@@ -431,18 +429,17 @@ impl ClipNode {
                     let data = ClipData::rounded_rect(size, radius, mode);
                     data.write(&mut request);
                 }
             }
         }
     }
 }
 
-/// The main clipping public interface that other modules access.
-#[derive(MallocSizeOf)]
+// The main clipping public interface that other modules access.
 pub struct ClipStore {
     pub clip_chain_nodes: Vec<ClipChainNode>,
     clip_node_instances: Vec<ClipNodeInstance>,
     clip_node_info: Vec<ClipNodeInfo>,
     clip_node_collectors: Vec<ClipNodeCollector>,
 }
 
 // A clip chain instance is what gets built for a given clip
@@ -706,16 +703,27 @@ impl ClipStore {
             pic_clip_rect,
             needs_mask,
         })
     }
 
     pub fn clear_old_instances(&mut self) {
         self.clip_node_instances.clear();
     }
+
+    /// Reports the heap usage of this clip store.
+    pub fn malloc_size_of(&self, op: VoidPtrToSizeFn) -> usize {
+        let mut size = 0;
+        unsafe {
+            size += op(self.clip_chain_nodes.as_ptr() as *const c_void);
+            size += op(self.clip_node_instances.as_ptr() as *const c_void);
+            size += op(self.clip_node_info.as_ptr() as *const c_void);
+        }
+        size
+    }
 }
 
 pub struct ComplexTranslateIter<I> {
     source: I,
     offset: LayoutVector2D,
 }
 
 impl<I: Iterator<Item = ComplexClipRegion>> Iterator for ComplexTranslateIter<I> {
@@ -777,17 +785,17 @@ impl ClipRegion<Option<ComplexClipRegion
 
 // The ClipItemKey is a hashable representation of the contents
 // of a clip item. It is used during interning to de-duplicate
 // clip nodes between frames and display lists. This allows quick
 // comparison of clip node equality by handle, and also allows
 // the uploaded GPU cache handle to be retained between display lists.
 // TODO(gw): Maybe we should consider constructing these directly
 //           in the DL builder?
-#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)]
+#[derive(Debug, Clone, Eq, PartialEq, Hash)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub enum ClipItemKey {
     Rectangle(SizeKey, ClipMode),
     RoundedRectangle(SizeKey, BorderRadiusAu, ClipMode),
     ImageMask(SizeKey, ImageKey, bool),
     BoxShadow(PointKey, SizeKey, BorderRadiusAu, RectangleKey, Au, BoxShadowClipMode),
 }
@@ -840,17 +848,17 @@ impl ClipItemKey {
             Au::from_f32_px(blur_radius),
             clip_mode,
         )
     }
 }
 
 impl intern::InternDebug for ClipItemKey {}
 
-#[derive(Debug, MallocSizeOf)]
+#[derive(Debug)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub enum ClipItem {
     Rectangle(LayoutSize, ClipMode),
     RoundedRectangle(LayoutSize, BorderRadius, ClipMode),
     Image {
         image: ImageKey,
         size: LayoutSize,
@@ -1274,17 +1282,17 @@ pub fn project_inner_rect(
     Some(WorldRect::new(
         WorldPoint::new(xs[1], ys[1]),
         WorldSize::new(xs[2] - xs[1], ys[2] - ys[1]),
     ))
 }
 
 // Collects a list of unique clips to be applied to a rasterization
 // root at the end of primitive preparation.
-#[derive(Debug, MallocSizeOf)]
+#[derive(Debug)]
 pub struct ClipNodeCollector {
     spatial_node_index: SpatialNodeIndex,
     clips: FastHashSet<ClipChainId>,
 }
 
 impl ClipNodeCollector {
     pub fn new(
         spatial_node_index: SpatialNodeIndex,
--- a/gfx/wr/webrender/src/clip_scroll_tree.rs
+++ b/gfx/wr/webrender/src/clip_scroll_tree.rs
@@ -36,17 +36,17 @@ impl CoordinateSystem {
     fn root() -> Self {
         CoordinateSystem {
             transform: LayoutTransform::identity(),
             parent: None,
         }
     }
 }
 
-#[derive(Debug, Copy, Clone, Eq, Hash, MallocSizeOf, PartialEq, PartialOrd, Ord)]
+#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct SpatialNodeIndex(pub u32);
 
 //Note: these have to match ROOT_REFERENCE_FRAME_SPATIAL_ID and ROOT_SCROLL_NODE_SPATIAL_ID
 pub const ROOT_SPATIAL_NODE_INDEX: SpatialNodeIndex = SpatialNodeIndex(0);
 const TOPMOST_SCROLL_NODE_INDEX: SpatialNodeIndex = SpatialNodeIndex(1);
 
--- a/gfx/wr/webrender/src/freelist.rs
+++ b/gfx/wr/webrender/src/freelist.rs
@@ -18,17 +18,17 @@
 //! reused.
 //!
 //! TODO(gw): Add an occupied list head, for fast iteration of the occupied list
 //! to implement retain() style functionality.
 
 use std::{fmt, u32};
 use std::marker::PhantomData;
 
-#[derive(Debug, Copy, Clone, MallocSizeOf, PartialEq)]
+#[derive(Debug, Copy, Clone, PartialEq)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 struct Epoch(u32);
 
 impl Epoch {
     /// Mints a new epoch.
     ///
     /// We start at 1 so that 0 is always an invalid epoch.
@@ -91,17 +91,16 @@ impl<M> Clone for WeakFreeListHandle<M> 
 impl<M> PartialEq for WeakFreeListHandle<M> {
     fn eq(&self, other: &Self) -> bool {
         self.index == other.index && self.epoch == other.epoch
     }
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(MallocSizeOf)]
 pub struct WeakFreeListHandle<M> {
     index: u32,
     epoch: Epoch,
     _marker: PhantomData<M>,
 }
 
 /// More-compact textual representation for debug logging.
 impl<M> fmt::Debug for WeakFreeListHandle<M> {
--- a/gfx/wr/webrender/src/glyph_rasterizer/mod.rs
+++ b/gfx/wr/webrender/src/glyph_rasterizer/mod.rs
@@ -23,17 +23,17 @@ mod pathfinder;
 #[cfg(feature = "pathfinder")]
 use self::pathfinder::create_pathfinder_font_context;
 #[cfg(feature = "pathfinder")]
 pub use self::pathfinder::{ThreadSafePathfinderFontContext, NativeFontHandleWrapper};
 
 #[cfg(not(feature = "pathfinder"))]
 mod no_pathfinder;
 
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd)]
+#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct FontTransform {
     pub scale_x: f32,
     pub skew_x: f32,
     pub skew_y: f32,
     pub scale_y: f32,
 }
@@ -159,17 +159,17 @@ impl<'a> From<&'a LayoutToWorldTransform
         FontTransform::new(xform.m11, xform.m21, xform.m12, xform.m22)
     }
 }
 
 // Some platforms (i.e. Windows) may have trouble rasterizing glyphs above this size.
 // Ensure glyph sizes are reasonably limited to avoid that scenario.
 pub const FONT_SIZE_LIMIT: f64 = 512.0;
 
-#[derive(Clone, Hash, PartialEq, Eq, Debug, Ord, PartialOrd, MallocSizeOf)]
+#[derive(Clone, Hash, PartialEq, Eq, Debug, Ord, PartialOrd)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct FontInstance {
     pub font_key: FontKey,
     // The font size is in *device* pixels, not logical pixels.
     // It is stored as an Au since we need sub-pixel sizes, but
     // can't store as a f32 due to use of this type as a hash key.
     // TODO(gw): Perhaps consider having LogicalAu and DeviceAu
--- a/gfx/wr/webrender/src/gpu_cache.rs
+++ b/gfx/wr/webrender/src/gpu_cache.rs
@@ -20,24 +20,26 @@
 //! will be invoked to build the data.
 //!
 //! After ```end_frame``` has occurred, callers can
 //! use the ```get_address``` API to get the allocated
 //! address in the GPU cache of a given resource slot
 //! for this frame.
 
 use api::{DebugFlags, DocumentId, PremultipliedColorF, IdNamespace, TexelRect};
+use api::{VoidPtrToSizeFn};
 use euclid::TypedRect;
 use internal_types::{FastHashMap};
 use profiler::GpuCacheProfileCounters;
 use render_backend::{FrameStamp, FrameId};
 use renderer::MAX_VERTEX_TEXTURE_WIDTH;
 use std::{mem, u16, u32};
 use std::num::NonZeroU32;
 use std::ops::Add;
+use std::os::raw::c_void;
 use std::time::{Duration, Instant};
 
 
 /// At the time of this writing, Firefox uses about 15 GPU cache rows on
 /// startup, and then gradually works its way up to the mid-30s with normal
 /// browsing.
 pub const GPU_CACHE_INITIAL_HEIGHT: i32 = 20;
 const NEW_ROWS_PER_RESIZE: i32 = 10;
@@ -48,37 +50,37 @@ const FRAMES_BEFORE_EVICTION: usize = 10
 /// The ratio of utilized blocks to total blocks for which we start the clock
 /// on reclaiming memory.
 const RECLAIM_THRESHOLD: f32 = 0.2;
 
 /// The amount of time utilization must be below the above threshold before we
 /// blow away the cache and rebuild it.
 const RECLAIM_DELAY_S: u64 = 5;
 
-#[derive(Debug, Copy, Clone, Eq, MallocSizeOf, PartialEq)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 struct Epoch(u32);
 
 impl Epoch {
     fn next(&mut self) {
         *self = Epoch(self.0.wrapping_add(1));
     }
 }
 
-#[derive(Debug, Copy, Clone, MallocSizeOf)]
+#[derive(Debug, Copy, Clone)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 struct CacheLocation {
     block_index: BlockIndex,
     epoch: Epoch,
 }
 
 /// A single texel in RGBAF32 texture - 16 bytes.
-#[derive(Copy, Clone, Debug, MallocSizeOf)]
+#[derive(Copy, Clone, Debug)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct GpuBlockData {
     data: [f32; 4],
 }
 
 impl GpuBlockData {
     pub const EMPTY: Self = GpuBlockData { data: [0.0; 4] };
@@ -124,33 +126,33 @@ impl From<TexelRect> for GpuBlockData {
 // Any data type that can be stored in the GPU cache should
 // implement this trait.
 pub trait ToGpuBlocks {
     // Request an arbitrary number of GPU data blocks.
     fn write_gpu_blocks(&self, GpuDataRequest);
 }
 
 // A handle to a GPU resource.
-#[derive(Debug, Copy, Clone, MallocSizeOf)]
+#[derive(Debug, Copy, Clone)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct GpuCacheHandle {
     location: Option<CacheLocation>,
 }
 
 impl GpuCacheHandle {
     pub fn new() -> Self {
         GpuCacheHandle { location: None }
     }
 }
 
 // A unique address in the GPU cache. These are uploaded
 // as part of the primitive instances, to allow the vertex
 // shader to fetch the specific data.
-#[derive(Copy, Debug, Clone, MallocSizeOf, Eq, PartialEq)]
+#[derive(Copy, Debug, Clone, Eq, PartialEq)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct GpuCacheAddress {
     pub u: u16,
     pub v: u16,
 }
 
 impl GpuCacheAddress {
@@ -176,17 +178,17 @@ impl Add<usize> for GpuCacheAddress {
         GpuCacheAddress {
             u: self.u + other as u16,
             v: self.v,
         }
     }
 }
 
 // An entry in a free-list of blocks in the GPU cache.
-#[derive(Debug, MallocSizeOf)]
+#[derive(Debug)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 struct Block {
     // The location in the cache of this block.
     address: GpuCacheAddress,
     // The current epoch (generation) of this block.
     epoch: Epoch,
     // Index of the next free block in the list it
@@ -228,17 +230,17 @@ impl Block {
     };
 }
 
 /// Represents the index of a Block in the block array. We only create such
 /// structs for blocks that represent the start of a chunk.
 ///
 /// Because we use Option<BlockIndex> in a lot of places, we use a NonZeroU32
 /// here and avoid ever using the index zero.
-#[derive(Debug, Copy, Clone, MallocSizeOf)]
+#[derive(Debug, Copy, Clone)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 struct BlockIndex(NonZeroU32);
 
 impl BlockIndex {
     fn new(idx: usize) -> Self {
         debug_assert!(idx <= u32::MAX as usize);
         BlockIndex(NonZeroU32::new(idx as u32).expect("Index zero forbidden"))
@@ -247,17 +249,16 @@ impl BlockIndex {
     fn get(&self) -> usize {
         self.0.get() as usize
     }
 }
 
 // A row in the cache texture.
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(MallocSizeOf)]
 struct Row {
     // The fixed size of blocks that this row supports.
     // Each row becomes a slab allocator for a fixed block size.
     // This means no dealing with fragmentation within a cache
     // row as items are allocated and freed.
     block_count_per_item: usize,
 }
 
@@ -270,45 +271,42 @@ impl Row {
 }
 
 // A list of update operations that can be applied on the cache
 // this frame. The list of updates is created by the render backend
 // during frame construction. It's passed to the render thread
 // where GL commands can be applied.
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(MallocSizeOf)]
 pub enum GpuCacheUpdate {
     Copy {
         block_index: usize,
         block_count: usize,
         address: GpuCacheAddress,
     },
 }
 
 /// Command to inform the debug display in the renderer when chunks are allocated
 /// or freed.
-#[derive(MallocSizeOf)]
 pub enum GpuCacheDebugCmd {
     /// Describes an allocated chunk.
     Alloc(GpuCacheDebugChunk),
     /// Describes a freed chunk.
     Free(GpuCacheAddress),
 }
 
-#[derive(Clone, MallocSizeOf)]
+#[derive(Clone)]
 pub struct GpuCacheDebugChunk {
     pub address: GpuCacheAddress,
     pub size: usize,
 }
 
 #[must_use]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(MallocSizeOf)]
 pub struct GpuCacheUpdateList {
     /// The frame current update list was generated from.
     pub frame_id: FrameId,
     /// Whether the texture should be cleared before updates
     /// are applied.
     pub clear: bool,
     /// The current height of the texture. The render thread
     /// should resize the texture if required.
@@ -322,17 +320,16 @@ pub struct GpuCacheUpdateList {
     #[cfg_attr(feature = "serde", serde(skip))]
     pub debug_commands: Vec<GpuCacheDebugCmd>,
 }
 
 // Holds the free lists of fixed size blocks. Mostly
 // just serves to work around the borrow checker.
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(MallocSizeOf)]
 struct FreeBlockLists {
     free_list_1: Option<BlockIndex>,
     free_list_2: Option<BlockIndex>,
     free_list_4: Option<BlockIndex>,
     free_list_8: Option<BlockIndex>,
     free_list_16: Option<BlockIndex>,
     free_list_32: Option<BlockIndex>,
     free_list_64: Option<BlockIndex>,
@@ -390,17 +387,16 @@ impl FreeBlockLists {
             _ => panic!("Can't allocate > MAX_VERTEX_TEXTURE_WIDTH per resource!"),
         }
     }
 }
 
 // CPU-side representation of the GPU resource cache texture.
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(MallocSizeOf)]
 struct Texture {
     // Current texture height
     height: i32,
     // All blocks that have been created for this texture
     blocks: Vec<Block>,
     // Metadata about each allocated row.
     rows: Vec<Row>,
     // The base Epoch for this texture.
@@ -455,16 +451,28 @@ impl Texture {
             occupied_list_heads: FastHashMap::default(),
             allocated_block_count: 0,
             reached_reclaim_threshold: None,
             debug_commands: Vec::new(),
             debug_flags,
         }
     }
 
+    // Reports the CPU heap usage of this Texture struct.
+    fn malloc_size_of(&self, op: VoidPtrToSizeFn) -> usize {
+        let mut size = 0;
+        unsafe {
+            size += op(self.blocks.as_ptr() as *const c_void);
+            size += op(self.rows.as_ptr() as *const c_void);
+            size += op(self.pending_blocks.as_ptr() as *const c_void);
+            size += op(self.updates.as_ptr() as *const c_void);
+        }
+        size
+    }
+
     // Push new data into the cache. The ```pending_block_index``` field represents
     // where the data was pushed into the texture ```pending_blocks``` array.
     // Return the allocated address for this data.
     fn push_data(
         &mut self,
         pending_block_index: Option<usize>,
         block_count: usize,
         frame_stamp: FrameStamp
@@ -659,17 +667,16 @@ impl<'a> Drop for GpuDataRequest<'a> {
         self.handle.location = Some(location);
     }
 }
 
 
 /// The main LRU cache interface.
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(MallocSizeOf)]
 pub struct GpuCache {
     /// Current FrameId.
     now: FrameStamp,
     /// CPU-side texture allocator.
     texture: Texture,
     /// Number of blocks requested this frame that don't
     /// need to be re-uploaded.
     saved_block_count: usize,
@@ -853,16 +860,21 @@ impl GpuCache {
     /// freed or pending slot will panic!
     pub fn get_address(&self, id: &GpuCacheHandle) -> GpuCacheAddress {
         let location = id.location.expect("handle not requested or allocated!");
         let block = &self.texture.blocks[location.block_index.get()];
         debug_assert_eq!(block.epoch, location.epoch);
         debug_assert_eq!(block.last_access_time, self.now.frame_id());
         block.address
     }
+
+    /// Reports the CPU heap usage of this GpuCache struct.
+    pub fn malloc_size_of(&self, op: VoidPtrToSizeFn) -> usize {
+        self.texture.malloc_size_of(op)
+    }
 }
 
 #[test]
 #[cfg(target_pointer_width = "64")]
 fn test_struct_sizes() {
     use std::mem;
     // We can end up with a lot of blocks stored in the global vec, and keeping
     // them small helps reduce memory overhead.
--- a/gfx/wr/webrender/src/gpu_types.rs
+++ b/gfx/wr/webrender/src/gpu_types.rs
@@ -54,17 +54,17 @@ impl ZBufferIdGenerator {
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 #[repr(C)]
 pub enum RasterizationSpace {
     Local = 0,
     Screen = 1,
 }
 
-#[derive(Debug, Copy, Clone, MallocSizeOf)]
+#[derive(Debug, Copy, Clone)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 #[repr(C)]
 pub enum BoxShadowStretchMode {
     Stretch = 0,
     Simple = 1,
 }
 
@@ -91,17 +91,17 @@ pub struct BlurInstance {
 #[repr(C)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct ScalingInstance {
     pub task_address: RenderTaskAddress,
     pub src_task_address: RenderTaskAddress,
 }
 
-#[derive(Copy, Clone, Debug, Hash, MallocSizeOf, PartialEq, Eq)]
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
 #[repr(C)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub enum BorderSegment {
     TopLeft,
     TopRight,
     BottomRight,
     BottomLeft,
@@ -312,17 +312,16 @@ impl From<SplitCompositeInstance> for Pr
     }
 }
 
 bitflags! {
     /// Flags that define how the common brush shader
     /// code should process this instance.
     #[cfg_attr(feature = "capture", derive(Serialize))]
     #[cfg_attr(feature = "replay", derive(Deserialize))]
-    #[derive(MallocSizeOf)]
     pub struct BrushFlags: u8 {
         /// Apply perspective interpolation to UVs
         const PERSPECTIVE_INTERPOLATION = 0x1;
         /// Do interpolation relative to segment rect,
         /// rather than primitive rect.
         const SEGMENT_RELATIVE = 0x2;
         /// Repeat UVs horizontally.
         const SEGMENT_REPEAT_X = 0x4;
--- a/gfx/wr/webrender/src/hit_test.rs
+++ b/gfx/wr/webrender/src/hit_test.rs
@@ -1,38 +1,37 @@
 /* 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 api::{BorderRadius, ClipMode, HitTestFlags, HitTestItem, HitTestResult, ItemTag, LayoutPoint};
-use api::{LayoutPrimitiveInfo, LayoutRect, PipelineId, WorldPoint};
+use api::{LayoutPrimitiveInfo, LayoutRect, PipelineId, VoidPtrToSizeFn, WorldPoint};
 use clip::{ClipDataStore, ClipNode, ClipItem, ClipStore};
 use clip::{rounded_rectangle_contains_point};
 use clip_scroll_tree::{SpatialNodeIndex, ClipScrollTree};
 use internal_types::FastHashMap;
 use prim_store::ScrollNodeAndClipChain;
+use std::os::raw::c_void;
 use std::u32;
 use util::LayoutToWorldFastTransform;
 
 /// A copy of important clip scroll node data to use during hit testing. This a copy of
 /// data from the ClipScrollTree that will persist as a new frame is under construction,
 /// allowing hit tests consistent with the currently rendered frame.
-#[derive(MallocSizeOf)]
 pub struct HitTestSpatialNode {
     /// The pipeline id of this node.
     pipeline_id: PipelineId,
 
     /// World transform for content transformed by this node.
     world_content_transform: LayoutToWorldFastTransform,
 
     /// World viewport transform for content transformed by this node.
     world_viewport_transform: LayoutToWorldFastTransform,
 }
 
-#[derive(MallocSizeOf)]
 pub struct HitTestClipNode {
     /// A particular point must be inside all of these regions to be considered clipped in
     /// for the purposes of a hit test.
     region: HitTestRegion,
 }
 
 impl HitTestClipNode {
     fn new(local_pos: LayoutPoint, node: &ClipNode) -> Self {
@@ -60,31 +59,30 @@ impl HitTestClipNode {
 
 // A hit testing clip chain node is the same as a
 // normal clip chain node, except that the clip
 // node is embedded inside the clip chain, rather
 // than referenced. This means we don't need to
 // copy the complete interned clip data store for
 // hit testing.
 
-#[derive(Debug, Copy, Clone, MallocSizeOf, PartialEq, Eq, Hash)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub struct HitTestClipChainId(u32);
 
 impl HitTestClipChainId {
     pub const NONE: Self = HitTestClipChainId(u32::MAX);
 }
 
-#[derive(MallocSizeOf)]
 pub struct HitTestClipChainNode {
     pub region: HitTestClipNode,
     pub spatial_node_index: SpatialNodeIndex,
     pub parent_clip_chain_id: HitTestClipChainId,
 }
 
-#[derive(Clone, MallocSizeOf)]
+#[derive(Clone)]
 pub struct HitTestingItem {
     rect: LayoutRect,
     clip_rect: LayoutRect,
     tag: ItemTag,
     is_backface_visible: bool,
 }
 
 impl HitTestingItem {
@@ -93,20 +91,19 @@ impl HitTestingItem {
             rect: info.rect,
             clip_rect: info.clip_rect,
             tag,
             is_backface_visible: info.is_backface_visible,
         }
     }
 }
 
-#[derive(Clone, MallocSizeOf)]
+#[derive(Clone)]
 pub struct HitTestingRun(pub Vec<HitTestingItem>, pub ScrollNodeAndClipChain);
 
-#[derive(MallocSizeOf)]
 enum HitTestRegion {
     Invalid,
     Rectangle(LayoutRect, ClipMode),
     RoundedRectangle(LayoutRect, BorderRadius, ClipMode),
 }
 
 impl HitTestRegion {
     pub fn contains(&self, point: &LayoutPoint) -> bool {
@@ -119,17 +116,16 @@ impl HitTestRegion {
                 rounded_rectangle_contains_point(point, &rect, &radii),
             HitTestRegion::RoundedRectangle(rect, radii, ClipMode::ClipOut) =>
                 !rounded_rectangle_contains_point(point, &rect, &radii),
             HitTestRegion::Invalid => true,
         }
     }
 }
 
-#[derive(MallocSizeOf)]
 pub struct HitTester {
     runs: Vec<HitTestingRun>,
     spatial_nodes: Vec<HitTestSpatialNode>,
     clip_chains: Vec<HitTestClipChainNode>,
     pipeline_root_nodes: FastHashMap<PipelineId, SpatialNodeIndex>,
 }
 
 impl HitTester {
@@ -370,25 +366,38 @@ impl HitTester {
 
         result.items.dedup();
         result
     }
 
     pub fn get_pipeline_root(&self, pipeline_id: PipelineId) -> &HitTestSpatialNode {
         &self.spatial_nodes[self.pipeline_root_nodes[&pipeline_id].0 as usize]
     }
+
+    // Reports the CPU heap usage of this HitTester struct.
+    pub fn malloc_size_of(&self, op: VoidPtrToSizeFn) -> usize {
+        let mut size = 0;
+        unsafe {
+            size += op(self.runs.as_ptr() as *const c_void);
+            size += op(self.spatial_nodes.as_ptr() as *const c_void);
+            size += op(self.clip_chains.as_ptr() as *const c_void);
+            // We can't measure pipeline_root_nodes because we don't have the
+            // real machinery from the malloc_size_of crate. We could estimate
+            // it but it should generally be very small so we don't bother.
+        }
+        size
+    }
 }
 
-#[derive(Clone, Copy, MallocSizeOf, PartialEq)]
+#[derive(Clone, Copy, PartialEq)]
 enum ClippedIn {
     ClippedIn,
     NotClippedIn,
 }
 
-#[derive(MallocSizeOf)]
 pub struct HitTest {
     pipeline_id: Option<PipelineId>,
     point: WorldPoint,
     flags: HitTestFlags,
     node_cache: FastHashMap<HitTestClipChainId, ClippedIn>,
     clip_chain_cache: Vec<Option<ClippedIn>>,
 }
 
--- a/gfx/wr/webrender/src/intern.rs
+++ b/gfx/wr/webrender/src/intern.rs
@@ -1,20 +1,21 @@
 /* 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 api::{LayoutPrimitiveInfo, LayoutRect};
+use api::VoidPtrToSizeFn;
 use internal_types::FastHashMap;
-use malloc_size_of::MallocSizeOf;
 use profiler::ResourceProfileCounter;
 use std::fmt::Debug;
 use std::hash::Hash;
 use std::marker::PhantomData;
 use std::{mem, ops, u64};
+use std::os::raw::c_void;
 use std::sync::atomic::{AtomicUsize, Ordering};
 use util::VecHelper;
 
 /*
 
  The interning module provides a generic data structure
  interning container. It is similar in concept to a
  traditional string interning container, but it is
@@ -45,17 +46,17 @@ use util::VecHelper;
 
 /// The epoch is incremented each time a scene is
 /// built. The most recently used scene epoch is
 /// stored inside each item and handle. This is
 /// then used for cache invalidation (item) and
 /// correctness validation (handle).
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Debug, Copy, Clone, MallocSizeOf, PartialEq)]
+#[derive(Debug, Copy, Clone, PartialEq)]
 struct Epoch(u64);
 
 impl Epoch {
     pub const INVALID: Self = Epoch(u64::MAX);
 }
 
 /// A list of updates to be applied to the data store,
 /// provided by the interning structure.
@@ -70,106 +71,94 @@ pub struct UpdateList<S> {
 
 lazy_static! {
     static ref NEXT_UID: AtomicUsize = AtomicUsize::new(0);
 }
 
 /// A globally, unique identifier
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Debug, Copy, Clone, Eq, Hash, MallocSizeOf, PartialEq)]
+#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)]
 pub struct ItemUid {
     uid: usize,
 }
 
 impl ItemUid {
     pub fn next_uid() -> ItemUid {
         let uid = NEXT_UID.fetch_add(1, Ordering::Relaxed);
         ItemUid { uid }
     }
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Debug, Copy, Clone, MallocSizeOf)]
+#[derive(Debug, Copy, Clone)]
 pub struct Handle<M: Copy> {
     index: u32,
     epoch: Epoch,
     uid: ItemUid,
     _marker: PhantomData<M>,
 }
 
 impl <M> Handle<M> where M: Copy {
     pub fn uid(&self) -> ItemUid {
         self.uid
     }
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(MallocSizeOf)]
 pub enum UpdateKind {
     Insert,
     Remove,
     UpdateEpoch,
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(MallocSizeOf)]
 pub struct Update {
     index: usize,
     kind: UpdateKind,
 }
 
 /// The data item is stored with an epoch, for validating
 /// correct access patterns.
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(MallocSizeOf)]
-struct Item<T: MallocSizeOf> {
+struct Item<T> {
     epoch: Epoch,
     data: T,
 }
 
 pub trait InternDebug {
     fn on_interned(&self, _uid: ItemUid) {}
 }
 
 /// The data store lives in the frame builder thread. It
 /// contains a free-list of items for fast access.
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(MallocSizeOf)]
-pub struct DataStore<S, T: MallocSizeOf, M> {
+pub struct DataStore<S, T, M> {
     items: Vec<Item<T>>,
     _source: PhantomData<S>,
     _marker: PhantomData<M>,
 }
 
-impl<S, T, M> ::std::default::Default for DataStore<S, T, M>
-where
-    S: Debug + MallocSizeOf,
-    T: From<S> + MallocSizeOf,
-    M: Debug
+impl<S, T, M> ::std::default::Default for DataStore<S, T, M> where S: Debug, T: From<S>, M: Debug
 {
     fn default() -> Self {
         DataStore {
             items: Vec::new(),
             _source: PhantomData,
             _marker: PhantomData,
         }
     }
 }
 
-impl<S, T, M> DataStore<S, T, M>
-where
-    S: Debug + MallocSizeOf,
-    T: From<S> + MallocSizeOf,
-    M: Debug
+impl<S, T, M> DataStore<S, T, M> where S: Debug, T: From<S>, M: Debug
 {
     /// Apply any updates from the scene builder thread to
     /// this data store.
     pub fn apply_updates(
         &mut self,
         update_list: UpdateList<S>,
         profile_counter: &mut ResourceProfileCounter,
     ) {
@@ -191,61 +180,59 @@ where
             }
         }
 
         let per_item_size = mem::size_of::<S>() + mem::size_of::<T>();
         profile_counter.set(self.items.len(), per_item_size * self.items.len());
 
         debug_assert!(data_iter.next().is_none());
     }
+
+    /// Reports CPU heap usage.
+    pub fn malloc_size_of(&self, op: VoidPtrToSizeFn) -> usize {
+        unsafe { op(self.items.as_ptr() as *const c_void) }
+    }
 }
 
 /// Retrieve an item from the store via handle
 impl<S, T, M> ops::Index<Handle<M>> for DataStore<S, T, M>
-where
-    S: MallocSizeOf,
-    T: MallocSizeOf,
-    M: Copy
+where M: Copy
 {
     type Output = T;
     fn index(&self, handle: Handle<M>) -> &T {
         let item = &self.items[handle.index as usize];
         assert_eq!(item.epoch, handle.epoch);
         &item.data
     }
 }
 
 /// Retrieve a mutable item from the store via handle
 /// Retrieve an item from the store via handle
 impl<S, T, M> ops::IndexMut<Handle<M>> for DataStore<S, T, M>
 where
-    S: MallocSizeOf,
-    T: MallocSizeOf,
     M: Copy
 {
     fn index_mut(&mut self, handle: Handle<M>) -> &mut T {
         let item = &mut self.items[handle.index as usize];
         assert_eq!(item.epoch, handle.epoch);
         &mut item.data
     }
 }
 
 /// The main interning data structure. This lives in the
 /// scene builder thread, and handles hashing and interning
 /// unique data structures. It also manages a free-list for
 /// the items in the data store, which is synchronized via
 /// an update list of additions / removals.
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(MallocSizeOf)]
 pub struct Interner<S, D, M>
 where
-    S: Eq + Hash + Clone + Debug + MallocSizeOf,
-    D: MallocSizeOf,
-    M: Copy + MallocSizeOf,
+    S: Eq + Hash + Clone + Debug,
+    M: Copy
 {
     /// Uniquely map an interning key to a handle
     map: FastHashMap<S, Handle<M>>,
     /// List of free slots in the data store for re-use.
     free_list: Vec<usize>,
     /// Pending list of updates that need to be applied.
     updates: Vec<Update>,
     /// Pending new data to insert.
@@ -254,37 +241,35 @@ where
     current_epoch: Epoch,
     /// The information associated with each interned
     /// item that can be accessed by the interner.
     local_data: Vec<Item<D>>,
 }
 
 impl<S, D, M> ::std::default::Default for Interner<S, D, M>
 where
-    S: Eq + Hash + Clone + Debug + MallocSizeOf,
-    D: MallocSizeOf,
-    M: Copy + Debug + MallocSizeOf,
+    S: Eq + Hash + Clone + Debug,
+    M: Copy + Debug
 {
     fn default() -> Self {
         Interner {
             map: FastHashMap::default(),
             free_list: Vec::new(),
             updates: Vec::new(),
             update_data: Vec::new(),
             current_epoch: Epoch(1),
             local_data: Vec::new(),
         }
     }
 }
 
 impl<S, D, M> Interner<S, D, M>
 where
-    S: Eq + Hash + Clone + Debug + InternDebug + MallocSizeOf,
-    D: MallocSizeOf,
-    M: Copy + Debug + MallocSizeOf
+    S: Eq + Hash + Clone + Debug + InternDebug,
+    M: Copy + Debug
 {
     /// Intern a data structure, and return a handle to
     /// that data. The handle can then be stored in the
     /// frame builder, and safely accessed via the data
     /// store that lives in the frame builder thread.
     /// The provided closure is invoked to build the
     /// local data about an interned structure if the
     /// key isn't already interned.
@@ -392,41 +377,51 @@ where
             epoch: self.current_epoch,
         };
 
         // Begin the next epoch
         self.current_epoch = Epoch(self.current_epoch.0 + 1);
 
         updates
     }
+
+    /// Reports CPU heap usage.
+    pub fn malloc_size_of(&self, op: VoidPtrToSizeFn, eop: VoidPtrToSizeFn) -> usize {
+        let mut bytes = 0;
+        unsafe {
+            bytes += op(self.local_data.as_ptr() as *const c_void);
+            bytes += self.map.values().next()
+                .map_or(0, |v| eop(v as *const _ as *const c_void));
+        }
+        bytes
+    }
 }
 
 /// Retrieve the local data for an item from the interner via handle
 impl<S, D, M> ops::Index<Handle<M>> for Interner<S, D, M>
 where
-    S: Eq + Clone + Hash + Debug + MallocSizeOf,
-    D: MallocSizeOf,
-    M: Copy + Debug + MallocSizeOf
+    S: Eq + Clone + Hash + Debug,
+    M: Copy + Debug
 {
     type Output = D;
     fn index(&self, handle: Handle<M>) -> &D {
         let item = &self.local_data[handle.index as usize];
         assert_eq!(item.epoch, handle.epoch);
         &item.data
     }
 }
 
 /// Implement `Internable` for a type that wants participate in interning.
 ///
 /// see DisplayListFlattener::add_interned_primitive<P>
 pub trait Internable {
-    type Marker: Copy + Debug + MallocSizeOf;
-    type Source: Eq + Hash + Clone + Debug + MallocSizeOf;
-    type StoreData: From<Self::Source> + MallocSizeOf;
-    type InternData: MallocSizeOf;
+    type Marker: Copy + Debug;
+    type Source: Eq + Hash + Clone + Debug;
+    type StoreData: From<Self::Source>;
+    type InternData;
 
     /// Build a new key from self with `info`.
     fn build_key(
         self,
         info: &LayoutPrimitiveInfo,
         prim_relative_clip_rect: LayoutRect,
     ) -> Self::Source;
 }
--- a/gfx/wr/webrender/src/lib.rs
+++ b/gfx/wr/webrender/src/lib.rs
@@ -53,27 +53,22 @@ macro_rules! matches {
 #[macro_use]
 extern crate bitflags;
 #[macro_use]
 extern crate cfg_if;
 #[macro_use]
 extern crate lazy_static;
 #[macro_use]
 extern crate log;
-#[macro_use]
-extern crate malloc_size_of_derive;
 #[cfg(any(feature = "serde"))]
 #[macro_use]
 extern crate serde;
 #[macro_use]
 extern crate thread_profiler;
 
-extern crate wr_malloc_size_of;
-use wr_malloc_size_of as malloc_size_of;
-
 mod batch;
 mod border;
 mod box_shadow;
 #[cfg(any(feature = "capture", feature = "replay"))]
 mod capture;
 mod clip;
 mod clip_scroll_tree;
 mod debug_colors;
@@ -193,17 +188,16 @@ extern crate ws;
 extern crate image as image_loader;
 #[cfg(feature = "debugger")]
 extern crate base64;
 #[cfg(all(feature = "capture", feature = "png"))]
 extern crate png;
 #[cfg(test)]
 extern crate rand;
 
-#[macro_use]
 pub extern crate webrender_api;
 extern crate webrender_build;
 
 #[doc(hidden)]
 pub use device::{build_shader_strings, ReadPixelsFormat, UploadMethod, VertexUsageHint};
 pub use device::{ProgramBinary, ProgramCache, ProgramCacheObserver};
 pub use device::Device;
 pub use frame_builder::ChasePrimitive;
--- a/gfx/wr/webrender/src/prim_store/borders.rs
+++ b/gfx/wr/webrender/src/prim_store/borders.rs
@@ -19,17 +19,17 @@ use prim_store::{
     PrimitiveInstanceKind, PrimitiveOpacity, PrimitiveSceneData,
     PrimitiveStore
 };
 use resource_cache::ImageRequest;
 use storage;
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)]
+#[derive(Debug, Clone, Eq, PartialEq, Hash)]
 pub struct NormalBorderPrim {
     pub border: NormalBorderAu,
     pub widths: LayoutSideOffsetsAu,
 }
 
 pub type NormalBorderKey = PrimKey<NormalBorderPrim>;
 
 impl NormalBorderKey {
@@ -62,17 +62,16 @@ impl AsInstanceKind<NormalBorderDataHand
             data_handle,
             cache_handles: storage::Range::empty(),
         }
     }
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(MallocSizeOf)]
 pub struct NormalBorderData {
     pub brush_segments: Vec<BrushSegment>,
     pub border_segments: Vec<BorderSegmentInfo>,
     pub border: NormalBorder,
     pub widths: LayoutSideOffsets,
 }
 
 impl NormalBorderData {
@@ -157,17 +156,17 @@ impl From<NormalBorderKey> for NormalBor
                 widths,
             }
         }
     }
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
+#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
 pub struct NormalBorderDataMarker;
 
 pub type NormalBorderDataStore = intern::DataStore<NormalBorderKey, NormalBorderTemplate, NormalBorderDataMarker>;
 pub type NormalBorderDataHandle = intern::Handle<NormalBorderDataMarker>;
 pub type NormalBorderDataUpdateList = intern::UpdateList<NormalBorderKey>;
 pub type NormalBorderDataInterner = intern::Interner<NormalBorderKey, PrimitiveSceneData, NormalBorderDataMarker>;
 
 impl intern::Internable for NormalBorderPrim {
@@ -205,19 +204,18 @@ impl IsVisible for NormalBorderPrim {
         true
     }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)]
+#[derive(Debug, Clone, Eq, PartialEq, Hash)]
 pub struct ImageBorder {
-    #[ignore_malloc_size_of = "Arc"]
     pub request: ImageRequest,
     pub nine_patch: NinePatchDescriptor,
 }
 
 pub type ImageBorderKey = PrimKey<ImageBorder>;
 
 impl ImageBorderKey {
     pub fn new(
@@ -248,19 +246,17 @@ impl AsInstanceKind<ImageBorderDataHandl
         PrimitiveInstanceKind::ImageBorder {
             data_handle
         }
     }
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(MallocSizeOf)]
 pub struct ImageBorderData {
-    #[ignore_malloc_size_of = "Arc"]
     pub request: ImageRequest,
     pub brush_segments: Vec<BrushSegment>,
 }
 
 impl ImageBorderData {
     /// Update the GPU cache for a given primitive template. This may be called multiple
     /// times per frame, by each primitive reference that refers to this interned
     /// template. The initial request call to the GPU cache ensures that work is only
@@ -338,17 +334,17 @@ impl From<ImageBorderKey> for ImageBorde
                 brush_segments,
             }
         }
     }
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
+#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
 pub struct ImageBorderDataMarker;
 
 pub type ImageBorderDataStore = intern::DataStore<ImageBorderKey, ImageBorderTemplate, ImageBorderDataMarker>;
 pub type ImageBorderDataHandle = intern::Handle<ImageBorderDataMarker>;
 pub type ImageBorderDataUpdateList = intern::UpdateList<ImageBorderKey>;
 pub type ImageBorderDataInterner = intern::Interner<ImageBorderKey, PrimitiveSceneData, ImageBorderDataMarker>;
 
 impl intern::Internable for ImageBorder {
--- a/gfx/wr/webrender/src/prim_store/gradient.rs
+++ b/gfx/wr/webrender/src/prim_store/gradient.rs
@@ -15,17 +15,17 @@ use prim_store::{PrimitiveInstanceKind, 
 use prim_store::{PrimKeyCommonData, PrimTemplateCommonData, PrimitiveStore};
 use prim_store::{NinePatchDescriptor, PointKey, SizeKey};
 use std::{hash, ops::{Deref, DerefMut}, mem};
 use util::pack_as_float;
 
 /// A hashable gradient stop that can be used in primitive keys.
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Debug, Clone, MallocSizeOf, PartialEq)]
+#[derive(Debug, Clone, PartialEq)]
 pub struct GradientStopKey {
     pub offset: f32,
     pub color: ColorU,
 }
 
 impl Eq for GradientStopKey {}
 
 impl hash::Hash for GradientStopKey {
@@ -33,17 +33,17 @@ impl hash::Hash for GradientStopKey {
         self.offset.to_bits().hash(state);
         self.color.hash(state);
     }
 }
 
 /// Identifying key for a line decoration.
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Debug, Clone, Eq, PartialEq, Hash, MallocSizeOf)]
+#[derive(Debug, Clone, Eq, PartialEq, Hash)]
 pub struct LinearGradientKey {
     pub common: PrimKeyCommonData,
     pub extend_mode: ExtendMode,
     pub start_point: PointKey,
     pub end_point: PointKey,
     pub stretch_size: SizeKey,
     pub tile_spacing: SizeKey,
     pub stops: Vec<GradientStopKey>,
@@ -90,17 +90,16 @@ impl AsInstanceKind<LinearGradientDataHa
             data_handle,
             visible_tiles_range: GradientTileRange::empty(),
         }
     }
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(MallocSizeOf)]
 pub struct LinearGradientTemplate {
     pub common: PrimTemplateCommonData,
     pub extend_mode: ExtendMode,
     pub start_point: LayoutPoint,
     pub end_point: LayoutPoint,
     pub stretch_size: LayoutSize,
     pub tile_spacing: LayoutSize,
     pub stops_opacity: PrimitiveOpacity,
@@ -224,17 +223,17 @@ impl LinearGradientTemplate {
                PrimitiveOpacity::translucent()
             }
         }
     }
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
+#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
 pub struct LinearGradientDataMarker;
 
 pub type LinearGradientDataStore = DataStore<LinearGradientKey, LinearGradientTemplate, LinearGradientDataMarker>;
 pub type LinearGradientDataHandle = Handle<LinearGradientDataMarker>;
 pub type LinearGradientDataUpdateList = UpdateList<LinearGradientKey>;
 pub type LinearGradientDataInterner = Interner<LinearGradientKey, PrimitiveSceneData, LinearGradientDataMarker>;
 
 pub struct LinearGradient {
@@ -275,17 +274,17 @@ impl IsVisible for LinearGradient {
     }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 
 /// Hashable radial gradient parameters, for use during prim interning.
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Debug, Clone, MallocSizeOf, PartialEq)]
+#[derive(Debug, Clone, PartialEq)]
 pub struct RadialGradientParams {
     pub start_radius: f32,
     pub end_radius: f32,
     pub ratio_xy: f32,
 }
 
 impl Eq for RadialGradientParams {}
 
@@ -295,17 +294,17 @@ impl hash::Hash for RadialGradientParams
         self.end_radius.to_bits().hash(state);
         self.ratio_xy.to_bits().hash(state);
     }
 }
 
 /// Identifying key for a line decoration.
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Debug, Clone, Eq, PartialEq, Hash, MallocSizeOf)]
+#[derive(Debug, Clone, Eq, PartialEq, Hash)]
 pub struct RadialGradientKey {
     pub common: PrimKeyCommonData,
     pub extend_mode: ExtendMode,
     pub center: PointKey,
     pub params: RadialGradientParams,
     pub stretch_size: SizeKey,
     pub stops: Vec<GradientStopKey>,
     pub tile_spacing: SizeKey,
@@ -350,17 +349,16 @@ impl AsInstanceKind<RadialGradientDataHa
             data_handle,
             visible_tiles_range: GradientTileRange::empty(),
         }
     }
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(MallocSizeOf)]
 pub struct RadialGradientTemplate {
     pub common: PrimTemplateCommonData,
     pub extend_mode: ExtendMode,
     pub center: LayoutPoint,
     pub params: RadialGradientParams,
     pub stretch_size: LayoutSize,
     pub tile_spacing: LayoutSize,
     pub brush_segments: Vec<BrushSegment>,
@@ -455,17 +453,17 @@ impl RadialGradientTemplate {
         }
 
         self.opacity = PrimitiveOpacity::translucent();
     }
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
+#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
 pub struct RadialGradientDataMarker;
 
 pub type RadialGradientDataStore = DataStore<RadialGradientKey, RadialGradientTemplate, RadialGradientDataMarker>;
 pub type RadialGradientDataHandle = Handle<RadialGradientDataMarker>;
 pub type RadialGradientDataUpdateList = UpdateList<RadialGradientKey>;
 pub type RadialGradientDataInterner = Interner<RadialGradientKey, PrimitiveSceneData, RadialGradientDataMarker>;
 
 pub struct RadialGradient {
--- a/gfx/wr/webrender/src/prim_store/image.rs
+++ b/gfx/wr/webrender/src/prim_store/image.rs
@@ -62,17 +62,17 @@ pub struct ImageCacheKey {
 pub struct ImageInstance {
     pub opacity_binding_index: OpacityBindingIndex,
     pub segment_instance_index: SegmentInstanceIndex,
     pub visible_tiles: Vec<VisibleImageTile>,
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Debug, Clone, Eq, PartialEq, MallocSizeOf, Hash)]
+#[derive(Debug, Clone, Eq, PartialEq, Hash)]
 pub struct Image {
     pub key: ApiImageKey,
     pub stretch_size: SizeKey,
     pub tile_spacing: SizeKey,
     pub color: ColorU,
     pub sub_rect: Option<DeviceIntRect>,
     pub image_rendering: ImageRendering,
     pub alpha_type: AlphaType,
@@ -122,31 +122,30 @@ impl AsInstanceKind<ImageDataHandle> for
             image_instance_index,
         }
     }
 }
 
 // Where to find the texture data for an image primitive.
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Debug, MallocSizeOf)]
+#[derive(Debug)]
 pub enum ImageSource {
     // A normal image - just reference the texture cache.
     Default,
     // An image that is pre-rendered into the texture cache
     // via a render task.
     Cache {
         size: DeviceIntSize,
         handle: Option<RenderTaskCacheEntryHandle>,
     },
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(MallocSizeOf)]
 pub struct ImageData {
     pub key: ApiImageKey,
     pub stretch_size: LayoutSize,
     pub tile_spacing: LayoutSize,
     pub color: ColorF,
     pub source: ImageSource,
     pub image_rendering: ImageRendering,
     pub sub_rect: Option<DeviceIntRect>,
@@ -332,17 +331,17 @@ impl From<ImageKey> for ImageTemplate {
             common,
             kind: image.kind.into(),
         }
     }
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
+#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
 pub struct ImageDataMarker;
 
 pub type ImageDataStore = DataStore<ImageKey, ImageTemplate, ImageDataMarker>;
 pub type ImageDataHandle = Handle<ImageDataMarker>;
 pub type ImageDataUpdateList = UpdateList<ImageKey>;
 pub type ImageDataInterner = Interner<ImageKey, PrimitiveSceneData, ImageDataMarker>;
 
 impl Internable for Image {
@@ -385,17 +384,17 @@ impl IsVisible for Image {
         true
     }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)]
+#[derive(Debug, Clone, Eq, PartialEq, Hash)]
 pub struct YuvImage {
     pub color_depth: ColorDepth,
     pub yuv_key: [ApiImageKey; 3],
     pub format: YuvFormat,
     pub color_space: YuvColorSpace,
     pub image_rendering: ImageRendering,
 }
 
@@ -434,17 +433,16 @@ impl AsInstanceKind<YuvImageDataHandle> 
             data_handle,
             segment_instance_index: SegmentInstanceIndex::INVALID
         }
     }
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(MallocSizeOf)]
 pub struct YuvImageData {
     pub color_depth: ColorDepth,
     pub yuv_key: [ApiImageKey; 3],
     pub format: YuvFormat,
     pub color_space: YuvColorSpace,
     pub image_rendering: ImageRendering,
 }
 
@@ -510,17 +508,17 @@ impl From<YuvImageKey> for YuvImageTempl
             common,
             kind: image.kind.into(),
         }
     }
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
+#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
 pub struct YuvImageDataMarker;
 
 pub type YuvImageDataStore = DataStore<YuvImageKey, YuvImageTemplate, YuvImageDataMarker>;
 pub type YuvImageDataHandle = Handle<YuvImageDataMarker>;
 pub type YuvImageDataUpdateList = UpdateList<YuvImageKey>;
 pub type YuvImageDataInterner = Interner<YuvImageKey, PrimitiveSceneData, YuvImageDataMarker>;
 
 impl Internable for YuvImage {
--- a/gfx/wr/webrender/src/prim_store/line_dec.rs
+++ b/gfx/wr/webrender/src/prim_store/line_dec.rs
@@ -12,28 +12,28 @@ use frame_builder::{FrameBuildingState};
 use gpu_cache::GpuDataRequest;
 use intern;
 use prim_store::{
     PrimKey, PrimKeyCommonData, PrimTemplate, PrimTemplateCommonData,
     PrimitiveSceneData, PrimitiveStore,
 };
 use prim_store::PrimitiveInstanceKind;
 
-#[derive(Clone, Debug, Hash, MallocSizeOf, PartialEq, Eq)]
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct LineDecorationCacheKey {
     pub style: LineStyle,
     pub orientation: LineOrientation,
     pub wavy_line_thickness: Au,
     pub size: LayoutSizeAu,
 }
 
 /// Identifying key for a line decoration.
-#[derive(Clone, Debug, Hash, MallocSizeOf, PartialEq, Eq)]
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct LineDecoration {
     // If the cache_key is Some(..) it is a line decoration
     // that relies on a render task (e.g. wavy). If the
     // cache key is None, it uses a fast path to draw the
     // line decoration as a solid rect.
     pub cache_key: Option<LineDecorationCacheKey>,
@@ -72,17 +72,16 @@ impl AsInstanceKind<LineDecorationDataHa
             data_handle,
             cache_handle: None,
         }
     }
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(MallocSizeOf)]
 pub struct LineDecorationData {
     pub cache_key: Option<LineDecorationCacheKey>,
     pub color: ColorF,
 }
 
 impl LineDecorationData {
     /// Update the GPU cache for a given primitive template. This may be called multiple
     /// times per frame, by each primitive reference that refers to this interned
@@ -132,17 +131,17 @@ impl From<LineDecorationKey> for LineDec
                 color: line_dec.kind.color.into(),
             }
         }
     }
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
+#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
 pub struct LineDecorationDataMarker;
 
 pub type LineDecorationDataStore = intern::DataStore<LineDecorationKey, LineDecorationTemplate, LineDecorationDataMarker>;
 pub type LineDecorationDataHandle = intern::Handle<LineDecorationDataMarker>;
 pub type LineDecorationDataUpdateList = intern::UpdateList<LineDecorationKey>;
 pub type LineDecorationDataInterner = intern::Interner<LineDecorationKey, PrimitiveSceneData, LineDecorationDataMarker>;
 
 impl intern::Internable for LineDecoration {
--- a/gfx/wr/webrender/src/prim_store/mod.rs
+++ b/gfx/wr/webrender/src/prim_store/mod.rs
@@ -23,17 +23,16 @@ use display_list_flattener::{AsInstanceK
 use euclid::{SideOffsets2D, TypedTransform3D, TypedRect, TypedScale, TypedSize2D};
 use frame_builder::{FrameBuildingContext, FrameBuildingState, PictureContext, PictureState};
 use frame_builder::PrimitiveContext;
 use glyph_rasterizer::GlyphKey;
 use gpu_cache::{GpuCache, GpuCacheAddress, GpuCacheHandle, GpuDataRequest, ToGpuBlocks};
 use gpu_types::BrushFlags;
 use image::{Repetition};
 use intern;
-use malloc_size_of::MallocSizeOf;
 use picture::{PictureCompositeMode, PicturePrimitive, PictureUpdateState, TileCacheUpdateState};
 use picture::{ClusterIndex, PrimitiveList, SurfaceIndex, SurfaceInfo, RetainedTiles, RasterConfig};
 use prim_store::borders::{ImageBorderDataHandle, NormalBorderDataHandle};
 use prim_store::gradient::{LinearGradientDataHandle, RadialGradientDataHandle};
 use prim_store::image::{ImageDataHandle, ImageInstance, VisibleImageTile, YuvImageDataHandle};
 use prim_store::line_dec::LineDecorationDataHandle;
 use prim_store::picture::PictureDataHandle;
 use prim_store::text_run::{TextRunDataHandle, TextRunPrimitive};
@@ -75,17 +74,17 @@ pub fn register_prim_chase_id(id: Primit
 
 #[cfg(not(debug_assertions))]
 pub fn register_prim_chase_id(_: PrimitiveDebugId) {
 }
 
 const MIN_BRUSH_SPLIT_AREA: f32 = 256.0 * 256.0;
 pub const VECS_PER_SEGMENT: usize = 2;
 
-#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq)]
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
 pub struct ScrollNodeAndClipChain {
     pub spatial_node_index: SpatialNodeIndex,
     pub clip_chain_id: ClipChainId,
 }
 
 impl ScrollNodeAndClipChain {
     pub fn new(
         spatial_node_index: SpatialNodeIndex,
@@ -95,17 +94,17 @@ impl ScrollNodeAndClipChain {
             spatial_node_index,
             clip_chain_id,
         }
     }
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Debug, Copy, Clone, MallocSizeOf)]
+#[derive(Debug, Copy, Clone)]
 pub struct PrimitiveOpacity {
     pub is_opaque: bool,
 }
 
 impl PrimitiveOpacity {
     pub fn opaque() -> PrimitiveOpacity {
         PrimitiveOpacity { is_opaque: true }
     }
@@ -343,39 +342,38 @@ impl GpuCacheAddress {
     }
 }
 
 /// The information about an interned primitive that
 /// is stored and available in the scene builder
 /// thread.
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(MallocSizeOf)]
 pub struct PrimitiveSceneData {
     pub prim_size: LayoutSize,
     pub prim_relative_clip_rect: LayoutRect,
     pub is_backface_visible: bool,
 }
 
 /// Information specific to a primitive type that
 /// uniquely identifies a primitive template by key.
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)]
+#[derive(Debug, Clone, Eq, PartialEq, Hash)]
 pub enum PrimitiveKeyKind {
     /// Clear an existing rect, used for special effects on some platforms.
     Clear,
     Rectangle {
         color: ColorU,
     },
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Debug, Clone, MallocSizeOf, PartialEq)]
+#[derive(Debug, Clone, PartialEq)]
 pub struct RectangleKey {
     x: f32,
     y: f32,
     w: f32,
     h: f32,
 }
 
 impl Eq for RectangleKey {}
@@ -407,17 +405,17 @@ impl From<LayoutRect> for RectangleKey {
             h: rect.size.height,
         }
     }
 }
 
 /// A hashable SideOffset2D that can be used in primitive keys.
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Debug, Clone, MallocSizeOf, PartialEq)]
+#[derive(Debug, Clone, PartialEq)]
 pub struct SideOffsetsKey {
     pub top: f32,
     pub right: f32,
     pub bottom: f32,
     pub left: f32,
 }
 
 impl Eq for SideOffsetsKey {}
@@ -462,17 +460,17 @@ impl From<SideOffsets2D<f32>> for SideOf
             left: offsets.left,
         }
     }
 }
 
 /// A hashable size for using as a key during primitive interning.
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Copy, Debug, Clone, MallocSizeOf, PartialEq)]
+#[derive(Copy, Debug, Clone, PartialEq)]
 pub struct SizeKey {
     w: f32,
     h: f32,
 }
 
 impl Eq for SizeKey {}
 
 impl hash::Hash for SizeKey {
@@ -495,17 +493,17 @@ impl<U> From<TypedSize2D<f32, U>> for Si
             h: size.height,
         }
     }
 }
 
 /// A hashable vec for using as a key during primitive interning.
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Copy, Debug, Clone, MallocSizeOf, PartialEq)]
+#[derive(Copy, Debug, Clone, PartialEq)]
 pub struct VectorKey {
     pub x: f32,
     pub y: f32,
 }
 
 impl Eq for VectorKey {}
 
 impl hash::Hash for VectorKey {
@@ -528,17 +526,17 @@ impl From<LayoutVector2D> for VectorKey 
             y: vec.y,
         }
     }
 }
 
 /// A hashable point for using as a key during primitive interning.
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Debug, Clone, MallocSizeOf, PartialEq)]
+#[derive(Debug, Clone, PartialEq)]
 pub struct PointKey {
     pub x: f32,
     pub y: f32,
 }
 
 impl Eq for PointKey {}
 
 impl hash::Hash for PointKey {
@@ -560,17 +558,17 @@ impl From<LayoutPoint> for PointKey {
             x: p.x,
             y: p.y,
         }
     }
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)]
+#[derive(Debug, Clone, Eq, PartialEq, Hash)]
 pub struct PrimKeyCommonData {
     pub is_backface_visible: bool,
     pub prim_size: SizeKey,
     pub prim_relative_clip_rect: RectangleKey,
 }
 
 impl PrimKeyCommonData {
     pub fn with_info(
@@ -582,25 +580,25 @@ impl PrimKeyCommonData {
             prim_size: info.rect.size.into(),
             prim_relative_clip_rect: prim_relative_clip_rect.into(),
         }
     }
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)]
-pub struct PrimKey<T: MallocSizeOf> {
+#[derive(Debug, Clone, Eq, PartialEq, Hash)]
+pub struct PrimKey<T> {
     pub common: PrimKeyCommonData,
     pub kind: T,
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)]
+#[derive(Debug, Clone, Eq, PartialEq, Hash)]
 pub struct PrimitiveKey {
     pub common: PrimKeyCommonData,
     pub kind: PrimitiveKeyKind,
 }
 
 impl PrimitiveKey {
     pub fn new(
         is_backface_visible: bool,
@@ -645,17 +643,16 @@ impl AsInstanceKind<PrimitiveDataHandle>
         }
     }
 }
 
 /// The shared information for a given primitive. This is interned and retained
 /// both across frames and display lists, by comparing the matching PrimitiveKey.
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(MallocSizeOf)]
 pub enum PrimitiveTemplateKind {
     Rectangle {
         color: ColorF,
     },
     Clear,
 }
 
 /// Construct the primitive template data from a primitive key. This
@@ -673,17 +670,16 @@ impl PrimitiveKeyKind {
                 }
             }
         }
     }
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(MallocSizeOf)]
 pub struct PrimTemplateCommonData {
     pub is_backface_visible: bool,
     pub prim_size: LayoutSize,
     pub prim_relative_clip_rect: LayoutRect,
     pub opacity: PrimitiveOpacity,
     /// The GPU cache handle for a primitive template. Since this structure
     /// is retained across display lists by interning, this GPU cache handle
     /// also remains valid, which reduces the number of updates to the GPU
@@ -700,25 +696,23 @@ impl PrimTemplateCommonData {
             gpu_cache_handle: GpuCacheHandle::new(),
             opacity: PrimitiveOpacity::translucent(),
         }
     }
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(MallocSizeOf)]
 pub struct PrimTemplate<T> {
     pub common: PrimTemplateCommonData,
     pub kind: T,
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(MallocSizeOf)]
 pub struct PrimitiveTemplate {
     pub common: PrimTemplateCommonData,
     pub kind: PrimitiveTemplateKind,
 }
 
 impl ops::Deref for PrimitiveTemplate {
     type Target = PrimTemplateCommonData;
     fn deref(&self) -> &Self::Target {
@@ -781,17 +775,17 @@ impl PrimitiveTemplate {
             }
         };
     }
 }
 
 // Type definitions for interning primitives.
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
+#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
 pub struct PrimitiveDataMarker;
 
 impl intern::Internable for PrimitiveKeyKind {
     type Marker = PrimitiveDataMarker;
     type Source = PrimitiveKey;
     type StoreData = PrimitiveTemplate;
     type InternData = PrimitiveSceneData;
 
@@ -847,17 +841,17 @@ impl OpacityBinding {
             let opacity = scene_properties.resolve_float(binding);
             new_opacity = new_opacity * opacity;
         }
 
         self.current = new_opacity;
     }
 }
 
-#[derive(Debug, MallocSizeOf)]
+#[derive(Debug)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct VisibleMaskImageTile {
     pub tile_offset: TileOffset,
     pub tile_rect: LayoutRect,
 }
 
 #[derive(Debug)]
@@ -866,32 +860,31 @@ pub struct VisibleGradientTile {
     pub local_rect: LayoutRect,
     pub local_clip_rect: LayoutRect,
 }
 
 /// Information about how to cache a border segment,
 /// along with the current render task cache entry.
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Debug, MallocSizeOf)]
+#[derive(Debug)]
 pub struct BorderSegmentInfo {
     pub local_task_size: LayoutSize,
     pub cache_key: BorderSegmentCacheKey,
 }
 
 bitflags! {
     /// Each bit of the edge AA mask is:
     /// 0, when the edge of the primitive needs to be considered for AA
     /// 1, when the edge of the segment needs to be considered for AA
     ///
     /// *Note*: the bit values have to match the shader logic in
     /// `write_transform_vertex()` function.
     #[cfg_attr(feature = "capture", derive(Serialize))]
     #[cfg_attr(feature = "replay", derive(Deserialize))]
-    #[derive(MallocSizeOf)]
     pub struct EdgeAaSegmentMask: u8 {
         const LEFT = 0x1;
         const TOP = 0x2;
         const RIGHT = 0x4;
         const BOTTOM = 0x8;
     }
 }
 
@@ -903,17 +896,17 @@ pub enum ClipMaskKind {
     /// The segment has no clip mask.
     None,
     /// The segment is made invisible / clipped completely.
     Clipped,
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Debug, Clone, MallocSizeOf)]
+#[derive(Debug, Clone)]
 pub struct BrushSegment {
     pub local_rect: LayoutRect,
     pub may_need_clip_mask: bool,
     pub edge_flags: EdgeAaSegmentMask,
     pub extra_data: [f32; 4],
     pub brush_flags: BrushFlags,
 }
 
@@ -1193,17 +1186,17 @@ impl ClipData {
         ] {
             corner.write(request);
         }
     }
 }
 
 /// A hashable descriptor for nine-patches, used by image and
 /// gradient borders.
-#[derive(Debug, Clone, PartialEq, Eq, Hash, MallocSizeOf)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct NinePatchDescriptor {
     pub width: i32,
     pub height: i32,
     pub slice: SideOffsets2D<i32>,
     pub fill: bool,
     pub repeat_horizontal: RepeatMode,
--- a/gfx/wr/webrender/src/prim_store/picture.rs
+++ b/gfx/wr/webrender/src/prim_store/picture.rs
@@ -14,17 +14,17 @@ use prim_store::{
     PrimKey, PrimKeyCommonData, PrimTemplate, PrimTemplateCommonData,
     PrimitiveInstanceKind, PrimitiveSceneData, PrimitiveStore, VectorKey,
 };
 
 /// Represents a hashable description of how a picture primitive
 /// will be composited into its parent.
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Debug, Clone, MallocSizeOf, PartialEq, Hash, Eq)]
+#[derive(Debug, Clone, PartialEq, Hash, Eq)]
 pub enum PictureCompositeKey {
     // No visual compositing effect
     Identity,
 
     // FilterOp
     Blur(Au),
     Brightness(Au),
     Contrast(Au),
@@ -122,17 +122,17 @@ impl From<Option<PictureCompositeMode>> 
                 PictureCompositeKey::Identity
             }
         }
     }
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)]
+#[derive(Debug, Clone, Eq, PartialEq, Hash)]
 pub struct Picture {
     pub composite_mode_key: PictureCompositeKey,
 }
 
 pub type PictureKey = PrimKey<Picture>;
 
 impl PictureKey {
     pub fn new(
@@ -166,17 +166,16 @@ impl AsInstanceKind<PictureDataHandle> f
         // Should never be hit as this method should not be
         // called for pictures.
         unreachable!();
     }
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(MallocSizeOf)]
 pub struct PictureData;
 
 pub type PictureTemplate = PrimTemplate<PictureData>;
 
 impl From<PictureKey> for PictureTemplate {
     fn from(key: PictureKey) -> Self {
         let common = PrimTemplateCommonData::with_key_common(key.common);
 
@@ -184,17 +183,17 @@ impl From<PictureKey> for PictureTemplat
             common,
             kind: PictureData,
         }
     }
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
+#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
 pub struct PictureDataMarker;
 
 pub type PictureDataStore = DataStore<PictureKey, PictureTemplate, PictureDataMarker>;
 pub type PictureDataHandle = Handle<PictureDataMarker>;
 pub type PictureDataUpdateList = UpdateList<PictureKey>;
 pub type PictureDataInterner = Interner<PictureKey, PrimitiveSceneData, PictureDataMarker>;
 
 impl Internable for Picture {
--- a/gfx/wr/webrender/src/prim_store/text_run.rs
+++ b/gfx/wr/webrender/src/prim_store/text_run.rs
@@ -18,17 +18,17 @@ use resource_cache::{ResourceCache};
 use util::{MatrixHelpers};
 use prim_store::PrimitiveInstanceKind;
 use std::ops;
 use storage;
 
 /// A run of glyphs, with associated font information.
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)]
+#[derive(Debug, Clone, Eq, PartialEq, Hash)]
 pub struct TextRunKey {
     pub common: PrimKeyCommonData,
     pub font: FontInstance,
     pub offset: VectorKey,
     pub glyphs: Vec<GlyphInstance>,
     pub shadow: bool,
 }
 
@@ -68,17 +68,16 @@ impl AsInstanceKind<TextRunDataHandle> f
         });
 
         PrimitiveInstanceKind::TextRun{ data_handle, run_index }
     }
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(MallocSizeOf)]
 pub struct TextRunTemplate {
     pub common: PrimTemplateCommonData,
     pub font: FontInstance,
     pub offset: LayoutVector2D,
     pub glyphs: Vec<GlyphInstance>,
 }
 
 impl ops::Deref for TextRunTemplate {
@@ -157,17 +156,17 @@ impl TextRunTemplate {
 
             assert!(request.current_used_block_num() <= MAX_VERTEX_TEXTURE_WIDTH);
         }
     }
 }
 
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)]
+#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
 pub struct TextRunDataMarker;
 
 pub type TextRunDataStore = intern::DataStore<TextRunKey, TextRunTemplate, TextRunDataMarker>;
 pub type TextRunDataHandle = intern::Handle<TextRunDataMarker>;
 pub type TextRunDataUpdateList = intern::UpdateList<TextRunKey>;
 pub type TextRunDataInterner = intern::Interner<TextRunKey, PrimitiveSceneData, TextRunDataMarker>;
 
 pub struct TextRun {
--- a/gfx/wr/webrender/src/render_backend.rs
+++ b/gfx/wr/webrender/src/render_backend.rs
@@ -9,33 +9,32 @@
 //! how these two pieces interact.
 
 use api::{ApiMsg, BuiltDisplayList, ClearCache, DebugCommand, DebugFlags};
 #[cfg(feature = "debugger")]
 use api::{BuiltDisplayListIter, SpecificDisplayItem};
 use api::{DevicePixelScale, DeviceIntPoint, DeviceIntRect, DeviceIntSize};
 use api::{DocumentId, DocumentLayer, ExternalScrollId, FrameMsg, HitTestFlags, HitTestResult};
 use api::{IdNamespace, LayoutPoint, PipelineId, RenderNotifier, SceneMsg, ScrollClamping};
-use api::{MemoryReport};
+use api::{MemoryReport, VoidPtrToSizeFn};
 use api::{ScrollLocation, ScrollNodeState, TransactionMsg, ResourceUpdate, BlobImageKey};
 use api::{NotificationRequest, Checkpoint};
 use api::channel::{MsgReceiver, MsgSender, Payload};
 #[cfg(feature = "capture")]
 use api::CaptureBits;
 #[cfg(feature = "replay")]
 use api::CapturedDocument;
 use clip::ClipDataStore;
 use clip_scroll_tree::{SpatialNodeIndex, ClipScrollTree};
 #[cfg(feature = "debugger")]
 use debug_server;
 use frame_builder::{FrameBuilder, FrameBuilderConfig};
 use gpu_cache::GpuCache;
 use hit_test::{HitTest, HitTester};
 use internal_types::{DebugOutput, FastHashMap, FastHashSet, RenderedDocument, ResultMsg};
-use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
 use picture::RetainedTiles;
 use prim_store::{PrimitiveDataStore, PrimitiveScratchBuffer, PrimitiveInstance};
 use prim_store::{PrimitiveInstanceKind, PrimTemplateCommonData};
 use prim_store::borders::{ImageBorderDataStore, NormalBorderDataStore};
 use prim_store::gradient::{LinearGradientDataStore, RadialGradientDataStore};
 use prim_store::image::{ImageDataStore, YuvImageDataStore};
 use prim_store::line_dec::LineDecorationDataStore;
 use prim_store::picture::PictureDataStore;
@@ -84,17 +83,17 @@ impl DocumentView {
         DevicePixelScale::new(
             self.device_pixel_ratio *
             self.page_zoom_factor *
             self.pinch_zoom_factor
         )
     }
 }
 
-#[derive(Copy, Clone, Hash, MallocSizeOf, PartialEq, PartialOrd, Debug, Eq, Ord)]
+#[derive(Copy, Clone, Hash, PartialEq, PartialOrd, Debug, Eq, Ord)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct FrameId(usize);
 
 impl FrameId {
     /// Returns a FrameId corresponding to the first frame.
     ///
     /// Note that we use 0 as the internal id here because the current code
@@ -138,17 +137,17 @@ impl ::std::ops::Sub<usize> for FrameId 
 
 /// Identifier to track a sequence of frames.
 ///
 /// This is effectively a `FrameId` with a ridealong timestamp corresponding
 /// to when advance() was called, which allows for more nuanced cache eviction
 /// decisions. As such, we use the `FrameId` for equality and comparison, since
 /// we should never have two `FrameStamps` with the same id but different
 /// timestamps.
-#[derive(Copy, Clone, Debug, MallocSizeOf)]
+#[derive(Copy, Clone, Debug)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct FrameStamp {
     id: FrameId,
     time: SystemTime,
     document_id: DocumentId,
 }
 
@@ -209,42 +208,40 @@ impl FrameStamp {
     /// An invalid sentinel FrameStamp.
     pub const INVALID: FrameStamp = FrameStamp {
         id: FrameId(0),
         time: UNIX_EPOCH,
         document_id: DocumentId::INVALID,
     };
 }
 
-macro_rules! declare_frame_resources {
-    ( $( { $x: ident, $y: ty, $datastore_ident: ident, $datastore_type: ty } )+ ) => {
-        /// A collection of resources that are shared by clips, primitives
-        /// between display lists.
-        #[cfg_attr(feature = "capture", derive(Serialize))]
-        #[cfg_attr(feature = "replay", derive(Deserialize))]
-        #[derive(Default)]
-        pub struct FrameResources {
-            $(
-                pub $datastore_ident: $datastore_type,
-            )+
-        }
+// A collection of resources that are shared by clips, primitives
+// between display lists.
+#[cfg_attr(feature = "capture", derive(Serialize))]
+#[cfg_attr(feature = "replay", derive(Deserialize))]
+#[derive(Default)]
+pub struct FrameResources {
+    /// The store of currently active / available clip nodes. This is kept
+    /// in sync with the clip interner in the scene builder for each document.
+    pub clip_data_store: ClipDataStore,
 
-        impl FrameResources {
-            /// Reports CPU heap usage.
-            fn report_memory(&self, ops: &mut MallocSizeOfOps, r: &mut MemoryReport) {
-                $(
-                    r.interning.$datastore_ident += self.$datastore_ident.size_of(ops);
-                )+
-            }
-        }
-    }
+    /// Currently active / available primitives. Kept in sync with the
+    /// primitive interner in the scene builder, per document.
+    pub prim_data_store: PrimitiveDataStore,
+    pub image_data_store: ImageDataStore,
+    pub image_border_data_store: ImageBorderDataStore,
+    pub line_decoration_data_store: LineDecorationDataStore,
+    pub linear_grad_data_store: LinearGradientDataStore,
+    pub normal_border_data_store: NormalBorderDataStore,
+    pub picture_data_store: PictureDataStore,
+    pub radial_grad_data_store: RadialGradientDataStore,
+    pub text_run_data_store: TextRunDataStore,
+    pub yuv_image_data_store: YuvImageDataStore,
 }
 
-enumerate_interners!(declare_frame_resources);
-
 impl FrameResources {
     pub fn as_common_data(
         &self,
         prim_inst: &PrimitiveInstance
     ) -> &PrimTemplateCommonData {
         match prim_inst.kind {
             PrimitiveInstanceKind::Rectangle { data_handle, .. } |
             PrimitiveInstanceKind::Clear { data_handle, .. } => {
@@ -284,16 +281,25 @@ impl FrameResources {
                 &prim_data.common
             }
             PrimitiveInstanceKind::YuvImage { data_handle, .. } => {
                 let prim_data = &self.yuv_image_data_store[data_handle];
                 &prim_data.common
             }
         }
     }
+
+    /// Reports CPU heap usage.
+    fn report_memory(&self, op: VoidPtrToSizeFn, r: &mut MemoryReport) {
+        r.data_stores += self.clip_data_store.malloc_size_of(op);
+        r.data_stores += self.prim_data_store.malloc_size_of(op);
+        r.data_stores += self.linear_grad_data_store.malloc_size_of(op);
+        r.data_stores += self.radial_grad_data_store.malloc_size_of(op);
+        r.data_stores += self.text_run_data_store.malloc_size_of(op);
+    }
 }
 
 struct Document {
     // The latest built scene, usable to build frames.
     // received from the scene builder thread.
     scene: Scene,
 
     // Temporary list of removed pipelines received from the scene builder
@@ -668,17 +674,17 @@ pub struct RenderBackend {
     resource_cache: ResourceCache,
 
     frame_config: FrameBuilderConfig,
     documents: FastHashMap<DocumentId, Document>,
 
     notifier: Box<RenderNotifier>,
     recorder: Option<Box<ApiRecordingReceiver>>,
     sampler: Option<Box<AsyncPropertySampler + Send>>,
-    size_of_ops: Option<MallocSizeOfOps>,
+    size_of_op: Option<VoidPtrToSizeFn>,
     debug_flags: DebugFlags,
     namespace_alloc_by_client: bool,
 }
 
 impl RenderBackend {
     pub fn new(
         api_rx: MsgReceiver<ApiMsg>,
         payload_rx: Receiver<Payload>,
@@ -687,17 +693,17 @@ impl RenderBackend {
         low_priority_scene_tx: Sender<SceneBuilderRequest>,
         scene_rx: Receiver<SceneBuilderResult>,
         default_device_pixel_ratio: f32,
         resource_cache: ResourceCache,
         notifier: Box<RenderNotifier>,
         frame_config: FrameBuilderConfig,
         recorder: Option<Box<ApiRecordingReceiver>>,
         sampler: Option<Box<AsyncPropertySampler + Send>>,
-        size_of_ops: Option<MallocSizeOfOps>,
+        size_of_op: Option<VoidPtrToSizeFn>,
         debug_flags: DebugFlags,
         namespace_alloc_by_client: bool,
     ) -> RenderBackend {
         RenderBackend {
             api_rx,
             payload_rx,
             result_tx,
             scene_tx,
@@ -707,17 +713,17 @@ impl RenderBackend {
             default_device_pixel_ratio,
             resource_cache,
             gpu_cache: GpuCache::new(),
             frame_config,
             documents: FastHashMap::default(),
             notifier,
             recorder,
             sampler,
-            size_of_ops,
+            size_of_op,
             debug_flags,
             namespace_alloc_by_client,
         }
     }
 
     fn process_scene_msg(
         &mut self,
         document_id: DocumentId,
@@ -1541,28 +1547,28 @@ impl RenderBackend {
             doc.clip_scroll_tree.print_with(&mut builder);
 
             debug_root.add(builder.build());
         }
 
         serde_json::to_string(&debug_root).unwrap()
     }
 
-    fn report_memory(&mut self, tx: MsgSender<MemoryReport>) {
+    fn report_memory(&self, tx: MsgSender<MemoryReport>) {
         let mut report = MemoryReport::default();
-        let ops = self.size_of_ops.as_mut().unwrap();
-        let op = ops.size_of_op;
-        report.gpu_cache_metadata = self.gpu_cache.size_of(ops);
+        let op = self.size_of_op.unwrap();
+        report.gpu_cache_metadata = self.gpu_cache.malloc_size_of(op);
         for (_id, doc) in &self.documents {
             if let Some(ref fb) = doc.frame_builder {
-                report.clip_stores += fb.clip_store.size_of(ops);
+                report.clip_stores += fb.clip_store.malloc_size_of(op);
             }
-            report.hit_testers += doc.hit_tester.size_of(ops);
+            report.hit_testers +=
+                doc.hit_tester.as_ref().map_or(0, |ht| ht.malloc_size_of(op));
 
-            doc.resources.report_memory(ops, &mut report)
+            doc.resources.report_memory(op, &mut report)
         }
 
         report += self.resource_cache.report_memory(op);
 
         // Send a message to report memory on the scene-builder thread, which
         // will add its report to this one and send the result back to the original
         // thread waiting on the request.
         self.scene_tx.send(SceneBuilderRequest::ReportMemory(report, tx)).unwrap();
--- a/gfx/wr/webrender/src/render_task.rs
+++ b/gfx/wr/webrender/src/render_task.rs
@@ -1108,17 +1108,17 @@ pub struct RenderTaskCacheKey {
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct RenderTaskCacheEntry {
     pending_render_task_id: Option<RenderTaskId>,
     user_data: Option<[f32; 3]>,
     is_opaque: bool,
     pub handle: TextureCacheHandle,
 }
 
-#[derive(Debug, MallocSizeOf)]
+#[derive(Debug)]
 pub enum RenderTaskCacheMarker {}
 
 // A cache of render tasks that are stored in the texture
 // cache for usage across frames.
 #[derive(Debug)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct RenderTaskCache {
--- a/gfx/wr/webrender/src/renderer.rs
+++ b/gfx/wr/webrender/src/renderer.rs
@@ -54,17 +54,16 @@ use gpu_cache::{GpuBlockData, GpuCacheUp
 use gpu_cache::{GpuCacheDebugChunk, GpuCacheDebugCmd};
 #[cfg(feature = "pathfinder")]
 use gpu_glyph_renderer::GpuGlyphRenderer;
 use gpu_types::ScalingInstance;
 use internal_types::{TextureSource, ORTHO_FAR_PLANE, ORTHO_NEAR_PLANE, ResourceCacheError};
 use internal_types::{CacheTextureId, DebugOutput, FastHashMap, LayerIndex, RenderedDocument, ResultMsg};
 use internal_types::{TextureCacheAllocationKind, TextureCacheUpdate, TextureUpdateList, TextureUpdateSource};
 use internal_types::{RenderTargetInfo, SavedTargetIndex};
-use malloc_size_of::MallocSizeOfOps;
 use prim_store::DeferredResolve;
 use profiler::{BackendProfileCounters, FrameProfileCounters, TimeProfileCounter,
                GpuProfileTag, RendererProfileCounters, RendererProfileTimers};
 use device::query::GpuProfiler;
 use rayon::{ThreadPool, ThreadPoolBuilder};
 use record::ApiRecordingReceiver;
 use render_backend::{FrameId, RenderBackend};
 use render_task::ClearMode;
@@ -1552,19 +1551,27 @@ pub struct Renderer {
     /// application to provide external buffers for image data.
     external_image_handler: Option<Box<ExternalImageHandler>>,
 
     /// Optional trait object that allows the client
     /// application to provide a texture handle to
     /// copy the WR output to.
     output_image_handler: Option<Box<OutputImageHandler>>,
 
-    /// Optional function pointers for measuring memory used by a given
+    /// Optional function pointer for measuring memory used by a given
     /// heap-allocated pointer.
-    size_of_ops: Option<MallocSizeOfOps>,
+    size_of_op: Option<VoidPtrToSizeFn>,
+
+    /// Optional function pointer for measuring memory used by a given
+    /// heap-allocated region of memory. Unlike the above, pointers passed
+    /// to this function do not need to point to the start of the allocation,
+    /// and can be anywhere in the allocated region. This is useful for measuring
+    /// structures like hashmaps that don't expose pointers to the start of the
+    /// allocation, but do expose pointers to elements within the allocation.
+    _enclosing_size_of_op: Option<VoidPtrToSizeFn>,
 
     // Currently allocated FBOs for output frames.
     output_targets: FastHashMap<u32, FrameOutput>,
 
     pub renderer_errors: Vec<RendererError>,
 
     /// List of profile results from previous frames. Can be retrieved
     /// via get_frame_profiles().
@@ -1820,20 +1827,16 @@ impl Renderer {
             dual_source_blending_is_supported: ext_dual_source_blending,
             chase_primitive: options.chase_primitive,
             enable_picture_caching: options.enable_picture_caching,
         };
 
         let device_pixel_ratio = options.device_pixel_ratio;
         let debug_flags = options.debug_flags;
         let payload_rx_for_backend = payload_rx.to_mpsc_receiver();
-        let size_of_op = options.size_of_op;
-        let enclosing_size_of_op = options.enclosing_size_of_op;
-        let make_size_of_ops =
-            move || size_of_op.map(|o| MallocSizeOfOps::new(o, enclosing_size_of_op));
         let recorder = options.recorder;
         let thread_listener = Arc::new(options.thread_listener);
         let thread_listener_for_rayon_start = thread_listener.clone();
         let thread_listener_for_rayon_end = thread_listener.clone();
         let workers = options
             .workers
             .take()
             .unwrap_or_else(|| {
@@ -1849,33 +1852,36 @@ impl Renderer {
                         if let Some(ref thread_listener) = *thread_listener_for_rayon_end {
                             thread_listener.thread_stopped(&format!("WRWorker#{}", idx));
                         }
                     })
                     .build();
                 Arc::new(worker.unwrap())
             });
         let sampler = options.sampler;
+        let size_of_op = options.size_of_op;
+        let enclosing_size_of_op = options.enclosing_size_of_op;
         let namespace_alloc_by_client = options.namespace_alloc_by_client;
 
         let blob_image_handler = options.blob_image_handler.take();
         let thread_listener_for_render_backend = thread_listener.clone();
         let thread_listener_for_scene_builder = thread_listener.clone();
         let thread_listener_for_lp_scene_builder = thread_listener.clone();
         let scene_builder_hooks = options.scene_builder_hooks;
         let rb_thread_name = format!("WRRenderBackend#{}", options.renderer_id.unwrap_or(0));
         let scene_thread_name = format!("WRSceneBuilder#{}", options.renderer_id.unwrap_or(0));
         let lp_scene_thread_name = format!("WRSceneBuilderLP#{}", options.renderer_id.unwrap_or(0));
         let glyph_rasterizer = GlyphRasterizer::new(workers)?;
 
         let (scene_builder, scene_tx, scene_rx) = SceneBuilder::new(
             config,
             api_tx.clone(),
             scene_builder_hooks,
-            make_size_of_ops(),
+            size_of_op,
+            enclosing_size_of_op,
         );
         thread::Builder::new().name(scene_thread_name.clone()).spawn(move || {
             register_thread_with_profiler(scene_thread_name.clone());
             if let Some(ref thread_listener) = *thread_listener_for_scene_builder {
                 thread_listener.thread_started(&scene_thread_name);
             }
 
             let mut scene_builder = scene_builder;
@@ -1938,17 +1944,17 @@ impl Renderer {
                 low_priority_scene_tx,
                 scene_rx,
                 device_pixel_ratio,
                 resource_cache,
                 backend_notifier,
                 config,
                 recorder,
                 sampler,
-                make_size_of_ops(),
+                size_of_op,
                 debug_flags,
                 namespace_alloc_by_client,
             );
             backend.run(backend_profile_counters);
             if let Some(ref thread_listener) = *thread_listener_for_render_backend {
                 thread_listener.thread_stopped(&rb_thread_name);
             }
         })?;
@@ -2000,17 +2006,18 @@ impl Renderer {
             transforms_texture,
             prim_header_i_texture,
             prim_header_f_texture,
             render_task_texture,
             pipeline_info: PipelineInfo::default(),
             dither_matrix_texture,
             external_image_handler: None,
             output_image_handler: None,
-            size_of_ops: make_size_of_ops(),
+            size_of_op: options.size_of_op,
+            _enclosing_size_of_op: options.enclosing_size_of_op,
             output_targets: FastHashMap::default(),
             cpu_profiles: VecDeque::new(),
             gpu_profiles: VecDeque::new(),
             gpu_cache_texture,
             #[cfg(feature = "debug_renderer")]
             gpu_cache_debug_chunks: Vec::new(),
             gpu_cache_frame_id: FrameId::INVALID,
             gpu_cache_overflow: false,
@@ -4560,17 +4567,17 @@ impl Renderer {
         #[cfg(feature = "replay")]
         for (_, ext) in self.owned_external_images {
             self.device.delete_external_texture(ext);
         }
         self.device.end_frame();
     }
 
     fn size_of<T>(&self, ptr: *const T) -> usize {
-        let op = self.size_of_ops.as_ref().unwrap().size_of_op;
+        let op = self.size_of_op.as_ref().unwrap();
         unsafe { op(ptr as *const c_void) }
     }
 
     /// Collects a memory report.
     pub fn report_memory(&self) -> MemoryReport {
         let mut report = MemoryReport::default();
 
         // GPU cache CPU memory.
--- a/gfx/wr/webrender/src/resource_cache.rs
+++ b/gfx/wr/webrender/src/resource_cache.rs
@@ -1816,23 +1816,16 @@ impl ResourceCache {
             .clear_fonts(|font| font.font_key.0 == namespace);
 
         if let Some(ref mut r) = self.blob_image_handler {
             r.clear_namespace(namespace);
         }
     }
 
     /// Reports the CPU heap usage of this ResourceCache.
-    ///
-    /// NB: It would be much better to use the derive(MallocSizeOf) machinery
-    /// here, but the Arcs complicate things. The two ways to handle that would
-    /// be to either (a) Implement MallocSizeOf manually for the things that own
-    /// them and manually avoid double-counting, or (b) Use the "seen this pointer
-    /// yet" machinery from the proper malloc_size_of crate. We can do this if/when
-    /// more accurate memory reporting on these resources becomes a priority.
     pub fn report_memory(&self, op: VoidPtrToSizeFn) -> MemoryReport {
         let mut report = MemoryReport::default();
 
         // Measure fonts. We only need the templates here, because the instances
         // don't have big buffers.
         for (_, font) in self.resources.font_templates.iter() {
             if let FontTemplate::Raw(ref raw, _) = font {
                 report.fonts += unsafe { op(raw.as_ptr() as *const c_void) };
--- a/gfx/wr/webrender/src/scene_builder.rs
+++ b/gfx/wr/webrender/src/scene_builder.rs
@@ -1,26 +1,25 @@
 /* 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 api::{AsyncBlobImageRasterizer, BlobImageRequest, BlobImageParams, BlobImageResult};
 use api::{DocumentId, PipelineId, ApiMsg, FrameMsg, ResourceUpdate, ExternalEvent, Epoch};
 use api::{BuiltDisplayList, ColorF, LayoutSize, NotificationRequest, Checkpoint, IdNamespace};
-use api::{MemoryReport};
+use api::{MemoryReport, VoidPtrToSizeFn};
 use api::channel::MsgSender;
 #[cfg(feature = "capture")]
 use capture::CaptureConfig;
 use frame_builder::{FrameBuilderConfig, FrameBuilder};
 use clip::{ClipDataInterner, ClipDataUpdateList};
 use clip_scroll_tree::ClipScrollTree;
 use display_list_flattener::DisplayListFlattener;
 use intern::{Internable, Interner};
 use internal_types::{FastHashMap, FastHashSet};
-use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
 use prim_store::{PrimitiveDataInterner, PrimitiveDataUpdateList, PrimitiveKeyKind};
 use prim_store::PrimitiveStoreStats;
 use prim_store::borders::{
     ImageBorder, ImageBorderDataInterner, ImageBorderDataUpdateList,
     NormalBorderPrim, NormalBorderDataInterner, NormalBorderDataUpdateList
 };
 use prim_store::gradient::{
     LinearGradient, LinearGradientDataInterner, LinearGradientDataUpdateList,
@@ -189,50 +188,55 @@ pub enum SceneBuilderResult {
 // Message from render backend to scene builder to indicate the
 // scene swap was completed. We need a separate channel for this
 // so that they don't get mixed with SceneBuilderRequest messages.
 pub enum SceneSwapResult {
     Complete(Sender<()>),
     Aborted,
 }
 
-macro_rules! declare_document_resources {
-    ( $( { $interner_ident: ident, $interner_type: ty, $x: ident, $y: ty } )+ ) => {
-        /// This struct contains all items that can be shared between
-        /// display lists. We want to intern and share the same clips,
-        /// primitives and other things between display lists so that:
-        /// - GPU cache handles remain valid, reducing GPU cache updates.
-        /// - Comparison of primitives and pictures between two
-        ///   display lists is (a) fast (b) done during scene building.
-        #[cfg_attr(feature = "capture", derive(Serialize))]
-        #[cfg_attr(feature = "replay", derive(Deserialize))]
-        #[derive(Default)]
-        pub struct DocumentResources {
-            $(
-                pub $interner_ident: $interner_type,
-            )+
-        }
+// This struct contains all items that can be shared between
+// display lists. We want to intern and share the same clips,
+// primitives and other things between display lists so that:
+// - GPU cache handles remain valid, reducing GPU cache updates.
+// - Comparison of primitives and pictures between two
+//   display lists is (a) fast (b) done during scene building.
+#[cfg_attr(feature = "capture", derive(Serialize))]
+#[cfg_attr(feature = "replay", derive(Deserialize))]
+#[derive(Default)]
+pub struct DocumentResources {
+    pub clip_interner: ClipDataInterner,
+    pub prim_interner: PrimitiveDataInterner,
+    pub image_interner: ImageDataInterner,
+    pub image_border_interner: ImageBorderDataInterner,
+    pub line_decoration_interner: LineDecorationDataInterner,
+    pub linear_grad_interner: LinearGradientDataInterner,
+    pub normal_border_interner: NormalBorderDataInterner,
+    pub picture_interner: PictureDataInterner,
+    pub radial_grad_interner: RadialGradientDataInterner,
+    pub text_run_interner: TextRunDataInterner,
+    pub yuv_image_interner: YuvImageDataInterner,
+}
 
-        impl DocumentResources {
-            /// Reports CPU heap memory used by the interners.
-            fn report_memory(
-                &self,
-                ops: &mut MallocSizeOfOps,
-                r: &mut MemoryReport,
-            ) {
-                $(
-                    r.interning.$interner_ident += self.$interner_ident.size_of(ops);
-                )+
-            }
-        }
+impl DocumentResources {
+    /// Reports CPU heap memory used by the interners.
+    fn report_memory(
+        &self,
+        op: VoidPtrToSizeFn,
+        eop: VoidPtrToSizeFn,
+        r: &mut MemoryReport,
+    ) {
+        r.interners += self.clip_interner.malloc_size_of(op, eop);
+        r.interners += self.prim_interner.malloc_size_of(op, eop);
+        r.interners += self.linear_grad_interner.malloc_size_of(op, eop);
+        r.interners += self.radial_grad_interner.malloc_size_of(op, eop);
+        r.interners += self.text_run_interner.malloc_size_of(op, eop);
     }
 }
 
-enumerate_interners!(declare_document_resources);
-
 // Access to `DocumentResources` interners by `Internable`
 pub trait InternerMut<I: Internable>
 {
     fn interner_mut(&mut self) -> &mut Interner<I::Source, I::InternData, I::Marker>;
 }
 
 macro_rules! impl_internet_mut {
     ($($ty:ident: $mem:ident,)*) => {
@@ -284,37 +288,40 @@ impl Document {
 pub struct SceneBuilder {
     documents: FastHashMap<DocumentId, Document>,
     rx: Receiver<SceneBuilderRequest>,
     tx: Sender<SceneBuilderResult>,
     api_tx: MsgSender<ApiMsg>,
     config: FrameBuilderConfig,
     hooks: Option<Box<SceneBuilderHooks + Send>>,
     simulate_slow_ms: u32,
-    size_of_ops: Option<MallocSizeOfOps>,
+    size_of_op: Option<VoidPtrToSizeFn>,
+    enclosing_size_of_op: Option<VoidPtrToSizeFn>,
 }
 
 impl SceneBuilder {
     pub fn new(
         config: FrameBuilderConfig,
         api_tx: MsgSender<ApiMsg>,
         hooks: Option<Box<SceneBuilderHooks + Send>>,
-        size_of_ops: Option<MallocSizeOfOps>,
+        size_of_op: Option<VoidPtrToSizeFn>,
+        enclosing_size_of_op: Option<VoidPtrToSizeFn>,
     ) -> (Self, Sender<SceneBuilderRequest>, Receiver<SceneBuilderResult>) {
         let (in_tx, in_rx) = channel();
         let (out_tx, out_rx) = channel();
         (
             SceneBuilder {
                 documents: FastHashMap::default(),
                 rx: in_rx,
                 tx: out_tx,
                 api_tx,
                 config,
                 hooks,
-                size_of_ops,
+                size_of_op,
+                enclosing_size_of_op,
                 simulate_slow_ms: 0,
             },
             in_tx,
             out_rx,
         )
     }
 
     /// Send a message to the render backend thread.
@@ -751,21 +758,22 @@ impl SceneBuilder {
         } else {
             if let &Some(ref hooks) = &self.hooks {
                 hooks.post_empty_scene_build();
             }
         }
     }
 
     /// Reports CPU heap memory used by the SceneBuilder.
-    fn report_memory(&mut self) -> MemoryReport {
-        let ops = self.size_of_ops.as_mut().unwrap();
+    fn report_memory(&self) -> MemoryReport {
+        let op = self.size_of_op.unwrap();
+        let eop = self.enclosing_size_of_op.unwrap();
         let mut report = MemoryReport::default();
         for doc in self.documents.values() {
-            doc.resources.report_memory(ops, &mut report);
+            doc.resources.report_memory(op, eop, &mut report);
         }
 
         report
     }
 }
 
 /// A scene builder thread which executes expensive operations such as blob rasterization
 /// with a lower priority than the normal scene builder thread.
--- a/gfx/wr/webrender/src/util.rs
+++ b/gfx/wr/webrender/src/util.rs
@@ -87,17 +87,17 @@ impl<T> VecHelper<T> for Vec<T> {
 
 // Represents an optimized transform where there is only
 // a scale and translation (which are guaranteed to maintain
 // an axis align rectangle under transformation). The
 // scaling is applied first, followed by the translation.
 // TODO(gw): We should try and incorporate F <-> T units here,
 //           but it's a bit tricky to do that now with the
 //           way the current clip-scroll tree works.
-#[derive(Debug, Clone, Copy, MallocSizeOf)]
+#[derive(Debug, Clone, Copy)]
 pub struct ScaleOffset {
     pub scale: Vector2D<f32>,
     pub offset: Vector2D<f32>,
 }
 
 impl ScaleOffset {
     pub fn identity() -> Self {
         ScaleOffset {
@@ -551,17 +551,17 @@ impl<U> MaxRect for TypedRect<f32, U> {
             TypedPoint2D::new(-MAX_COORD, -MAX_COORD),
             TypedSize2D::new(2.0 * MAX_COORD, 2.0 * MAX_COORD),
         )
     }
 }
 
 /// An enum that tries to avoid expensive transformation matrix calculations
 /// when possible when dealing with non-perspective axis-aligned transformations.
-#[derive(Debug, MallocSizeOf)]
+#[derive(Debug)]
 pub enum FastTransform<Src, Dst> {
     /// A simple offset, which can be used without doing any matrix math.
     Offset(TypedVector2D<f32, Src>),
 
     /// A 2D transformation with an inverse.
     Transform {
         transform: TypedTransform3D<f32, Src, Dst>,
         inverse: Option<TypedTransform3D<f32, Dst, Src>>,
--- a/gfx/wr/webrender_api/Cargo.toml
+++ b/gfx/wr/webrender_api/Cargo.toml
@@ -14,21 +14,19 @@ deserialize = []
 
 [dependencies]
 app_units = "0.7"
 bincode = "1.0"
 bitflags = "1.0"
 byteorder = "1.2.1"
 ipc-channel = {version = "0.11.0", optional = true}
 euclid = { version = "0.19.4", features = ["serde"] }
-malloc_size_of_derive = "0.1"
 serde = { version = "=1.0.80", features = ["rc"] }
 serde_derive = { version = "=1.0.80", features = ["deserialize_in_place"] }
 serde_bytes = "0.10"
 time = "0.1"
-wr_malloc_size_of = { version = "0.0.1", path = "../wr_malloc_size_of" }
 
 [target.'cfg(target_os = "macos")'.dependencies]
 core-foundation = "0.6"
 core-graphics = "0.17.1"
 
 [target.'cfg(target_os = "windows")'.dependencies]
 dwrote = "0.7"
--- a/gfx/wr/webrender_api/src/api.rs
+++ b/gfx/wr/webrender_api/src/api.rs
@@ -556,17 +556,17 @@ pub struct HitTestItem {
 }
 
 #[derive(Clone, Debug, Default, Deserialize, Serialize)]
 pub struct HitTestResult {
     pub items: Vec<HitTestItem>,
 }
 
 bitflags! {
-    #[derive(Deserialize, MallocSizeOf, Serialize)]
+    #[derive(Deserialize, Serialize)]
     pub struct HitTestFlags: u8 {
         const FIND_ALL = 0b00000001;
         const POINT_RELATIVE_TO_PIPELINE_VIEWPORT = 0b00000010;
     }
 }
 
 #[derive(Clone, Deserialize, Serialize)]
 pub struct AddFontInstance {
@@ -782,137 +782,90 @@ pub struct Epoch(pub u32);
 
 impl Epoch {
     pub fn invalid() -> Epoch {
         Epoch(u32::MAX)
     }
 }
 
 #[repr(C)]
-#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize)]
+#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize)]
 pub struct IdNamespace(pub u32);
 
 #[repr(C)]
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
+#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
 pub struct DocumentId(pub IdNamespace, pub u32);
 
 impl DocumentId {
     pub const INVALID: DocumentId = DocumentId(IdNamespace(0), 0);
 }
 
 /// This type carries no valuable semantics for WR. However, it reflects the fact that
 /// clients (Servo) may generate pipelines by different semi-independent sources.
 /// These pipelines still belong to the same `IdNamespace` and the same `DocumentId`.
 /// Having this extra Id field enables them to generate `PipelineId` without collision.
 pub type PipelineSourceId = u32;
 
 /// From the point of view of WR, `PipelineId` is completely opaque and generic as long as
 /// it's clonable, serializable, comparable, and hashable.
 #[repr(C)]
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
+#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
 pub struct PipelineId(pub PipelineSourceId, pub u32);
 
 impl PipelineId {
     pub fn dummy() -> Self {
         PipelineId(0, 0)
     }
 }
 
-/// Meta-macro to enumerate the various interner identifiers and types.
-///
-/// IMPORTANT: Keep this synchronized with the list in mozilla-central located at
-/// gfx/webrender_bindings/webrender_ffi.h
-///
-/// Note that this could be a lot less verbose if concat_idents! were stable. :-(
-#[macro_export]
-macro_rules! enumerate_interners {
-    ($macro_name: ident) => {
-        $macro_name! {
-            { clip_interner, ClipDataInterner, clip_data_store, ClipDataStore }
-            { prim_interner, PrimitiveDataInterner, prim_data_store, PrimitiveDataStore }
-            { normal_border_interner, NormalBorderDataInterner, normal_border_data_store, NormalBorderDataStore }
-            { image_border_interner, ImageBorderDataInterner, image_border_data_store, ImageBorderDataStore }
-            { image_interner, ImageDataInterner, image_data_store, ImageDataStore }
-            { yuv_image_interner, YuvImageDataInterner, yuv_image_data_store, YuvImageDataStore }
-            { line_decoration_interner, LineDecorationDataInterner, line_decoration_data_store, LineDecorationDataStore }
-            { linear_grad_interner, LinearGradientDataInterner, linear_grad_data_store, LinearGradientDataStore }
-            { radial_grad_interner, RadialGradientDataInterner, radial_grad_data_store, RadialGradientDataStore }
-            { picture_interner, PictureDataInterner, picture_data_store, PictureDataStore }
-            { text_run_interner, TextRunDataInterner, text_run_data_store, TextRunDataStore }
-        }
-    }
-}
-
-macro_rules! declare_interning_memory_report {
-    ( $( { $interner_ident: ident, $x: ty, $datastore_ident: ident, $y: ty } )+ ) => {
-        #[repr(C)]
-        #[derive(Clone, Debug, Default, Deserialize, Serialize)]
-        pub struct InterningMemoryReport {
-            $(
-                pub $interner_ident: usize,
-                pub $datastore_ident: usize,
-            )+
-        }
-
-        impl ::std::ops::AddAssign for InterningMemoryReport {
-            fn add_assign(&mut self, other: InterningMemoryReport) {
-                $(
-                    self.$interner_ident += other.$interner_ident;
-                    self.$datastore_ident += other.$datastore_ident;
-                )+
-            }
-        }
-    }
-}
-
-enumerate_interners!(declare_interning_memory_report);
-
 /// Collection of heap sizes, in bytes.
-/// cbindgen:derive-eq=false
 #[repr(C)]
 #[derive(Clone, Debug, Default, Deserialize, Serialize)]
 pub struct MemoryReport {
     //
     // CPU Memory.
     //
+    pub primitive_stores: usize,
     pub clip_stores: usize,
     pub gpu_cache_metadata: usize,
     pub gpu_cache_cpu_mirror: usize,
     pub render_tasks: usize,
     pub hit_testers: usize,
     pub fonts: usize,
     pub images: usize,
     pub rasterized_blobs: usize,
     pub shader_cache: usize,
-    pub interning: InterningMemoryReport,
+    pub data_stores: usize,
+    pub interners: usize,
 
     //
     // GPU memory.
     //
     pub gpu_cache_textures: usize,
     pub vertex_data_textures: usize,
     pub render_target_textures: usize,
     pub texture_cache_textures: usize,
     pub depth_target_textures: usize,
     pub swap_chain: usize,
 }
 
 impl ::std::ops::AddAssign for MemoryReport {
     fn add_assign(&mut self, other: MemoryReport) {
+        self.primitive_stores += other.primitive_stores;
         self.clip_stores += other.clip_stores;
         self.gpu_cache_metadata += other.gpu_cache_metadata;
         self.gpu_cache_cpu_mirror += other.gpu_cache_cpu_mirror;
         self.render_tasks += other.render_tasks;
         self.hit_testers += other.hit_testers;
         self.fonts += other.fonts;
         self.images += other.images;
         self.rasterized_blobs += other.rasterized_blobs;
         self.shader_cache += other.shader_cache;
-        self.interning += other.interning;
-
+        self.data_stores += other.data_stores;
+        self.interners += other.interners;
         self.gpu_cache_textures += other.gpu_cache_textures;
         self.vertex_data_textures += other.vertex_data_textures;
         self.render_target_textures += other.render_target_textures;
         self.texture_cache_textures += other.texture_cache_textures;
         self.depth_target_textures += other.depth_target_textures;
         self.swap_chain += other.swap_chain;
     }
 }
@@ -1005,17 +958,17 @@ impl RenderApiSender {
             payload_sender: self.payload_sender.clone(),
             namespace_id,
             next_id: Cell::new(ResourceId(0)),
         }
     }
 }
 
 bitflags! {
-    #[derive(Default, Deserialize, MallocSizeOf, Serialize)]
+    #[derive(Default, Deserialize, Serialize)]
     pub struct DebugFlags: u32 {
         /// Display the frame profiler on screen.
         const PROFILER_DBG          = 1 << 0;
         /// Display intermediate render targets on screen.
         const RENDER_TARGET_DBG     = 1 << 1;
         /// Display all texture cache pages on screen.
         const TEXTURE_CACHE_DBG     = 1 << 2;
         /// Display GPU timing results.
@@ -1331,17 +1284,17 @@ impl ZoomFactor {
 
     /// Get the zoom factor as an untyped float.
     pub fn get(&self) -> f32 {
         self.0
     }
 }
 
 #[repr(C)]
-#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash)]
+#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, Eq, Hash)]
 pub struct PropertyBindingId {
     namespace: IdNamespace,
     uid: u32,
 }
 
 impl PropertyBindingId {
     pub fn new(value: u64) -> Self {
         PropertyBindingId {
--- a/gfx/wr/webrender_api/src/color.rs
+++ b/gfx/wr/webrender_api/src/color.rs
@@ -34,17 +34,17 @@ impl PremultipliedColorF {
     }
 }
 
 /// Represents RGBA screen colors with floating point numbers.
 ///
 /// All components must be between 0.0 and 1.0.
 /// An alpha value of 1.0 is opaque while 0.0 is fully transparent.
 #[repr(C)]
-#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
+#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
 pub struct ColorF {
     pub r: f32,
     pub g: f32,
     pub b: f32,
     pub a: f32,
 }
 
 impl ColorF {
@@ -107,17 +107,17 @@ impl Hash for PremultipliedColorF {
         self.a.to_bits().hash(state);
     }
 }
 
 /// Represents RGBA screen colors with one byte per channel.
 ///
 /// If the alpha value `a` is 255 the color is opaque.
 #[repr(C)]
-#[derive(Clone, Copy, Hash, Eq, Debug, Deserialize, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
+#[derive(Clone, Copy, Hash, Eq, Debug, Deserialize, PartialEq, PartialOrd, Ord, Serialize)]
 pub struct ColorU {
     pub r: u8,
     pub g: u8,
     pub b: u8,
     pub a: u8,
 }
 
 impl ColorU {
--- a/gfx/wr/webrender_api/src/display_item.rs
+++ b/gfx/wr/webrender_api/src/display_item.rs
@@ -242,39 +242,39 @@ pub struct RectangleDisplayItem {
 pub struct LineDisplayItem {
     pub orientation: LineOrientation, // toggles whether above values are interpreted as x/y values
     pub wavy_line_thickness: f32,
     pub color: ColorF,
     pub style: LineStyle,
 }
 
 #[repr(u8)]
-#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash)]
+#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, Eq, Hash)]
 pub enum LineOrientation {
     Vertical,
     Horizontal,
 }
 
 #[repr(u8)]
-#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash)]
+#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, Eq, Hash)]
 pub enum LineStyle {
     Solid,
     Dotted,
     Dashed,
     Wavy,
 }
 
 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
 pub struct TextDisplayItem {
     pub font_key: FontInstanceKey,
     pub color: ColorF,
     pub glyph_options: Option<GlyphOptions>,
 } // IMPLICIT: glyphs: Vec<GlyphInstance>
 
-#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
+#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
 pub struct NormalBorder {
     pub left: BorderSide,
     pub right: BorderSide,
     pub top: BorderSide,
     pub bottom: BorderSide,
     pub radius: BorderRadius,
     /// Whether to apply anti-aliasing on the border corners.
     ///
@@ -323,17 +323,17 @@ impl NormalBorder {
         normalize_side(&mut self.left, widths.left);
         normalize_side(&mut self.right, widths.right);
         normalize_side(&mut self.top, widths.top);
         normalize_side(&mut self.bottom, widths.bottom);
     }
 }
 
 #[repr(u32)]
-#[derive(Debug, Copy, Clone, MallocSizeOf, PartialEq, Serialize, Deserialize, Eq, Hash)]
+#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize, Eq, Hash)]
 pub enum RepeatMode {
     Stretch,
     Repeat,
     Round,
     Space,
 }
 
 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
@@ -396,33 +396,33 @@ pub struct BorderDisplayItem {
 #[repr(C)]
 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
 pub enum BorderRadiusKind {
     Uniform,
     NonUniform,
 }
 
 #[repr(C)]
-#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
+#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
 pub struct BorderRadius {
     pub top_left: LayoutSize,
     pub top_right: LayoutSize,
     pub bottom_left: LayoutSize,
     pub bottom_right: LayoutSize,
 }
 
 #[repr(C)]
-#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
+#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
 pub struct BorderSide {
     pub color: ColorF,
     pub style: BorderStyle,
 }
 
 #[repr(u32)]
-#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Hash, Eq)]
+#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, Hash, Eq)]
 pub enum BorderStyle {
     None = 0,
     Solid = 1,
     Double = 2,
     Dotted = 3,
     Dashed = 4,
     Hidden = 5,
     Groove = 6,
@@ -433,17 +433,17 @@ pub enum BorderStyle {
 
 impl BorderStyle {
     pub fn is_hidden(&self) -> bool {
         *self == BorderStyle::Hidden || *self == BorderStyle::None
     }
 }
 
 #[repr(u32)]
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
+#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
 pub enum BoxShadowClipMode {
     Outset = 0,
     Inset = 1,
 }
 
 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
 pub struct BoxShadowDisplayItem {
     pub box_bounds: LayoutRect,
@@ -459,17 +459,17 @@ pub struct BoxShadowDisplayItem {
 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
 pub struct Shadow {
     pub offset: LayoutVector2D,
     pub color: ColorF,
     pub blur_radius: f32,
 }
 
 #[repr(u8)]
-#[derive(Debug, Copy, Clone, Hash, Eq, MallocSizeOf, PartialEq, Serialize, Deserialize, Ord, PartialOrd)]
+#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Ord, PartialOrd)]
 pub enum ExtendMode {
     Clamp,
     Repeat,
 }
 
 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
 pub struct Gradient {
     pub start_point: LayoutPoint,
@@ -480,17 +480,17 @@ pub struct Gradient {
 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
 pub struct GradientDisplayItem {
     pub gradient: Gradient,
     pub tile_size: LayoutSize,
     pub tile_spacing: LayoutSize,
 }
 
 #[repr(C)]
-#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
+#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
 pub struct GradientStop {
     pub offset: f32,
     pub color: ColorF,
 }
 
 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
 pub struct RadialGradient {
     pub center: LayoutPoint,
@@ -654,39 +654,39 @@ pub struct ImageDisplayItem {
     pub stretch_size: LayoutSize,
     pub tile_spacing: LayoutSize,
     pub image_rendering: ImageRendering,
     pub alpha_type: AlphaType,
     pub color: ColorF,
 }
 
 #[repr(u32)]
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
+#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
 pub enum ImageRendering {
     Auto = 0,
     CrispEdges = 1,
     Pixelated = 2,
 }
 
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
+#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
 pub enum AlphaType {
     Alpha = 0,
     PremultipliedAlpha = 1,
 }
 
 #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
 pub struct YuvImageDisplayItem {
     pub yuv_data: YuvData,
     pub color_depth: ColorDepth,
     pub color_space: YuvColorSpace,
     pub image_rendering: ImageRendering,
 }
 
 #[repr(u32)]
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
+#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
 pub enum YuvColorSpace {
     Rec601 = 0,
     Rec709 = 1,
 }
 
 #[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
 pub enum YuvData {
     NV12(ImageKey, ImageKey), // (Y channel, CbCr interleaved channel)
@@ -699,17 +699,17 @@ impl YuvData {
         match *self {
             YuvData::NV12(..) => YuvFormat::NV12,
             YuvData::PlanarYCbCr(..) => YuvFormat::PlanarYCbCr,
             YuvData::InterleavedYCbCr(..) => YuvFormat::InterleavedYCbCr,
         }
     }
 }
 
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
+#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
 pub enum YuvFormat {
     NV12 = 0,
     PlanarYCbCr = 1,
     InterleavedYCbCr = 2,
 }
 
 impl YuvFormat {
     pub fn get_plane_num(&self) -> usize {
@@ -736,17 +736,17 @@ impl ImageMask {
             None
         } else {
             Some(self.rect)
         }
     }
 }
 
 #[repr(C)]
-#[derive(Copy, Clone, Debug, MallocSizeOf, PartialEq, Serialize, Deserialize, Eq, Hash)]
+#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
 pub enum ClipMode {
     Clip,    // Pixels inside the region are visible.
     ClipOut, // Pixels outside the region are visible.
 }
 
 impl Not for ClipMode {
     type Output = ClipMode;
 
--- a/gfx/wr/webrender_api/src/font.rs
+++ b/gfx/wr/webrender_api/src/font.rs
@@ -66,17 +66,17 @@ pub struct GlyphDimensions {
     pub left: i32,
     pub top: i32,
     pub width: i32,
     pub height: i32,
     pub advance: f32,
 }
 
 #[repr(C)]
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, Ord, PartialOrd)]
+#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, Ord, PartialOrd)]
 pub struct FontKey(pub IdNamespace, pub u32);
 
 impl FontKey {
     pub fn new(namespace: IdNamespace, key: u32) -> FontKey {
         FontKey(namespace, key)
     }
 }
 
@@ -89,17 +89,17 @@ impl FontKey {
 /// intended to distinguish this data from instance-specific data.
 #[derive(Clone)]
 pub enum FontTemplate {
     Raw(Arc<Vec<u8>>, u32),
     Native(NativeFontHandle),
 }
 
 #[repr(u32)]
-#[derive(Debug, Copy, Clone, Hash, Eq, MallocSizeOf, PartialEq, Serialize, Deserialize, Ord, PartialOrd)]
+#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Ord, PartialOrd)]
 pub enum FontRenderMode {
     Mono = 0,
     Alpha,
     Subpixel,
 }
 
 impl FontRenderMode {
     // Combine two font render modes such that the lesser amount of AA limits the AA of the result.
@@ -107,17 +107,17 @@ impl FontRenderMode {
         match (self, other) {
             (FontRenderMode::Subpixel, _) | (_, FontRenderMode::Mono) => other,
             _ => self,
         }
     }
 }
 
 #[repr(C)]
-#[derive(Clone, Copy, Debug, MallocSizeOf, PartialOrd, Deserialize, Serialize)]
+#[derive(Clone, Copy, Debug, PartialOrd, Deserialize, Serialize)]
 pub struct FontVariation {
     pub tag: u32,
     pub value: f32,
 }
 
 impl Ord for FontVariation {
     fn cmp(&self, other: &FontVariation) -> Ordering {
         self.tag.cmp(&other.tag)
@@ -154,17 +154,17 @@ impl Default for GlyphOptions {
             render_mode: FontRenderMode::Subpixel,
             flags: FontInstanceFlags::empty(),
         }
     }
 }
 
 bitflags! {
     #[repr(C)]
-    #[derive(Deserialize, MallocSizeOf, Serialize)]
+    #[derive(Deserialize, Serialize)]
     pub struct FontInstanceFlags: u32 {
         // Common flags
         const SYNTHETIC_BOLD    = 1 << 1;
         const EMBEDDED_BITMAPS  = 1 << 2;
         const SUBPIXEL_BGR      = 1 << 3;
         const TRANSPOSE         = 1 << 4;
         const FLIP_X            = 1 << 5;
         const FLIP_Y            = 1 << 6;
@@ -199,17 +199,17 @@ impl Default for FontInstanceFlags {
     #[cfg(not(any(target_os = "macos", target_os = "windows")))]
     fn default() -> FontInstanceFlags {
         FontInstanceFlags::SUBPIXEL_POSITION
     }
 }
 
 
 #[repr(C)]
-#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
+#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize)]
 pub struct SyntheticItalics {
     // Angle in degrees (-90..90) for synthetic italics in 8.8 fixed-point.
     pub angle: i16,
 }
 
 impl SyntheticItalics {
     pub const ANGLE_SCALE: f32 = 256.0;
 
@@ -268,17 +268,17 @@ impl Default for FontInstanceOptions {
             bg_color: ColorU::new(0, 0, 0, 0),
             synthetic_italics: SyntheticItalics::disabled(),
         }
     }
 }
 
 #[cfg(target_os = "windows")]
 #[repr(C)]
-#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
+#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize)]
 pub struct FontInstancePlatformOptions {
     pub gamma: u16, // percent
     pub contrast: u16, // percent
 }
 
 #[cfg(target_os = "windows")]
 impl Default for FontInstancePlatformOptions {
     fn default() -> FontInstancePlatformOptions {
@@ -286,54 +286,54 @@ impl Default for FontInstancePlatformOpt
             gamma: 180, // Default DWrite gamma
             contrast: 100,
         }
     }
 }
 
 #[cfg(target_os = "macos")]
 #[repr(C)]
-#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
+#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize)]
 pub struct FontInstancePlatformOptions {
     pub unused: u32,
 }
 
 #[cfg(target_os = "macos")]
 impl Default for FontInstancePlatformOptions {
     fn default() -> FontInstancePlatformOptions {
         FontInstancePlatformOptions {
             unused: 0,
         }
     }
 }
 
 #[cfg(not(any(target_os = "macos", target_os = "windows")))]
 #[repr(u8)]
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
+#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize)]
 pub enum FontLCDFilter {
     None,
     Default,
     Light,
     Legacy,
 }
 
 #[cfg(not(any(target_os = "macos", target_os = "windows")))]
 #[repr(u8)]
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
+#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize)]
 pub enum FontHinting {
     None,
     Mono,
     Light,
     Normal,
     LCD,
 }
 
 #[cfg(not(any(target_os = "macos", target_os = "windows")))]
 #[repr(C)]
-#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)]
+#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize)]
 pub struct FontInstancePlatformOptions {
     pub lcd_filter: FontLCDFilter,
     pub hinting: FontHinting,
 }
 
 #[cfg(not(any(target_os = "macos", target_os = "windows")))]
 impl Default for FontInstancePlatformOptions {
     fn default() -> FontInstancePlatformOptions {
@@ -365,17 +365,17 @@ pub struct FontInstanceData {
     pub options: Option<FontInstanceOptions>,
     pub platform_options: Option<FontInstancePlatformOptions>,
     pub variations: Vec<FontVariation>,
 }
 
 pub type GlyphIndex = u32;
 
 #[repr(C)]
-#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
+#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
 pub struct GlyphInstance {
     pub index: GlyphIndex,
     pub point: LayoutPoint,
 }
 
 impl Eq for GlyphInstance {}
 
 impl Hash for GlyphInstance {
--- a/gfx/wr/webrender_api/src/image.rs
+++ b/gfx/wr/webrender_api/src/image.rs
@@ -12,17 +12,17 @@ use {DeviceIntPoint, DeviceIntRect, Devi
 use {BlobDirtyRect, IdNamespace, TileOffset, TileSize};
 use euclid::{size2, TypedRect, num::Zero};
 use std::ops::{Add, Sub};
 
 /// An opaque identifier describing an image registered with WebRender.
 /// This is used as a handle to reference images, and is used as the
 /// hash map key for the actual image storage in the `ResourceCache`.
 #[repr(C)]
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
+#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
 pub struct ImageKey(pub IdNamespace, pub u32);
 
 impl ImageKey {
     /// Placeholder Image key, used to represent None.
     pub const DUMMY: Self = ImageKey(IdNamespace(0), 0);
 
     /// Mints a new ImageKey. The given ID must be unique.
     pub fn new(namespace: IdNamespace, key: u32) -> Self {
@@ -132,17 +132,17 @@ impl ImageFormat {
             ImageFormat::RGBAI32 => 16,
             ImageFormat::RGBA8 => 4,
         }
     }
 }
 
 /// Specifies the color depth of an image. Currently only used for YUV images.
 #[repr(u8)]
-#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
+#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
 pub enum ColorDepth {
     /// 8 bits image (most common)
     Color8,
     /// 10 bits image
     Color10,
     /// 12 bits image
     Color12,
     /// 16 bits image
--- a/gfx/wr/webrender_api/src/lib.rs
+++ b/gfx/wr/webrender_api/src/lib.rs
@@ -25,25 +25,21 @@ extern crate core;
 extern crate core_foundation;
 #[cfg(target_os = "macos")]
 extern crate core_graphics;
 #[cfg(target_os = "windows")]
 extern crate dwrote;
 pub extern crate euclid;
 #[cfg(feature = "ipc")]
 extern crate ipc_channel;
-#[macro_use]
-extern crate malloc_size_of_derive;
 extern crate serde;
 #[macro_use]
 extern crate serde_derive;
 extern crate time;
 
-extern crate wr_malloc_size_of;
-use wr_malloc_size_of as malloc_size_of;
 
 mod api;
 pub mod channel;
 mod color;
 mod display_item;
 mod display_list;
 mod font;
 mod gradient_builder;
--- a/gfx/wr/webrender_api/src/units.rs
+++ b/gfx/wr/webrender_api/src/units.rs
@@ -60,33 +60,33 @@ pub type RasterIntSize = TypedSize2D<i32
 pub type RasterRect = TypedRect<f32, RasterPixel>;
 pub type RasterPoint = TypedPoint2D<f32, RasterPixel>;
 pub type RasterSize = TypedSize2D<f32, RasterPixel>;
 pub type RasterPoint3D = TypedPoint3D<f32, RasterPixel>;
 pub type RasterVector2D = TypedVector2D<f32, RasterPixel>;
 pub type RasterVector3D = TypedVector3D<f32, RasterPixel>;
 
 /// Geometry in a stacking context's local coordinate space (logical pixels).
-#[derive(Hash, Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Ord, PartialOrd, Deserialize, Serialize)]
+#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Deserialize, Serialize)]
 pub struct LayoutPixel;
 
 pub type LayoutRect = TypedRect<f32, LayoutPixel>;
 pub type LayoutPoint = TypedPoint2D<f32, LayoutPixel>;
 pub type LayoutPoint3D = TypedPoint3D<f32, LayoutPixel>;
 pub type LayoutVector2D = TypedVector2D<f32, LayoutPixel>;
 pub type LayoutVector3D = TypedVector3D<f32, LayoutPixel>;
 pub type LayoutSize = TypedSize2D<f32, LayoutPixel>;
 pub type LayoutSideOffsets = TypedSideOffsets2D<f32, LayoutPixel>;
 
 pub type LayoutIntRect = TypedRect<i32, LayoutPixel>;
 pub type LayoutIntPoint = TypedPoint2D<i32, LayoutPixel>;
 pub type LayoutIntSize = TypedSize2D<i32, LayoutPixel>;
 
 /// Geometry in the document's coordinate space (logical pixels).
-#[derive(Hash, Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Ord, PartialOrd)]
+#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
 pub struct WorldPixel;
 
 pub type WorldRect = TypedRect<f32, WorldPixel>;
 pub type WorldPoint = TypedPoint2D<f32, WorldPixel>;
 pub type WorldSize = TypedSize2D<f32, WorldPixel>;
 pub type WorldPoint3D = TypedPoint3D<f32, WorldPixel>;
 pub type WorldVector2D = TypedVector2D<f32, WorldPixel>;
 pub type WorldVector3D = TypedVector3D<f32, WorldPixel>;
deleted file mode 100644
--- a/gfx/wr/wr_malloc_size_of/Cargo.toml
+++ /dev/null
@@ -1,12 +0,0 @@
-[package]
-name = "wr_malloc_size_of"
-version = "0.0.1"
-license = "MIT/Apache-2.0"
-publish = false
-
-[lib]
-path = "lib.rs"
-
-[dependencies]
-app_units = "0.7"
-euclid = "0.19"
deleted file mode 100644
--- a/gfx/wr/wr_malloc_size_of/LICENSE-APACHE
+++ /dev/null
@@ -1,201 +0,0 @@
-                              Apache License
-                        Version 2.0, January 2004
-                     http://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
-   "License" shall mean the terms and conditions for use, reproduction,
-   and distribution as defined by Sections 1 through 9 of this document.
-
-   "Licensor" shall mean the copyright owner or entity authorized by
-   the copyright owner that is granting the License.
-
-   "Legal Entity" shall mean the union of the acting entity and all
-   other entities that control, are controlled by, or are under common
-   control with that entity. For the purposes of this definition,
-   "control" means (i) the power, direct or indirect, to cause the
-   direction or management of such entity, whether by contract or
-   otherwise, or (ii) ownership of fifty percent (50%) or more of the
-   outstanding shares, or (iii) beneficial ownership of such entity.
-
-   "You" (or "Your") shall mean an individual or Legal Entity
-   exercising permissions granted by this License.
-
-   "Source" form shall mean the preferred form for making modifications,
-   including but not limited to software source code, documentation
-   source, and configuration files.
-
-   "Object" form shall mean any form resulting from mechanical
-   transformation or translation of a Source form, including but
-   not limited to compiled object code, generated documentation,
-   and conversions to other media types.
-
-   "Work" shall mean the work of authorship, whether in Source or
-   Object form, made available under the License, as indicated by a
-   copyright notice that is included in or attached to the work
-   (an example is provided in the Appendix below).
-
-   "Derivative Works" shall mean any work, whether in Source or Object
-   form, that is based on (or derived from) the Work and for which the
-   editorial revisions, annotations, elaborations, or other modifications
-   represent, as a whole, an original work of authorship. For the purposes
-   of this License, Derivative Works shall not include works that remain
-   separable from, or merely link (or bind by name) to the interfaces of,
-   the Work and Derivative Works thereof.
-
-   "Contribution" shall mean any work of authorship, including
-   the original version of the Work and any modifications or additions
-   to that Work or Derivative Works thereof, that is intentionally
-   submitted to Licensor for inclusion in the Work by the copyright owner
-   or by an individual or Legal Entity authorized to submit on behalf of
-   the copyright owner. For the purposes of this definition, "submitted"
-   means any form of electronic, verbal, or written communication sent
-   to the Licensor or its representatives, including but not limited to
-   communication on electronic mailing lists, source code control systems,
-   and issue tracking systems that are managed by, or on behalf of, the
-   Licensor for the purpose of discussing and improving the Work, but
-   excluding communication that is conspicuously marked or otherwise
-   designated in writing by the copyright owner as "Not a Contribution."
-
-   "Contributor" shall mean Licensor and any individual or Legal Entity
-   on behalf of whom a Contribution has been received by Licensor and
-   subsequently incorporated within the Work.
-
-2. Grant of Copyright License. Subject to the terms and conditions of
-   this License, each Contributor hereby grants to You a perpetual,
-   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-   copyright license to reproduce, prepare Derivative Works of,
-   publicly display, publicly perform, sublicense, and distribute the
-   Work and such Derivative Works in Source or Object form.
-
-3. Grant of Patent License. Subject to the terms and conditions of
-   this License, each Contributor hereby grants to You a perpetual,
-   worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-   (except as stated in this section) patent license to make, have made,
-   use, offer to sell, sell, import, and otherwise transfer the Work,
-   where such license applies only to those patent claims licensable
-   by such Contributor that are necessarily infringed by their
-   Contribution(s) alone or by combination of their Contribution(s)
-   with the Work to which such Contribution(s) was submitted. If You
-   institute patent litigation against any entity (including a
-   cross-claim or counterclaim in a lawsuit) alleging that the Work
-   or a Contribution incorporated within the Work constitutes direct
-   or contributory patent infringement, then any patent licenses
-   granted to You under this License for that Work shall terminate
-   as of the date such litigation is filed.
-
-4. Redistribution. You may reproduce and distribute copies of the
-   Work or Derivative Works thereof in any medium, with or without
-   modifications, and in Source or Object form, provided that You
-   meet the following conditions:
-
-   (a) You must give any other recipients of the Work or
-       Derivative Works a copy of this License; and
-
-   (b) You must cause any modified files to carry prominent notices
-       stating that You changed the files; and
-
-   (c) You must retain, in the Source form of any Derivative Works
-       that You distribute, all copyright, patent, trademark, and
-       attribution notices from the Source form of the Work,
-       excluding those notices that do not pertain to any part of
-       the Derivative Works; and
-
-   (d) If the Work includes a "NOTICE" text file as part of its
-       distribution, then any Derivative Works that You distribute must
-       include a readable copy of the attribution notices contained
-       within such NOTICE file, excluding those notices that do not
-       pertain to any part of the Derivative Works, in at least one
-       of the following places: within a NOTICE text file distributed
-       as part of the Derivative Works; within the Source form or
-       documentation, if provided along with the Derivative Works; or,
-       within a display generated by the Derivative Works, if and
-       wherever such third-party notices normally appear. The contents
-       of the NOTICE file are for informational purposes only and
-       do not modify the License. You may add Your own attribution
-       notices within Derivative Works that You distribute, alongside
-       or as an addendum to the NOTICE text from the Work, provided
-       that such additional attribution notices cannot be construed
-       as modifying the License.
-
-   You may add Your own copyright statement to Your modifications and
-   may provide additional or different license terms and conditions
-   for use, reproduction, or distribution of Your modifications, or
-   for any such Derivative Works as a whole, provided Your use,
-   reproduction, and distribution of the Work otherwise complies with
-   the conditions stated in this License.
-
-5. Submission of Contributions. Unless You explicitly state otherwise,
-   any Contribution intentionally submitted for inclusion in the Work
-   by You to the Licensor shall be under the terms and conditions of
-   this License, without any additional terms or conditions.
-   Notwithstanding the above, nothing herein shall supersede or modify
-   the terms of any separate license agreement you may have executed
-   with Licensor regarding such Contributions.
-
-6. Trademarks. This License does not grant permission to use the trade
-   names, trademarks, service marks, or product names of the Licensor,
-   except as required for reasonable and customary use in describing the
-   origin of the Work and reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty. Unless required by applicable law or
-   agreed to in writing, Licensor provides the Work (and each
-   Contributor provides its Contributions) on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-   implied, including, without limitation, any warranties or conditions
-   of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-   PARTICULAR PURPOSE. You are solely responsible for determining the
-   appropriateness of using or redistributing the Work and assume any
-   risks associated with Your exercise of permissions under this License.
-
-8. Limitation of Liability. In no event and under no legal theory,
-   whether in tort (including negligence), contract, or otherwise,
-   unless required by applicable law (such as deliberate and grossly
-   negligent acts) or agreed to in writing, shall any Contributor be
-   liable to You for damages, including any direct, indirect, special,
-   incidental, or consequential damages of any character arising as a
-   result of this License or out of the use or inability to use the
-   Work (including but not limited to damages for loss of goodwill,
-   work stoppage, computer failure or malfunction, or any and all
-   other commercial damages or losses), even if such Contributor
-   has been advised of the possibility of such damages.
-
-9. Accepting Warranty or Additional Liability. While redistributing
-   the Work or Derivative Works thereof, You may choose to offer,
-   and charge a fee for, acceptance of support, warranty, indemnity,
-   or other liability obligations and/or rights consistent with this
-   License. However, in accepting such obligations, You may act only
-   on Your own behalf and on Your sole responsibility, not on behalf
-   of any other Contributor, and only if You agree to indemnify,
-   defend, and hold each Contributor harmless for any liability
-   incurred by, or claims asserted against, such Contributor by reason
-   of your accepting any such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Apache License to your work.
-
-   To apply the Apache License to your work, attach the following
-   boilerplate notice, with the fields enclosed by brackets "[]"
-   replaced with your own identifying information. (Don't include
-   the brackets!)  The text should be enclosed in the appropriate
-   comment syntax for the file format. We also recommend that a
-   file or class name and description of purpose be included on the
-   same "printed page" as the copyright notice for easier
-   identification within third-party archives.
-
-Copyright [yyyy] [name of copyright owner]
-
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
-	http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
deleted file mode 100644
--- a/gfx/wr/wr_malloc_size_of/LICENSE-MIT
+++ /dev/null
@@ -1,23 +0,0 @@
-Permission is hereby granted, free of charge, to any
-person obtaining a copy of this software and associated
-documentation files (the "Software"), to deal in the
-Software without restriction, including without
-limitation the rights to use, copy, modify, merge,
-publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software
-is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice
-shall be included in all copies or substantial portions
-of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
-ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
-TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
-SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
-IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
deleted file mode 100644
--- a/gfx/wr/wr_malloc_size_of/lib.rs
+++ /dev/null
@@ -1,435 +0,0 @@
-// Copyright 2016-2017 The Servo Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! A reduced fork of Firefox's malloc_size_of crate, for bundling with WebRender.
-
-extern crate app_units;
-extern crate euclid;
-
-use std::hash::{BuildHasher, Hash};
-use std::mem::size_of;
-use std::ops::Range;
-use std::os::raw::c_void;
-
-/// A C function that takes a pointer to a heap allocation and returns its size.
-type VoidPtrToSizeFn = unsafe extern "C" fn(ptr: *const c_void) -> usize;
-
-/// Operations used when measuring heap usage of data structures.
-pub struct MallocSizeOfOps {
-    /// A function that returns the size of a heap allocation.
-    pub size_of_op: VoidPtrToSizeFn,
-
-    /// Like `size_of_op`, but can take an interior pointer. Optional because
-    /// not all allocators support this operation. If it's not provided, some
-    /// memory measurements will actually be computed estimates rather than
-    /// real and accurate measurements.
-    pub enclosing_size_of_op: Option<VoidPtrToSizeFn>,
-}
-
-impl MallocSizeOfOps {
-    pub fn new(
-        size_of: VoidPtrToSizeFn,
-        malloc_enclosing_size_of: Option<VoidPtrToSizeFn>,
-    ) -> Self {
-        MallocSizeOfOps {
-            size_of_op: size_of,
-            enclosing_size_of_op: malloc_enclosing_size_of,
-        }
-    }
-
-    /// Check if an allocation is empty. This relies on knowledge of how Rust
-    /// handles empty allocations, which may change in the future.
-    fn is_empty<T: ?Sized>(ptr: *const T) -> bool {
-        // The correct condition is this:
-        //   `ptr as usize <= ::std::mem::align_of::<T>()`
-        // But we can't call align_of() on a ?Sized T. So we approximate it
-        // with the following. 256 is large enough that it should always be
-        // larger than the required alignment, but small enough that it is
-        // always in the first page of memory and therefore not a legitimate
-        // address.
-        return ptr as *const usize as usize <= 256;
-    }
-
-    /// Call `size_of_op` on `ptr`, first checking that the allocation isn't
-    /// empty, because some types (such as `Vec`) utilize empty allocations.
-    pub unsafe fn malloc_size_of<T: ?Sized>(&self, ptr: *const T) -> usize {
-        if MallocSizeOfOps::is_empty(ptr) {
-            0
-        } else {
-            (self.size_of_op)(ptr as *const c_void)
-        }
-    }
-
-    /// Is an `enclosing_size_of_op` available?
-    pub fn has_malloc_enclosing_size_of(&self) -> bool {
-        self.enclosing_size_of_op.is_some()
-    }
-
-    /// Call `enclosing_size_of_op`, which must be available, on `ptr`, which
-    /// must not be empty.
-    pub unsafe fn malloc_enclosing_size_of<T>(&self, ptr: *const T) -> usize {
-        assert!(!MallocSizeOfOps::is_empty(ptr));
-        (self.enclosing_size_of_op.unwrap())(ptr as *const c_void)
-    }
-}
-
-/// Trait for measuring the "deep" heap usage of a data structure. This is the
-/// most commonly-used of the traits.
-pub trait MallocSizeOf {
-    /// Measure the heap usage of all descendant heap-allocated structures, but
-    /// not the space taken up by the value itself.
-    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize;
-}
-
-/// Trait for measuring the "shallow" heap usage of a container.
-pub trait MallocShallowSizeOf {
-    /// Measure the heap usage of immediate heap-allocated descendant
-    /// structures, but not the space taken up by the value itself. Anything
-    /// beyond the immediate descendants must be measured separately, using
-    /// iteration.
-    fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize;
-}
-
-impl MallocSizeOf for String {
-    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
-        unsafe { ops.malloc_size_of(self.as_ptr()) }
-    }
-}
-
-impl<T: ?Sized> MallocShallowSizeOf for Box<T> {
-    fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
-        unsafe { ops.malloc_size_of(&**self) }
-    }
-}
-
-impl<T: MallocSizeOf + ?Sized> MallocSizeOf for Box<T> {
-    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
-        self.shallow_size_of(ops) + (**self).size_of(ops)
-    }
-}
-
-impl MallocSizeOf for () {
-    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
-        0
-    }
-}
-
-impl<T1, T2> MallocSizeOf for (T1, T2)
-where
-    T1: MallocSizeOf,
-    T2: MallocSizeOf,
-{
-    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
-        self.0.size_of(ops) + self.1.size_of(ops)
-    }
-}
-
-impl<T1, T2, T3> MallocSizeOf for (T1, T2, T3)
-where
-    T1: MallocSizeOf,
-    T2: MallocSizeOf,
-    T3: MallocSizeOf,
-{
-    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
-        self.0.size_of(ops) + self.1.size_of(ops) + self.2.size_of(ops)
-    }
-}
-
-impl<T1, T2, T3, T4> MallocSizeOf for (T1, T2, T3, T4)
-where
-    T1: MallocSizeOf,
-    T2: MallocSizeOf,
-    T3: MallocSizeOf,
-    T4: MallocSizeOf,
-{
-    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
-        self.0.size_of(ops) + self.1.size_of(ops) + self.2.size_of(ops) + self.3.size_of(ops)
-    }
-}
-
-impl<T: MallocSizeOf> MallocSizeOf for Option<T> {
-    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
-        if let Some(val) = self.as_ref() {
-            val.size_of(ops)
-        } else {
-            0
-        }
-    }
-}
-
-impl<T: MallocSizeOf, E: MallocSizeOf> MallocSizeOf for Result<T, E> {
-    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
-        match *self {
-            Ok(ref x) => x.size_of(ops),
-            Err(ref e) => e.size_of(ops),
-        }
-    }
-}
-
-impl<T: MallocSizeOf + Copy> MallocSizeOf for std::cell::Cell<T> {
-    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
-        self.get().size_of(ops)
-    }
-}
-
-impl<T: MallocSizeOf> MallocSizeOf for std::cell::RefCell<T> {
-    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
-        self.borrow().size_of(ops)
-    }
-}
-
-impl<'a, B: ?Sized + ToOwned> MallocSizeOf for std::borrow::Cow<'a, B>
-where
-    B::Owned: MallocSizeOf,
-{
-    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
-        match *self {
-            std::borrow::Cow::Borrowed(_) => 0,
-            std::borrow::Cow::Owned(ref b) => b.size_of(ops),
-        }
-    }
-}
-
-impl<T: MallocSizeOf> MallocSizeOf for [T] {
-    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
-        let mut n = 0;
-        for elem in self.iter() {
-            n += elem.size_of(ops);
-        }
-        n
-    }
-}
-
-impl<T> MallocShallowSizeOf for Vec<T> {
-    fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
-        unsafe { ops.malloc_size_of(self.as_ptr()) }
-    }
-}
-
-impl<T: MallocSizeOf> MallocSizeOf for Vec<T> {
-    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
-        let mut n = self.shallow_size_of(ops);
-        for elem in self.iter() {
-            n += elem.size_of(ops);
-        }
-        n
-    }
-}
-
-macro_rules! malloc_size_of_hash_set {
-    ($ty:ty) => {
-        impl<T, S> MallocShallowSizeOf for $ty
-        where
-            T: Eq + Hash,
-            S: BuildHasher,
-        {
-            fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
-                if ops.has_malloc_enclosing_size_of() {
-                    // The first value from the iterator gives us an interior pointer.
-                    // `ops.malloc_enclosing_size_of()` then gives us the storage size.
-                    // This assumes that the `HashSet`'s contents (values and hashes)
-                    // are all stored in a single contiguous heap allocation.
-                    self.iter()
-                        .next()
-                        .map_or(0, |t| unsafe { ops.malloc_enclosing_size_of(t) })
-                } else {
-                    // An estimate.
-                    self.capacity() * (size_of::<T>() + size_of::<usize>())
-                }
-            }
-        }
-
-        impl<T, S> MallocSizeOf for $ty
-        where
-            T: Eq + Hash + MallocSizeOf,
-            S: BuildHasher,
-        {
-            fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
-                let mut n = self.shallow_size_of(ops);
-                for t in self.iter() {
-                    n += t.size_of(ops);
-                }
-                n
-            }
-        }
-    };
-}
-
-malloc_size_of_hash_set!(std::collections::HashSet<T, S>);
-
-macro_rules! malloc_size_of_hash_map {
-    ($ty:ty) => {
-        impl<K, V, S> MallocShallowSizeOf for $ty
-        where
-            K: Eq + Hash,
-            S: BuildHasher,
-        {
-            fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
-                // See the implementation for std::collections::HashSet for details.
-                if ops.has_malloc_enclosing_size_of() {
-                    self.values()
-                        .next()
-                        .map_or(0, |v| unsafe { ops.malloc_enclosing_size_of(v) })
-                } else {
-                    self.capacity() * (size_of::<V>() + size_of::<K>() + size_of::<usize>())
-                }
-            }
-        }
-
-        impl<K, V, S> MallocSizeOf for $ty
-        where
-            K: Eq + Hash + MallocSizeOf,
-            V: MallocSizeOf,
-            S: BuildHasher,
-        {
-            fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
-                let mut n = self.shallow_size_of(ops);
-                for (k, v) in self.iter() {
-                    n += k.size_of(ops);
-                    n += v.size_of(ops);
-                }
-                n
-            }
-        }
-    };
-}
-
-malloc_size_of_hash_map!(std::collections::HashMap<K, V, S>);
-
-// PhantomData is always 0.
-impl<T> MallocSizeOf for std::marker::PhantomData<T> {
-    fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
-        0
-    }
-}
-
-impl<T: MallocSizeOf, Unit> MallocSizeOf for euclid::Length<T, Unit> {
-    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
-        self.0.size_of(ops)
-    }
-}
-
-impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::TypedScale<T, Src, Dst> {
-    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
-        self.0.size_of(ops)
-    }
-}
-
-impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedPoint2D<T, U> {
-    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
-        self.x.size_of(ops) + self.y.size_of(ops)
-    }
-}
-
-impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedRect<T, U> {
-    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
-        self.origin.size_of(ops) + self.size.size_of(ops)
-    }
-}
-
-impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedSideOffsets2D<T, U> {
-    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
-        self.top.size_of(ops) +
-            self.right.size_of(ops) +
-            self.bottom.size_of(ops) +
-            self.left.size_of(ops)
-    }
-}
-
-impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedSize2D<T, U> {
-    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
-        self.width.size_of(ops) + self.height.size_of(ops)
-    }
-}
-
-impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::TypedTransform2D<T, Src, Dst> {
-    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
-        self.m11.size_of(ops) +
-            self.m12.size_of(ops) +
-            self.m21.size_of(ops) +
-            self.m22.size_of(ops) +
-            self.m31.size_of(ops) +
-            self.m32.size_of(ops)
-    }
-}
-
-impl<T: MallocSizeOf, Src, Dst> MallocSizeOf for euclid::TypedTransform3D<T, Src, Dst> {
-    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
-        self.m11.size_of(ops) +
-            self.m12.size_of(ops) +
-            self.m13.size_of(ops) +
-            self.m14.size_of(ops) +
-            self.m21.size_of(ops) +
-            self.m22.size_of(ops) +
-            self.m23.size_of(ops) +
-            self.m24.size_of(ops) +
-            self.m31.size_of(ops) +
-            self.m32.size_of(ops) +
-            self.m33.size_of(ops) +
-            self.m34.size_of(ops) +
-            self.m41.size_of(ops) +
-            self.m42.size_of(ops) +
-            self.m43.size_of(ops) +
-            self.m44.size_of(ops)
-    }
-}
-
-impl<T: MallocSizeOf, U> MallocSizeOf for euclid::TypedVector2D<T, U> {
-    fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
-        self.x.size_of(ops) + self.y.size_of(ops)
-    }
-}
-
-/// For use on types where size_of() returns 0.
-#[macro_export]
-macro_rules! malloc_size_of_is_0(
-    ($($ty:ty),+) => (
-        $(
-            impl $crate::MallocSizeOf for $ty {
-                #[inline(always)]
-                fn size_of(&self, _: &mut $crate::MallocSizeOfOps) -> usize {
-                    0
-                }
-            }
-        )+
-    );
-    ($($ty:ident<$($gen:ident),+>),+) => (
-        $(
-        impl<$($gen: $crate::MallocSizeOf),+> $crate::MallocSizeOf for $ty<$($gen),+> {
-            #[inline(always)]
-            fn size_of(&self, _: &mut $crate::MallocSizeOfOps) -> usize {
-                0
-            }
-        }
-        )+
-    );
-);
-
-malloc_size_of_is_0!(bool, char, str);
-malloc_size_of_is_0!(u8, u16, u32, u64, u128, usize);
-malloc_size_of_is_0!(i8, i16, i32, i64, i128, isize);
-malloc_size_of_is_0!(f32, f64);
-
-malloc_size_of_is_0!(std::sync::atomic::AtomicBool);
-malloc_size_of_is_0!(std::sync::atomic::AtomicIsize);
-malloc_size_of_is_0!(std::sync::atomic::AtomicUsize);
-
-malloc_size_of_is_0!(std::num::NonZeroUsize);
-malloc_size_of_is_0!(std::num::NonZeroU32);
-
-malloc_size_of_is_0!(std::time::Duration);
-malloc_size_of_is_0!(std::time::Instant);
-malloc_size_of_is_0!(std::time::SystemTime);
-
-malloc_size_of_is_0!(Range<u8>, Range<u16>, Range<u32>, Range<u64>, Range<usize>);
-malloc_size_of_is_0!(Range<i8>, Range<i16>, Range<i32>, Range<i64>, Range<isize>);
-malloc_size_of_is_0!(Range<f32>, Range<f64>);
-
-malloc_size_of_is_0!(app_units::Au);
--- a/servo/components/malloc_size_of/lib.rs
+++ b/servo/components/malloc_size_of/lib.rs
@@ -37,19 +37,16 @@
 //!   be measured, it should be measured via the `MallocUnconditionalSizeOf`
 //!   trait.
 //! - If an `Rc` or `Arc` should be measured only if it hasn't been seen
 //!   before, it should be measured via the `MallocConditionalSizeOf` trait.
 //! - Using universal function call syntax is a good idea when measuring boxed
 //!   fields in structs, because it makes it clear that the Box is being
 //!   measured as well as the thing it points to. E.g.
 //!   `<Box<_> as MallocSizeOf>::size_of(field, ops)`.
-//!
-//!   Note: WebRender has a reduced for of this crate, so that we can avoid
-//!   publishing this crate on crates.io.
 
 extern crate app_units;
 #[cfg(feature = "servo")]
 extern crate crossbeam_channel;
 extern crate cssparser;
 extern crate euclid;
 extern crate hashglobe;
 #[cfg(feature = "servo")]
new file mode 100644
--- /dev/null
+++ b/servo/components/malloc_size_of_derive/Cargo.toml
@@ -0,0 +1,15 @@
+[package]
+name = "malloc_size_of_derive"
+version = "0.0.1"
+authors = ["The Servo Project Developers"]
+license = "MIT/Apache-2.0"
+publish = false
+
+[lib]
+path = "lib.rs"
+proc-macro = true
+
+[dependencies]
+proc-macro2 = "0.4"
+syn = { version = "0.15", features = ["full"] }
+synstructure = "0.10"
rename from third_party/rust/malloc_size_of_derive/LICENSE-APACHE
rename to servo/components/malloc_size_of_derive/LICENSE-APACHE
rename from third_party/rust/malloc_size_of_derive/LICENSE-MIT
rename to servo/components/malloc_size_of_derive/LICENSE-MIT
rename from third_party/rust/malloc_size_of_derive/lib.rs
rename to servo/components/malloc_size_of_derive/lib.rs
--- a/servo/components/style/Cargo.toml
+++ b/servo/components/style/Cargo.toml
@@ -39,17 +39,17 @@ fxhash = "0.2"
 hashglobe = { path = "../hashglobe" }
 html5ever = {version = "0.22", optional = true}
 indexmap = "1.0"
 itertools = "0.7.6"
 itoa = "0.4"
 lazy_static = "1"
 log = "0.4"
 malloc_size_of = { path = "../malloc_size_of" }
-malloc_size_of_derive = "0.1"
+malloc_size_of_derive = { path = "../malloc_size_of_derive" }
 matches = "0.1"
 nsstring = {path = "../../../xpcom/rust/nsstring/", optional = true}
 num_cpus = {version = "1.1.0"}
 num-integer = "0.1"
 num-traits = "0.2"
 num-derive = "0.2"
 ordered-float = "1.0"
 owning_ref = "0.4"
--- a/servo/components/style_traits/Cargo.toml
+++ b/servo/components/style_traits/Cargo.toml
@@ -14,15 +14,15 @@ servo = ["serde", "servo_atoms", "csspar
 gecko = []
 
 [dependencies]
 app_units = "0.7"
 cssparser = "0.25"
 bitflags = "1.0"
 euclid = "0.19"
 malloc_size_of = { path = "../malloc_size_of" }
-malloc_size_of_derive = "0.1"
+malloc_size_of_derive = { path = "../malloc_size_of_derive" }
 selectors = { path = "../selectors" }
 serde = {version = "1.0", optional = true}
 webrender_api = {git = "https://github.com/servo/webrender", optional = true}
 servo_atoms = {path = "../atoms", optional = true}
 servo_arc = { path = "../servo_arc" }
 servo_url = { path = "../url", optional = true }
deleted file mode 100644
--- a/third_party/rust/malloc_size_of_derive/.cargo-checksum.json
+++ /dev/null
@@ -1,1 +0,0 @@
-{"files":{"Cargo.toml":"ca54d29c0cfac91471c60317233978b7e23f4d82537b3116431f681b44f98b33","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"c6f47e3c516f7dfc1b0eeaa999e557ec129cb0bbe2e70d712293d56af09141c3","lib.rs":"d0aec9f3ccc0a86d4d8979baa7b8c334e211878b12f1a3df9c6489b786894f03"},"package":"35adee9ed962cf7d07d62cb58bc45029f3227f5b5b86246caa8632f06c187bc3"}
\ No newline at end of file
deleted file mode 100644
--- a/third_party/rust/malloc_size_of_derive/Cargo.toml
+++ /dev/null
@@ -1,32 +0,0 @@
-# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
-#
-# When uploading crates to the registry Cargo will automatically
-# "normalize" Cargo.toml files for maximal compatibility
-# with all versions of Cargo and also rewrite `path` dependencies
-# to registry (e.g. crates.io) dependencies
-#
-# If you believe there's an error in this file please file an
-# issue against the rust-lang/cargo repository. If you're
-# editing this file be aware that the upstream Cargo.toml
-# will likely look very different (and much more reasonable)
-
-[package]
-name = "malloc_size_of_derive"
-version = "0.1.0"
-authors = ["The Servo Project Developers"]
-description = "Crate for Firefox memory reporting, not intended for external use"
-license = "MIT/Apache-2.0"
-repository = "https://github.com/bholley/malloc_size_of_derive"
-
-[lib]
-path = "lib.rs"
-proc-macro = true
-[dependencies.proc-macro2]
-version = "0.4"
-
-[dependencies.syn]
-version = "0.15"
-features = ["full"]
-
-[dependencies.synstructure]
-version = "0.10"
deleted file mode 100644
--- a/third_party/rust/malloc_size_of_derive/README.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# malloc_size_of_derive
-
-This crate is used for Firefox memory reporting. It's not intended for external
-use, but is published so that it can be used by WebRender, which can be built
-and used separately from Firefox.