From df0de42464e981e2bd124cc9dd910a9582c96dab Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Sat, 12 Jan 2019 19:21:56 +0000 Subject: [PATCH 1/9] Bug 1519454 - Put malloc_size_of_derive on crates.io, and add a reduced fork of malloc_size_of for WebRender. r=emilio Differential Revision: https://phabricator.services.mozilla.com/D16353 [wrupdater] From https://hg.mozilla.org/mozilla-central/rev/f3ef205b4f632c18d20eb83e7b5f6a0e3ca77b21 --- Cargo.lock | 35 +++ webrender/Cargo.toml | 2 + webrender_api/Cargo.toml | 2 + wr_malloc_size_of/Cargo.toml | 12 + wr_malloc_size_of/LICENSE-APACHE | 201 ++++++++++++++ wr_malloc_size_of/LICENSE-MIT | 23 ++ wr_malloc_size_of/lib.rs | 442 +++++++++++++++++++++++++++++++ 7 files changed, 717 insertions(+) create mode 100644 wr_malloc_size_of/Cargo.toml create mode 100644 wr_malloc_size_of/LICENSE-APACHE create mode 100644 wr_malloc_size_of/LICENSE-MIT create mode 100644 wr_malloc_size_of/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 22c42cb877..f445fdf90d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -757,6 +757,16 @@ 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" @@ -1320,6 +1330,17 @@ dependencies = [ "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" @@ -1553,6 +1574,7 @@ dependencies = [ "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)", @@ -1572,6 +1594,7 @@ dependencies = [ "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)", ] @@ -1602,10 +1625,12 @@ dependencies = [ "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]] @@ -1674,6 +1699,14 @@ dependencies = [ "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" @@ -1861,6 +1894,7 @@ dependencies = [ "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" @@ -1925,6 +1959,7 @@ dependencies = [ "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" diff --git a/webrender/Cargo.toml b/webrender/Cargo.toml index caf620bb7f..5d83ba28f1 100644 --- a/webrender/Cargo.toml +++ b/webrender/Cargo.toml @@ -34,6 +34,7 @@ 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" } @@ -47,6 +48,7 @@ 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] diff --git a/webrender_api/Cargo.toml b/webrender_api/Cargo.toml index db4063d984..be2d4109f4 100644 --- a/webrender_api/Cargo.toml +++ b/webrender_api/Cargo.toml @@ -19,10 +19,12 @@ 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" diff --git a/wr_malloc_size_of/Cargo.toml b/wr_malloc_size_of/Cargo.toml new file mode 100644 index 0000000000..48d1814997 --- /dev/null +++ b/wr_malloc_size_of/Cargo.toml @@ -0,0 +1,12 @@ +[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" diff --git a/wr_malloc_size_of/LICENSE-APACHE b/wr_malloc_size_of/LICENSE-APACHE new file mode 100644 index 0000000000..16fe87b06e --- /dev/null +++ b/wr_malloc_size_of/LICENSE-APACHE @@ -0,0 +1,201 @@ + 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. diff --git a/wr_malloc_size_of/LICENSE-MIT b/wr_malloc_size_of/LICENSE-MIT new file mode 100644 index 0000000000..31aa79387f --- /dev/null +++ b/wr_malloc_size_of/LICENSE-MIT @@ -0,0 +1,23 @@ +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. diff --git a/wr_malloc_size_of/lib.rs b/wr_malloc_size_of/lib.rs new file mode 100644 index 0000000000..e43fdb8d36 --- /dev/null +++ b/wr_malloc_size_of/lib.rs @@ -0,0 +1,442 @@ +// 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 or the MIT license +// , 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, +} + +impl MallocSizeOfOps { + pub fn new( + size_of: VoidPtrToSizeFn, + malloc_enclosing_size_of: Option, + ) -> 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(ptr: *const T) -> bool { + // The correct condition is this: + // `ptr as usize <= ::std::mem::align_of::()` + // 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(&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(&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<'a, T: ?Sized> MallocSizeOf for &'a T { + fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize { + // Zero makes sense for a non-owning reference. + 0 + } +} + +impl MallocShallowSizeOf for Box { + fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + unsafe { ops.malloc_size_of(&**self) } + } +} + +impl MallocSizeOf for Box { + 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 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 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 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 MallocSizeOf for Option { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + if let Some(val) = self.as_ref() { + val.size_of(ops) + } else { + 0 + } + } +} + +impl MallocSizeOf for Result { + 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 MallocSizeOf for std::cell::Cell { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + self.get().size_of(ops) + } +} + +impl MallocSizeOf for std::cell::RefCell { + 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 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 MallocShallowSizeOf for Vec { + fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + unsafe { ops.malloc_size_of(self.as_ptr()) } + } +} + +impl MallocSizeOf for Vec { + 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 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::() + size_of::()) + } + } + } + + impl 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); + +macro_rules! malloc_size_of_hash_map { + ($ty:ty) => { + impl 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::() + size_of::() + size_of::()) + } + } + } + + impl 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); + +// PhantomData is always 0. +impl MallocSizeOf for std::marker::PhantomData { + fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize { + 0 + } +} + +impl MallocSizeOf for euclid::Length { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + self.0.size_of(ops) + } +} + +impl MallocSizeOf for euclid::TypedScale { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + self.0.size_of(ops) + } +} + +impl MallocSizeOf for euclid::TypedPoint2D { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + self.x.size_of(ops) + self.y.size_of(ops) + } +} + +impl MallocSizeOf for euclid::TypedRect { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + self.origin.size_of(ops) + self.size.size_of(ops) + } +} + +impl MallocSizeOf for euclid::TypedSideOffsets2D { + 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 MallocSizeOf for euclid::TypedSize2D { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + self.width.size_of(ops) + self.height.size_of(ops) + } +} + +impl MallocSizeOf for euclid::TypedTransform2D { + 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 MallocSizeOf for euclid::TypedTransform3D { + 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 MallocSizeOf for euclid::TypedVector2D { + 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, Range, Range, Range, Range); +malloc_size_of_is_0!(Range, Range, Range, Range, Range); +malloc_size_of_is_0!(Range, Range); + +malloc_size_of_is_0!(app_units::Au); From 4ba2e1b3f286102a54d856510dd22ed2a7564ad9 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Sat, 12 Jan 2019 19:21:58 +0000 Subject: [PATCH 2/9] Bug 1519454 - Hook up MallocSizeOf and use it to replace some manual reporting. r=emilio Depends on D16353 Differential Revision: https://phabricator.services.mozilla.com/D16354 [wrupdater] From https://hg.mozilla.org/mozilla-central/rev/e9b1d04247debbf9506351b855091546ce59c4d1 --- webrender/src/clip.rs | 31 +++++++++---------------- webrender/src/clip_scroll_tree.rs | 2 +- webrender/src/gpu_cache.rs | 38 +++++++++++-------------------- webrender/src/hit_test.rs | 31 +++++++++---------------- webrender/src/intern.rs | 6 ++--- webrender/src/lib.rs | 5 ++++ webrender/src/prim_store/mod.rs | 4 ++-- webrender/src/render_backend.rs | 23 ++++++++++--------- webrender/src/renderer.rs | 29 +++++++++-------------- webrender/src/resource_cache.rs | 7 ++++++ webrender/src/scene_builder.rs | 24 +++++++++---------- webrender/src/util.rs | 4 ++-- webrender_api/src/api.rs | 10 ++++---- webrender_api/src/display_item.rs | 4 ++-- webrender_api/src/lib.rs | 4 ++++ webrender_api/src/units.rs | 4 ++-- wr_malloc_size_of/lib.rs | 7 ------ 17 files changed, 102 insertions(+), 131 deletions(-) diff --git a/webrender/src/clip.rs b/webrender/src/clip.rs index bfba1ad729..364cbc888a 100644 --- a/webrender/src/clip.rs +++ b/webrender/src/clip.rs @@ -6,7 +6,7 @@ use api::{BorderRadius, ClipMode, ComplexClipRegion, DeviceIntRect, DevicePixelS use api::{ImageRendering, LayoutRect, LayoutSize, LayoutPoint, LayoutVector2D}; use api::{BoxShadowClipMode, LayoutToWorldScale, PicturePixel, WorldPixel}; use api::{PictureRect, LayoutPixel, WorldPoint, WorldSize, WorldRect, LayoutToWorldTransform}; -use api::{VoidPtrToSizeFn, ImageKey}; +use api::{ImageKey}; use app_units::Au; use border::{ensure_no_corner_overlap, BorderRadiusAu}; use box_shadow::{BLUR_SAMPLE_SCALE, BoxShadowClipSource, BoxShadowCacheKey}; @@ -22,7 +22,6 @@ 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}; /* @@ -107,7 +106,7 @@ use util::{extract_inner_rect_safe, project_rect, ScaleOffset}; // Type definitions for interning clip nodes. #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)] pub struct ClipDataMarker; pub type ClipDataStore = intern::DataStore; @@ -186,6 +185,7 @@ impl From for ClipNode { 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; @@ -195,7 +195,7 @@ bitflags! { // 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, PartialEq, Hash)] +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Hash)] pub struct ClipChainId(pub u32); // The root of each clip chain is the NONE id. The @@ -209,7 +209,7 @@ impl ClipChainId { // 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)] +#[derive(Clone, Debug, MallocSizeOf)] pub struct ClipChainNode { pub handle: ClipDataHandle, pub local_pos: LayoutPoint, @@ -223,7 +223,7 @@ pub struct ClipChainNode { // an index to the node data itself, as well as // some flags describing how this clip node instance // is positioned. -#[derive(Debug)] +#[derive(Debug, MallocSizeOf)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct ClipNodeInstance { @@ -250,7 +250,7 @@ pub struct ClipNodeRange { // todo(gw): optimize: // separate arrays for matrices // cache and only build as needed. -#[derive(Debug)] +#[derive(Debug, MallocSizeOf)] enum ClipSpaceConversion { Local, ScaleOffset(ScaleOffset), @@ -259,6 +259,7 @@ enum ClipSpaceConversion { // Temporary information that is cached and reused // during building of a clip chain instance. +#[derive(MallocSizeOf)] struct ClipNodeInfo { conversion: ClipSpaceConversion, handle: ClipDataHandle, @@ -434,7 +435,8 @@ impl ClipNode { } } -// The main clipping public interface that other modules access. +/// The main clipping public interface that other modules access. +#[derive(MallocSizeOf)] pub struct ClipStore { pub clip_chain_nodes: Vec, clip_node_instances: Vec, @@ -708,17 +710,6 @@ impl ClipStore { 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 { @@ -1287,7 +1278,7 @@ pub fn project_inner_rect( // Collects a list of unique clips to be applied to a rasterization // root at the end of primitive preparation. -#[derive(Debug)] +#[derive(Debug, MallocSizeOf)] pub struct ClipNodeCollector { spatial_node_index: SpatialNodeIndex, clips: FastHashSet, diff --git a/webrender/src/clip_scroll_tree.rs b/webrender/src/clip_scroll_tree.rs index ea0c212ebc..8040d421a6 100644 --- a/webrender/src/clip_scroll_tree.rs +++ b/webrender/src/clip_scroll_tree.rs @@ -41,7 +41,7 @@ impl CoordinateSystem { } } -#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq, PartialOrd, Ord)] +#[derive(Debug, Copy, Clone, Eq, Hash, MallocSizeOf, PartialEq, PartialOrd, Ord)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct SpatialNodeIndex(pub u32); diff --git a/webrender/src/gpu_cache.rs b/webrender/src/gpu_cache.rs index 49e9f7dfc6..969198c970 100644 --- a/webrender/src/gpu_cache.rs +++ b/webrender/src/gpu_cache.rs @@ -25,7 +25,6 @@ //! for this frame. use api::{DebugFlags, DocumentId, PremultipliedColorF, IdNamespace, TexelRect}; -use api::{VoidPtrToSizeFn}; use euclid::TypedRect; use internal_types::{FastHashMap}; use profiler::GpuCacheProfileCounters; @@ -34,7 +33,6 @@ 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}; @@ -55,7 +53,7 @@ const RECLAIM_THRESHOLD: f32 = 0.2; /// blow away the cache and rebuild it. const RECLAIM_DELAY_S: u64 = 5; -#[derive(Debug, Copy, Clone, Eq, PartialEq)] +#[derive(Debug, Copy, Clone, Eq, MallocSizeOf, PartialEq)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] struct Epoch(u32); @@ -75,7 +73,7 @@ struct CacheLocation { } /// A single texel in RGBAF32 texture - 16 bytes. -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, MallocSizeOf)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct GpuBlockData { @@ -147,7 +145,7 @@ impl GpuCacheHandle { // 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, Eq, PartialEq)] +#[derive(Copy, Debug, Clone, MallocSizeOf, Eq, PartialEq)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct GpuCacheAddress { @@ -183,7 +181,7 @@ impl Add for GpuCacheAddress { } // An entry in a free-list of blocks in the GPU cache. -#[derive(Debug)] +#[derive(Debug, MallocSizeOf)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] struct Block { @@ -235,7 +233,7 @@ impl Block { /// /// Because we use Option in a lot of places, we use a NonZeroU32 /// here and avoid ever using the index zero. -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, MallocSizeOf)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] struct BlockIndex(NonZeroU32); @@ -254,6 +252,7 @@ impl BlockIndex { // 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. @@ -276,6 +275,7 @@ impl Row { // 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, @@ -286,6 +286,7 @@ pub enum GpuCacheUpdate { /// 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), @@ -293,7 +294,7 @@ pub enum GpuCacheDebugCmd { Free(GpuCacheAddress), } -#[derive(Clone)] +#[derive(Clone, MallocSizeOf)] pub struct GpuCacheDebugChunk { pub address: GpuCacheAddress, pub size: usize, @@ -302,6 +303,7 @@ pub struct GpuCacheDebugChunk { #[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, @@ -325,6 +327,7 @@ pub struct GpuCacheUpdateList { // 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, free_list_2: Option, @@ -392,6 +395,7 @@ impl FreeBlockLists { // 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, @@ -456,18 +460,6 @@ impl Texture { } } - // 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. @@ -672,6 +664,7 @@ impl<'a> Drop for GpuDataRequest<'a> { /// 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, @@ -865,11 +858,6 @@ impl GpuCache { 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] diff --git a/webrender/src/hit_test.rs b/webrender/src/hit_test.rs index 56f917b0b2..d44f4128f1 100644 --- a/webrender/src/hit_test.rs +++ b/webrender/src/hit_test.rs @@ -3,19 +3,19 @@ * 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, VoidPtrToSizeFn, WorldPoint}; +use api::{LayoutPrimitiveInfo, LayoutRect, PipelineId, 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, @@ -27,6 +27,7 @@ pub struct HitTestSpatialNode { 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. @@ -64,20 +65,21 @@ impl HitTestClipNode { // copy the complete interned clip data store for // hit testing. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Copy, Clone, MallocSizeOf, 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)] +#[derive(Clone, MallocSizeOf)] pub struct HitTestingItem { rect: LayoutRect, clip_rect: LayoutRect, @@ -96,9 +98,10 @@ impl HitTestingItem { } } -#[derive(Clone)] +#[derive(Clone, MallocSizeOf)] pub struct HitTestingRun(pub Vec, pub ScrollNodeAndClipChain); +#[derive(MallocSizeOf)] enum HitTestRegion { Invalid, Rectangle(LayoutRect, ClipMode), @@ -121,6 +124,7 @@ impl HitTestRegion { } } +#[derive(MallocSizeOf)] pub struct HitTester { runs: Vec, spatial_nodes: Vec, @@ -371,28 +375,15 @@ impl HitTester { 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, PartialEq)] +#[derive(Clone, Copy, MallocSizeOf, PartialEq)] enum ClippedIn { ClippedIn, NotClippedIn, } +#[derive(MallocSizeOf)] pub struct HitTest { pipeline_id: Option, point: WorldPoint, diff --git a/webrender/src/intern.rs b/webrender/src/intern.rs index f37742948f..0df0d204fe 100644 --- a/webrender/src/intern.rs +++ b/webrender/src/intern.rs @@ -51,7 +51,7 @@ use util::VecHelper; /// correctness validation (handle). #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Copy, Clone, PartialEq)] +#[derive(Debug, Copy, Clone, MallocSizeOf, PartialEq)] struct Epoch(u64); impl Epoch { @@ -76,7 +76,7 @@ lazy_static! { /// A globally, unique identifier #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)] +#[derive(Debug, Copy, Clone, Eq, Hash, MallocSizeOf, PartialEq)] pub struct ItemUid { uid: usize, } @@ -90,7 +90,7 @@ impl ItemUid { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, MallocSizeOf)] pub struct Handle { index: u32, epoch: Epoch, diff --git a/webrender/src/lib.rs b/webrender/src/lib.rs index c3f8e16dc0..771d073ea0 100644 --- a/webrender/src/lib.rs +++ b/webrender/src/lib.rs @@ -58,12 +58,17 @@ extern crate cfg_if; 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; diff --git a/webrender/src/prim_store/mod.rs b/webrender/src/prim_store/mod.rs index f59d39ab1b..68a485b5e1 100644 --- a/webrender/src/prim_store/mod.rs +++ b/webrender/src/prim_store/mod.rs @@ -79,7 +79,7 @@ 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, PartialEq)] +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq)] pub struct ScrollNodeAndClipChain { pub spatial_node_index: SpatialNodeIndex, pub clip_chain_id: ClipChainId, @@ -846,7 +846,7 @@ impl OpacityBinding { } } -#[derive(Debug)] +#[derive(Debug, MallocSizeOf)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct VisibleMaskImageTile { diff --git a/webrender/src/render_backend.rs b/webrender/src/render_backend.rs index e881532cd3..0ab80dea8b 100644 --- a/webrender/src/render_backend.rs +++ b/webrender/src/render_backend.rs @@ -30,6 +30,7 @@ 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}; @@ -88,7 +89,7 @@ impl DocumentView { } } -#[derive(Copy, Clone, Hash, PartialEq, PartialOrd, Debug, Eq, Ord)] +#[derive(Copy, Clone, Hash, MallocSizeOf, PartialEq, PartialOrd, Debug, Eq, Ord)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct FrameId(usize); @@ -142,7 +143,7 @@ impl ::std::ops::Sub for FrameId { /// 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)] +#[derive(Copy, Clone, Debug, MallocSizeOf)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct FrameStamp { @@ -679,7 +680,7 @@ pub struct RenderBackend { notifier: Box, recorder: Option>, sampler: Option>, - size_of_op: Option, + size_of_ops: Option, debug_flags: DebugFlags, namespace_alloc_by_client: bool, } @@ -698,7 +699,7 @@ impl RenderBackend { frame_config: FrameBuilderConfig, recorder: Option>, sampler: Option>, - size_of_op: Option, + size_of_ops: Option, debug_flags: DebugFlags, namespace_alloc_by_client: bool, ) -> RenderBackend { @@ -718,7 +719,7 @@ impl RenderBackend { notifier, recorder, sampler, - size_of_op, + size_of_ops, debug_flags, namespace_alloc_by_client, } @@ -1552,16 +1553,16 @@ impl RenderBackend { serde_json::to_string(&debug_root).unwrap() } - fn report_memory(&self, tx: MsgSender) { + fn report_memory(&mut self, tx: MsgSender) { let mut report = MemoryReport::default(); - let op = self.size_of_op.unwrap(); - report.gpu_cache_metadata = self.gpu_cache.malloc_size_of(op); + 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); for (_id, doc) in &self.documents { if let Some(ref fb) = doc.frame_builder { - report.clip_stores += fb.clip_store.malloc_size_of(op); + report.clip_stores += fb.clip_store.size_of(ops); } - report.hit_testers += - doc.hit_tester.as_ref().map_or(0, |ht| ht.malloc_size_of(op)); + report.hit_testers += doc.hit_tester.size_of(ops); doc.resources.report_memory(op, &mut report) } diff --git a/webrender/src/renderer.rs b/webrender/src/renderer.rs index 8e275175e8..2df4124291 100644 --- a/webrender/src/renderer.rs +++ b/webrender/src/renderer.rs @@ -59,6 +59,7 @@ use internal_types::{TextureSource, ORTHO_FAR_PLANE, ORTHO_NEAR_PLANE, ResourceC 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}; @@ -1556,17 +1557,9 @@ pub struct Renderer { /// copy the WR output to. output_image_handler: Option>, - /// Optional function pointer for measuring memory used by a given + /// Optional function pointers for measuring memory used by a given /// heap-allocated pointer. - size_of_op: Option, - - /// 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, + size_of_ops: Option, // Currently allocated FBOs for output frames. output_targets: FastHashMap, @@ -1832,6 +1825,10 @@ impl Renderer { 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(); @@ -1857,8 +1854,6 @@ impl Renderer { 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(); @@ -1875,8 +1870,7 @@ impl Renderer { config, api_tx.clone(), scene_builder_hooks, - size_of_op, - enclosing_size_of_op, + make_size_of_ops(), ); thread::Builder::new().name(scene_thread_name.clone()).spawn(move || { register_thread_with_profiler(scene_thread_name.clone()); @@ -1949,7 +1943,7 @@ impl Renderer { config, recorder, sampler, - size_of_op, + make_size_of_ops(), debug_flags, namespace_alloc_by_client, ); @@ -2011,8 +2005,7 @@ impl Renderer { dither_matrix_texture, external_image_handler: None, output_image_handler: None, - size_of_op: options.size_of_op, - _enclosing_size_of_op: options.enclosing_size_of_op, + size_of_ops: make_size_of_ops(), output_targets: FastHashMap::default(), cpu_profiles: VecDeque::new(), gpu_profiles: VecDeque::new(), @@ -4572,7 +4565,7 @@ impl Renderer { } fn size_of(&self, ptr: *const T) -> usize { - let op = self.size_of_op.as_ref().unwrap(); + let op = self.size_of_ops.as_ref().unwrap().size_of_op; unsafe { op(ptr as *const c_void) } } diff --git a/webrender/src/resource_cache.rs b/webrender/src/resource_cache.rs index 3cb0db61f9..04860c1def 100644 --- a/webrender/src/resource_cache.rs +++ b/webrender/src/resource_cache.rs @@ -1821,6 +1821,13 @@ impl ResourceCache { } /// 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(); diff --git a/webrender/src/scene_builder.rs b/webrender/src/scene_builder.rs index 1e8c4d82f6..918f7faf1d 100644 --- a/webrender/src/scene_builder.rs +++ b/webrender/src/scene_builder.rs @@ -5,7 +5,7 @@ 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, VoidPtrToSizeFn}; +use api::{MemoryReport}; use api::channel::MsgSender; #[cfg(feature = "capture")] use capture::CaptureConfig; @@ -15,6 +15,7 @@ use clip_scroll_tree::ClipScrollTree; use display_list_flattener::DisplayListFlattener; use intern::{Internable, Interner}; use internal_types::{FastHashMap, FastHashSet}; +use malloc_size_of::MallocSizeOfOps; use prim_store::{PrimitiveDataInterner, PrimitiveDataUpdateList, PrimitiveKeyKind}; use prim_store::PrimitiveStoreStats; use prim_store::borders::{ @@ -220,10 +221,11 @@ impl DocumentResources { /// Reports CPU heap memory used by the interners. fn report_memory( &self, - op: VoidPtrToSizeFn, - eop: VoidPtrToSizeFn, + ops: &mut MallocSizeOfOps, r: &mut MemoryReport, ) { + let op = ops.size_of_op; + let eop = ops.enclosing_size_of_op.unwrap(); 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); @@ -293,8 +295,7 @@ pub struct SceneBuilder { config: FrameBuilderConfig, hooks: Option>, simulate_slow_ms: u32, - size_of_op: Option, - enclosing_size_of_op: Option, + size_of_ops: Option, } impl SceneBuilder { @@ -302,8 +303,7 @@ impl SceneBuilder { config: FrameBuilderConfig, api_tx: MsgSender, hooks: Option>, - size_of_op: Option, - enclosing_size_of_op: Option, + size_of_ops: Option, ) -> (Self, Sender, Receiver) { let (in_tx, in_rx) = channel(); let (out_tx, out_rx) = channel(); @@ -315,8 +315,7 @@ impl SceneBuilder { api_tx, config, hooks, - size_of_op, - enclosing_size_of_op, + size_of_ops, simulate_slow_ms: 0, }, in_tx, @@ -763,12 +762,11 @@ impl SceneBuilder { } /// Reports CPU heap memory used by the SceneBuilder. - fn report_memory(&self) -> MemoryReport { - let op = self.size_of_op.unwrap(); - let eop = self.enclosing_size_of_op.unwrap(); + fn report_memory(&mut self) -> MemoryReport { + let ops = self.size_of_ops.as_mut().unwrap(); let mut report = MemoryReport::default(); for doc in self.documents.values() { - doc.resources.report_memory(op, eop, &mut report); + doc.resources.report_memory(ops, &mut report); } report diff --git a/webrender/src/util.rs b/webrender/src/util.rs index ba94c2a28f..9c6dd4e24f 100644 --- a/webrender/src/util.rs +++ b/webrender/src/util.rs @@ -92,7 +92,7 @@ impl VecHelper for Vec { // 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)] +#[derive(Debug, Clone, Copy, MallocSizeOf)] pub struct ScaleOffset { pub scale: Vector2D, pub offset: Vector2D, @@ -556,7 +556,7 @@ impl MaxRect for TypedRect { /// An enum that tries to avoid expensive transformation matrix calculations /// when possible when dealing with non-perspective axis-aligned transformations. -#[derive(Debug)] +#[derive(Debug, MallocSizeOf)] pub enum FastTransform { /// A simple offset, which can be used without doing any matrix math. Offset(TypedVector2D), diff --git a/webrender_api/src/api.rs b/webrender_api/src/api.rs index 5838c24bc3..dae80eb534 100644 --- a/webrender_api/src/api.rs +++ b/webrender_api/src/api.rs @@ -561,7 +561,7 @@ pub struct HitTestResult { } bitflags! { - #[derive(Deserialize, Serialize)] + #[derive(Deserialize, MallocSizeOf, Serialize)] pub struct HitTestFlags: u8 { const FIND_ALL = 0b00000001; const POINT_RELATIVE_TO_PIPELINE_VIEWPORT = 0b00000010; @@ -787,11 +787,11 @@ impl Epoch { } #[repr(C)] -#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize)] +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize)] pub struct IdNamespace(pub u32); #[repr(C)] -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] pub struct DocumentId(pub IdNamespace, pub u32); impl DocumentId { @@ -807,7 +807,7 @@ 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, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] pub struct PipelineId(pub PipelineSourceId, pub u32); impl PipelineId { @@ -963,7 +963,7 @@ impl RenderApiSender { } bitflags! { - #[derive(Default, Deserialize, Serialize)] + #[derive(Default, Deserialize, MallocSizeOf, Serialize)] pub struct DebugFlags: u32 { /// Display the frame profiler on screen. const PROFILER_DBG = 1 << 0; diff --git a/webrender_api/src/display_item.rs b/webrender_api/src/display_item.rs index 4df5f0a13f..6932175b3e 100644 --- a/webrender_api/src/display_item.rs +++ b/webrender_api/src/display_item.rs @@ -401,7 +401,7 @@ pub enum BorderRadiusKind { } #[repr(C)] -#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)] pub struct BorderRadius { pub top_left: LayoutSize, pub top_right: LayoutSize, @@ -741,7 +741,7 @@ impl ImageMask { } #[repr(C)] -#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)] +#[derive(Copy, Clone, Debug, MallocSizeOf, PartialEq, Serialize, Deserialize, Eq, Hash)] pub enum ClipMode { Clip, // Pixels inside the region are visible. ClipOut, // Pixels outside the region are visible. diff --git a/webrender_api/src/lib.rs b/webrender_api/src/lib.rs index 6da3ff31c1..63be1f807a 100644 --- a/webrender_api/src/lib.rs +++ b/webrender_api/src/lib.rs @@ -30,11 +30,15 @@ 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; diff --git a/webrender_api/src/units.rs b/webrender_api/src/units.rs index 8939a06075..3fcf4655de 100644 --- a/webrender_api/src/units.rs +++ b/webrender_api/src/units.rs @@ -65,7 +65,7 @@ pub type RasterVector2D = TypedVector2D; pub type RasterVector3D = TypedVector3D; /// Geometry in a stacking context's local coordinate space (logical pixels). -#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Deserialize, Serialize)] +#[derive(Hash, Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Ord, PartialOrd, Deserialize, Serialize)] pub struct LayoutPixel; pub type LayoutRect = TypedRect; @@ -81,7 +81,7 @@ pub type LayoutIntPoint = TypedPoint2D; pub type LayoutIntSize = TypedSize2D; /// Geometry in the document's coordinate space (logical pixels). -#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)] +#[derive(Hash, Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Ord, PartialOrd)] pub struct WorldPixel; pub type WorldRect = TypedRect; diff --git a/wr_malloc_size_of/lib.rs b/wr_malloc_size_of/lib.rs index e43fdb8d36..1e05a8435b 100644 --- a/wr_malloc_size_of/lib.rs +++ b/wr_malloc_size_of/lib.rs @@ -103,13 +103,6 @@ impl MallocSizeOf for String { } } -impl<'a, T: ?Sized> MallocSizeOf for &'a T { - fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize { - // Zero makes sense for a non-owning reference. - 0 - } -} - impl MallocShallowSizeOf for Box { fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize { unsafe { ops.malloc_size_of(&**self) } From 4bacd4b41e9aadf090d7035e9ec9e8a212dcb6a0 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Sat, 12 Jan 2019 19:22:01 +0000 Subject: [PATCH 3/9] Bug 1519454 - Implement MallocSizeOf for Interner and DataStore. r=emilio Depends on D16354 Differential Revision: https://phabricator.services.mozilla.com/D16355 [wrupdater] From https://hg.mozilla.org/mozilla-central/rev/054028a8d4a75083599eda3791913d0d66aa1b8d --- webrender/src/border.rs | 8 ++-- webrender/src/box_shadow.rs | 4 +- webrender/src/clip.rs | 5 ++- webrender/src/freelist.rs | 3 +- webrender/src/glyph_rasterizer/mod.rs | 4 +- webrender/src/gpu_cache.rs | 4 +- webrender/src/gpu_types.rs | 5 ++- webrender/src/intern.rs | 57 +++++++++++++++++++-------- webrender/src/prim_store/borders.rs | 12 ++++-- webrender/src/prim_store/gradient.rs | 14 ++++--- webrender/src/prim_store/image.rs | 12 +++--- webrender/src/prim_store/line_dec.rs | 7 ++-- webrender/src/prim_store/mod.rs | 37 ++++++++++------- webrender/src/prim_store/picture.rs | 7 ++-- webrender/src/prim_store/text_run.rs | 5 ++- webrender/src/render_task.rs | 2 +- webrender/src/scene_builder.rs | 2 +- webrender_api/src/api.rs | 2 +- webrender_api/src/color.rs | 4 +- webrender_api/src/display_item.rs | 26 ++++++------ webrender_api/src/font.rs | 22 +++++------ webrender_api/src/image.rs | 4 +- 22 files changed, 145 insertions(+), 101 deletions(-) diff --git a/webrender/src/border.rs b/webrender/src/border.rs index c07d1a27ad..397d696937 100644 --- a/webrender/src/border.rs +++ b/webrender/src/border.rs @@ -34,7 +34,7 @@ pub const MAX_DASH_COUNT: u32 = 2048; // all the border structs with hashable // variants... -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Clone, Debug, Hash, MallocSizeOf, PartialEq, Eq)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct BorderRadiusAu { @@ -66,7 +66,7 @@ impl From for BorderRadius { } } -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Clone, Debug, Hash, MallocSizeOf, PartialEq, Eq)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct BorderSideAu { @@ -94,7 +94,7 @@ impl From for BorderSide { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Clone, Hash, Eq, PartialEq)] +#[derive(Debug, Clone, Hash, Eq, MallocSizeOf, PartialEq)] pub struct NormalBorderAu { pub left: BorderSideAu, pub right: BorderSideAu, @@ -148,7 +148,7 @@ impl From for ApiNormalBorder { /// Cache key that uniquely identifies a border /// segment in the render task cache. -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Clone, Debug, Hash, MallocSizeOf, PartialEq, Eq)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct BorderSegmentCacheKey { diff --git a/webrender/src/box_shadow.rs b/webrender/src/box_shadow.rs index f14a526423..db04712aa0 100644 --- a/webrender/src/box_shadow.rs +++ b/webrender/src/box_shadow.rs @@ -12,7 +12,7 @@ use prim_store::{ScrollNodeAndClipChain, PrimitiveKeyKind}; use render_task::RenderTaskCacheEntryHandle; use util::RectHelpers; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, MallocSizeOf)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct BoxShadowClipSource { @@ -51,7 +51,7 @@ 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, PartialEq)] +#[derive(Debug, Clone, Eq, Hash, MallocSizeOf, PartialEq)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct BoxShadowCacheKey { diff --git a/webrender/src/clip.rs b/webrender/src/clip.rs index 364cbc888a..183871f9bf 100644 --- a/webrender/src/clip.rs +++ b/webrender/src/clip.rs @@ -133,6 +133,7 @@ enum ClipResult { #[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, @@ -781,7 +782,7 @@ impl ClipRegion> { // 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, PartialEq, Hash)] +#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub enum ClipItemKey { @@ -844,7 +845,7 @@ impl ClipItemKey { impl intern::InternDebug for ClipItemKey {} -#[derive(Debug)] +#[derive(Debug, MallocSizeOf)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub enum ClipItem { diff --git a/webrender/src/freelist.rs b/webrender/src/freelist.rs index faec9b7109..bcff127fec 100644 --- a/webrender/src/freelist.rs +++ b/webrender/src/freelist.rs @@ -23,7 +23,7 @@ use std::{fmt, u32}; use std::marker::PhantomData; -#[derive(Debug, Copy, Clone, PartialEq)] +#[derive(Debug, Copy, Clone, MallocSizeOf, PartialEq)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] struct Epoch(u32); @@ -96,6 +96,7 @@ impl PartialEq for WeakFreeListHandle { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] +#[derive(MallocSizeOf)] pub struct WeakFreeListHandle { index: u32, epoch: Epoch, diff --git a/webrender/src/glyph_rasterizer/mod.rs b/webrender/src/glyph_rasterizer/mod.rs index 78b0265908..2c7dc7081c 100644 --- a/webrender/src/glyph_rasterizer/mod.rs +++ b/webrender/src/glyph_rasterizer/mod.rs @@ -28,7 +28,7 @@ pub use self::pathfinder::{ThreadSafePathfinderFontContext, NativeFontHandleWrap #[cfg(not(feature = "pathfinder"))] mod no_pathfinder; -#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)] +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct FontTransform { @@ -164,7 +164,7 @@ impl<'a> From<&'a LayoutToWorldTransform> for FontTransform { // 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)] +#[derive(Clone, Hash, PartialEq, Eq, Debug, Ord, PartialOrd, MallocSizeOf)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct FontInstance { diff --git a/webrender/src/gpu_cache.rs b/webrender/src/gpu_cache.rs index 969198c970..1ce2544186 100644 --- a/webrender/src/gpu_cache.rs +++ b/webrender/src/gpu_cache.rs @@ -64,7 +64,7 @@ impl Epoch { } } -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, MallocSizeOf)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] struct CacheLocation { @@ -129,7 +129,7 @@ pub trait ToGpuBlocks { } // A handle to a GPU resource. -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, MallocSizeOf)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct GpuCacheHandle { diff --git a/webrender/src/gpu_types.rs b/webrender/src/gpu_types.rs index 5f37271fe7..6c7d7214c5 100644 --- a/webrender/src/gpu_types.rs +++ b/webrender/src/gpu_types.rs @@ -59,7 +59,7 @@ pub enum RasterizationSpace { Screen = 1, } -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, MallocSizeOf)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] #[repr(C)] @@ -96,7 +96,7 @@ pub struct ScalingInstance { pub src_task_address: RenderTaskAddress, } -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Hash, MallocSizeOf, PartialEq, Eq)] #[repr(C)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] @@ -317,6 +317,7 @@ bitflags! { /// 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; diff --git a/webrender/src/intern.rs b/webrender/src/intern.rs index 0df0d204fe..0255aa6669 100644 --- a/webrender/src/intern.rs +++ b/webrender/src/intern.rs @@ -5,6 +5,7 @@ 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; @@ -106,6 +107,7 @@ impl Handle where M: Copy { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] +#[derive(MallocSizeOf)] pub enum UpdateKind { Insert, Remove, @@ -114,6 +116,7 @@ pub enum UpdateKind { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] +#[derive(MallocSizeOf)] pub struct Update { index: usize, kind: UpdateKind, @@ -123,7 +126,8 @@ pub struct Update { /// correct access patterns. #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -struct Item { +#[derive(MallocSizeOf)] +struct Item { epoch: Epoch, data: T, } @@ -136,13 +140,18 @@ pub trait InternDebug { /// contains a free-list of items for fast access. #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -pub struct DataStore { +#[derive(MallocSizeOf)] +pub struct DataStore { items: Vec>, _source: PhantomData, _marker: PhantomData, } -impl ::std::default::Default for DataStore where S: Debug, T: From, M: Debug +impl ::std::default::Default for DataStore +where + S: Debug + MallocSizeOf, + T: From + MallocSizeOf, + M: Debug { fn default() -> Self { DataStore { @@ -153,7 +162,11 @@ impl ::std::default::Default for DataStore where S: Debug, T: } } -impl DataStore where S: Debug, T: From, M: Debug +impl DataStore +where + S: Debug + MallocSizeOf, + T: From + MallocSizeOf, + M: Debug { /// Apply any updates from the scene builder thread to /// this data store. @@ -194,7 +207,10 @@ impl DataStore where S: Debug, T: From, M: Debug /// Retrieve an item from the store via handle impl ops::Index> for DataStore -where M: Copy +where + S: MallocSizeOf, + T: MallocSizeOf, + M: Copy { type Output = T; fn index(&self, handle: Handle) -> &T { @@ -208,6 +224,8 @@ where M: Copy /// Retrieve an item from the store via handle impl ops::IndexMut> for DataStore where + S: MallocSizeOf, + T: MallocSizeOf, M: Copy { fn index_mut(&mut self, handle: Handle) -> &mut T { @@ -224,10 +242,12 @@ where /// an update list of additions / removals. #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] +#[derive(MallocSizeOf)] pub struct Interner where - S: Eq + Hash + Clone + Debug, - M: Copy + S: Eq + Hash + Clone + Debug + MallocSizeOf, + D: MallocSizeOf, + M: Copy + MallocSizeOf, { /// Uniquely map an interning key to a handle map: FastHashMap>, @@ -246,8 +266,9 @@ where impl ::std::default::Default for Interner where - S: Eq + Hash + Clone + Debug, - M: Copy + Debug + S: Eq + Hash + Clone + Debug + MallocSizeOf, + D: MallocSizeOf, + M: Copy + Debug + MallocSizeOf, { fn default() -> Self { Interner { @@ -263,8 +284,9 @@ where impl Interner where - S: Eq + Hash + Clone + Debug + InternDebug, - M: Copy + Debug + S: Eq + Hash + Clone + Debug + InternDebug + MallocSizeOf, + D: MallocSizeOf, + M: Copy + Debug + MallocSizeOf { /// Intern a data structure, and return a handle to /// that data. The handle can then be stored in the @@ -398,8 +420,9 @@ where /// Retrieve the local data for an item from the interner via handle impl ops::Index> for Interner where - S: Eq + Clone + Hash + Debug, - M: Copy + Debug + S: Eq + Clone + Hash + Debug + MallocSizeOf, + D: MallocSizeOf, + M: Copy + Debug + MallocSizeOf { type Output = D; fn index(&self, handle: Handle) -> &D { @@ -413,10 +436,10 @@ where /// /// see DisplayListFlattener::add_interned_primitive

pub trait Internable { - type Marker: Copy + Debug; - type Source: Eq + Hash + Clone + Debug; - type StoreData: From; - type InternData; + type Marker: Copy + Debug + MallocSizeOf; + type Source: Eq + Hash + Clone + Debug + MallocSizeOf; + type StoreData: From + MallocSizeOf; + type InternData: MallocSizeOf; /// Build a new key from self with `info`. fn build_key( diff --git a/webrender/src/prim_store/borders.rs b/webrender/src/prim_store/borders.rs index 81b39c7dc5..e18b6f925e 100644 --- a/webrender/src/prim_store/borders.rs +++ b/webrender/src/prim_store/borders.rs @@ -24,7 +24,7 @@ use storage; #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Clone, Eq, PartialEq, Hash)] +#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)] pub struct NormalBorderPrim { pub border: NormalBorderAu, pub widths: LayoutSideOffsetsAu, @@ -67,6 +67,7 @@ impl AsInstanceKind for NormalBorderKey { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] +#[derive(MallocSizeOf)] pub struct NormalBorderData { pub brush_segments: Vec, pub border_segments: Vec, @@ -161,7 +162,7 @@ impl From for NormalBorderTemplate { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)] pub struct NormalBorderDataMarker; pub type NormalBorderDataStore = intern::DataStore; @@ -209,8 +210,9 @@ impl IsVisible for NormalBorderPrim { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Clone, Eq, PartialEq, Hash)] +#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)] pub struct ImageBorder { + #[ignore_malloc_size_of = "Arc"] pub request: ImageRequest, pub nine_patch: NinePatchDescriptor, } @@ -251,7 +253,9 @@ impl AsInstanceKind for ImageBorderKey { #[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, } @@ -339,7 +343,7 @@ impl From for ImageBorderTemplate { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)] pub struct ImageBorderDataMarker; pub type ImageBorderDataStore = intern::DataStore; diff --git a/webrender/src/prim_store/gradient.rs b/webrender/src/prim_store/gradient.rs index dd514146c5..d102ca01df 100644 --- a/webrender/src/prim_store/gradient.rs +++ b/webrender/src/prim_store/gradient.rs @@ -20,7 +20,7 @@ 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, PartialEq)] +#[derive(Debug, Clone, MallocSizeOf, PartialEq)] pub struct GradientStopKey { pub offset: f32, pub color: ColorU, @@ -38,7 +38,7 @@ impl hash::Hash for GradientStopKey { /// Identifying key for a line decoration. #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Clone, Eq, PartialEq, Hash)] +#[derive(Debug, Clone, Eq, PartialEq, Hash, MallocSizeOf)] pub struct LinearGradientKey { pub common: PrimKeyCommonData, pub extend_mode: ExtendMode, @@ -95,6 +95,7 @@ impl AsInstanceKind for LinearGradientKey { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] +#[derive(MallocSizeOf)] pub struct LinearGradientTemplate { pub common: PrimTemplateCommonData, pub extend_mode: ExtendMode, @@ -228,7 +229,7 @@ impl LinearGradientTemplate { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)] pub struct LinearGradientDataMarker; pub type LinearGradientDataStore = DataStore; @@ -279,7 +280,7 @@ 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, PartialEq)] +#[derive(Debug, Clone, MallocSizeOf, PartialEq)] pub struct RadialGradientParams { pub start_radius: f32, pub end_radius: f32, @@ -299,7 +300,7 @@ impl hash::Hash for RadialGradientParams { /// Identifying key for a line decoration. #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Clone, Eq, PartialEq, Hash)] +#[derive(Debug, Clone, Eq, PartialEq, Hash, MallocSizeOf)] pub struct RadialGradientKey { pub common: PrimKeyCommonData, pub extend_mode: ExtendMode, @@ -354,6 +355,7 @@ impl AsInstanceKind for RadialGradientKey { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] +#[derive(MallocSizeOf)] pub struct RadialGradientTemplate { pub common: PrimTemplateCommonData, pub extend_mode: ExtendMode, @@ -458,7 +460,7 @@ impl RadialGradientTemplate { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)] pub struct RadialGradientDataMarker; pub type RadialGradientDataStore = DataStore; diff --git a/webrender/src/prim_store/image.rs b/webrender/src/prim_store/image.rs index afdfc18c3b..7c4812493b 100644 --- a/webrender/src/prim_store/image.rs +++ b/webrender/src/prim_store/image.rs @@ -67,7 +67,7 @@ pub struct ImageInstance { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Clone, Eq, PartialEq, Hash)] +#[derive(Debug, Clone, Eq, PartialEq, MallocSizeOf, Hash)] pub struct Image { pub key: ApiImageKey, pub stretch_size: SizeKey, @@ -127,7 +127,7 @@ impl AsInstanceKind for ImageKey { // Where to find the texture data for an image primitive. #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug)] +#[derive(Debug, MallocSizeOf)] pub enum ImageSource { // A normal image - just reference the texture cache. Default, @@ -141,6 +141,7 @@ pub enum ImageSource { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] +#[derive(MallocSizeOf)] pub struct ImageData { pub key: ApiImageKey, pub stretch_size: LayoutSize, @@ -336,7 +337,7 @@ impl From for ImageTemplate { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)] pub struct ImageDataMarker; pub type ImageDataStore = DataStore; @@ -389,7 +390,7 @@ impl IsVisible for Image { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Clone, Eq, PartialEq, Hash)] +#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)] pub struct YuvImage { pub color_depth: ColorDepth, pub yuv_key: [ApiImageKey; 3], @@ -438,6 +439,7 @@ impl AsInstanceKind for YuvImageKey { #[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], @@ -513,7 +515,7 @@ impl From for YuvImageTemplate { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)] pub struct YuvImageDataMarker; pub type YuvImageDataStore = DataStore; diff --git a/webrender/src/prim_store/line_dec.rs b/webrender/src/prim_store/line_dec.rs index 8ddcdf085a..d56a6022db 100644 --- a/webrender/src/prim_store/line_dec.rs +++ b/webrender/src/prim_store/line_dec.rs @@ -17,7 +17,7 @@ use prim_store::{ }; use prim_store::PrimitiveInstanceKind; -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Clone, Debug, Hash, MallocSizeOf, PartialEq, Eq)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct LineDecorationCacheKey { @@ -28,7 +28,7 @@ pub struct LineDecorationCacheKey { } /// Identifying key for a line decoration. -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Clone, Debug, Hash, MallocSizeOf, PartialEq, Eq)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct LineDecoration { @@ -77,6 +77,7 @@ impl AsInstanceKind for LineDecorationKey { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] +#[derive(MallocSizeOf)] pub struct LineDecorationData { pub cache_key: Option, pub color: ColorF, @@ -136,7 +137,7 @@ impl From for LineDecorationTemplate { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)] pub struct LineDecorationDataMarker; pub type LineDecorationDataStore = intern::DataStore; diff --git a/webrender/src/prim_store/mod.rs b/webrender/src/prim_store/mod.rs index 68a485b5e1..0142983ccf 100644 --- a/webrender/src/prim_store/mod.rs +++ b/webrender/src/prim_store/mod.rs @@ -28,6 +28,7 @@ use gpu_cache::{GpuCache, GpuCacheAddress, GpuCacheHandle, GpuDataRequest, ToGpu 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}; @@ -99,7 +100,7 @@ impl ScrollNodeAndClipChain { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, MallocSizeOf)] pub struct PrimitiveOpacity { pub is_opaque: bool, } @@ -347,6 +348,7 @@ impl GpuCacheAddress { /// 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, @@ -357,7 +359,7 @@ pub struct PrimitiveSceneData { /// uniquely identifies a primitive template by key. #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Clone, Eq, PartialEq, Hash)] +#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)] pub enum PrimitiveKeyKind { /// Clear an existing rect, used for special effects on some platforms. Clear, @@ -368,7 +370,7 @@ pub enum PrimitiveKeyKind { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, MallocSizeOf, PartialEq)] pub struct RectangleKey { x: f32, y: f32, @@ -410,7 +412,7 @@ impl From for RectangleKey { /// 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, PartialEq)] +#[derive(Debug, Clone, MallocSizeOf, PartialEq)] pub struct SideOffsetsKey { pub top: f32, pub right: f32, @@ -465,7 +467,7 @@ impl From> for SideOffsetsKey { /// 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, PartialEq)] +#[derive(Copy, Debug, Clone, MallocSizeOf, PartialEq)] pub struct SizeKey { w: f32, h: f32, @@ -498,7 +500,7 @@ impl From> for SizeKey { /// 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, PartialEq)] +#[derive(Copy, Debug, Clone, MallocSizeOf, PartialEq)] pub struct VectorKey { pub x: f32, pub y: f32, @@ -531,7 +533,7 @@ impl From for VectorKey { /// 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, PartialEq)] +#[derive(Debug, Clone, MallocSizeOf, PartialEq)] pub struct PointKey { pub x: f32, pub y: f32, @@ -563,7 +565,7 @@ impl From for PointKey { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Clone, Eq, PartialEq, Hash)] +#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)] pub struct PrimKeyCommonData { pub is_backface_visible: bool, pub prim_size: SizeKey, @@ -585,15 +587,15 @@ impl PrimKeyCommonData { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Clone, Eq, PartialEq, Hash)] -pub struct PrimKey { +#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)] +pub struct PrimKey { pub common: PrimKeyCommonData, pub kind: T, } #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Clone, Eq, PartialEq, Hash)] +#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)] pub struct PrimitiveKey { pub common: PrimKeyCommonData, pub kind: PrimitiveKeyKind, @@ -648,6 +650,7 @@ impl AsInstanceKind for PrimitiveKey { /// 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, @@ -675,6 +678,7 @@ 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, @@ -701,6 +705,7 @@ impl PrimTemplateCommonData { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] +#[derive(MallocSizeOf)] pub struct PrimTemplate { pub common: PrimTemplateCommonData, pub kind: T, @@ -708,6 +713,7 @@ pub struct PrimTemplate { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] +#[derive(MallocSizeOf)] pub struct PrimitiveTemplate { pub common: PrimTemplateCommonData, pub kind: PrimitiveTemplateKind, @@ -780,7 +786,7 @@ 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, PartialEq)] +#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)] pub struct PrimitiveDataMarker; impl intern::Internable for PrimitiveKeyKind { @@ -865,7 +871,7 @@ pub struct VisibleGradientTile { /// along with the current render task cache entry. #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug)] +#[derive(Debug, MallocSizeOf)] pub struct BorderSegmentInfo { pub local_task_size: LayoutSize, pub cache_key: BorderSegmentCacheKey, @@ -880,6 +886,7 @@ bitflags! { /// `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; @@ -901,7 +908,7 @@ pub enum ClipMaskKind { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Clone)] +#[derive(Debug, Clone, MallocSizeOf)] pub struct BrushSegment { pub local_rect: LayoutRect, pub may_need_clip_mask: bool, @@ -1191,7 +1198,7 @@ impl ClipData { /// A hashable descriptor for nine-patches, used by image and /// gradient borders. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, MallocSizeOf)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct NinePatchDescriptor { diff --git a/webrender/src/prim_store/picture.rs b/webrender/src/prim_store/picture.rs index 2ea28ccc3b..06a341ec0e 100644 --- a/webrender/src/prim_store/picture.rs +++ b/webrender/src/prim_store/picture.rs @@ -19,7 +19,7 @@ use prim_store::{ /// will be composited into its parent. #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Clone, PartialEq, Hash, Eq)] +#[derive(Debug, Clone, MallocSizeOf, PartialEq, Hash, Eq)] pub enum PictureCompositeKey { // No visual compositing effect Identity, @@ -127,7 +127,7 @@ impl From> for PictureCompositeKey { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Clone, Eq, PartialEq, Hash)] +#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)] pub struct Picture { pub composite_mode_key: PictureCompositeKey, } @@ -171,6 +171,7 @@ impl AsInstanceKind for PictureKey { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] +#[derive(MallocSizeOf)] pub struct PictureData; pub type PictureTemplate = PrimTemplate; @@ -188,7 +189,7 @@ impl From for PictureTemplate { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)] pub struct PictureDataMarker; pub type PictureDataStore = DataStore; diff --git a/webrender/src/prim_store/text_run.rs b/webrender/src/prim_store/text_run.rs index dc79060bfd..7deeaf16b4 100644 --- a/webrender/src/prim_store/text_run.rs +++ b/webrender/src/prim_store/text_run.rs @@ -23,7 +23,7 @@ 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, PartialEq, Hash)] +#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)] pub struct TextRunKey { pub common: PrimKeyCommonData, pub font: FontInstance, @@ -73,6 +73,7 @@ impl AsInstanceKind for TextRunKey { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] +#[derive(MallocSizeOf)] pub struct TextRunTemplate { pub common: PrimTemplateCommonData, pub font: FontInstance, @@ -161,7 +162,7 @@ impl TextRunTemplate { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)] pub struct TextRunDataMarker; pub type TextRunDataStore = intern::DataStore; diff --git a/webrender/src/render_task.rs b/webrender/src/render_task.rs index 5ef5544447..f590111326 100644 --- a/webrender/src/render_task.rs +++ b/webrender/src/render_task.rs @@ -1113,7 +1113,7 @@ pub struct RenderTaskCacheEntry { pub handle: TextureCacheHandle, } -#[derive(Debug)] +#[derive(Debug, MallocSizeOf)] pub enum RenderTaskCacheMarker {} // A cache of render tasks that are stored in the texture diff --git a/webrender/src/scene_builder.rs b/webrender/src/scene_builder.rs index 918f7faf1d..4abaf35209 100644 --- a/webrender/src/scene_builder.rs +++ b/webrender/src/scene_builder.rs @@ -15,7 +15,7 @@ use clip_scroll_tree::ClipScrollTree; use display_list_flattener::DisplayListFlattener; use intern::{Internable, Interner}; use internal_types::{FastHashMap, FastHashSet}; -use malloc_size_of::MallocSizeOfOps; +use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; use prim_store::{PrimitiveDataInterner, PrimitiveDataUpdateList, PrimitiveKeyKind}; use prim_store::PrimitiveStoreStats; use prim_store::borders::{ diff --git a/webrender_api/src/api.rs b/webrender_api/src/api.rs index dae80eb534..eebeabfebb 100644 --- a/webrender_api/src/api.rs +++ b/webrender_api/src/api.rs @@ -1289,7 +1289,7 @@ impl ZoomFactor { } #[repr(C)] -#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, Eq, Hash)] +#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash)] pub struct PropertyBindingId { namespace: IdNamespace, uid: u32, diff --git a/webrender_api/src/color.rs b/webrender_api/src/color.rs index bdda69e819..bc8cd07105 100644 --- a/webrender_api/src/color.rs +++ b/webrender_api/src/color.rs @@ -39,7 +39,7 @@ impl PremultipliedColorF { /// 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, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)] pub struct ColorF { pub r: f32, pub g: f32, @@ -112,7 +112,7 @@ impl Hash for PremultipliedColorF { /// /// If the alpha value `a` is 255 the color is opaque. #[repr(C)] -#[derive(Clone, Copy, Hash, Eq, Debug, Deserialize, PartialEq, PartialOrd, Ord, Serialize)] +#[derive(Clone, Copy, Hash, Eq, Debug, Deserialize, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)] pub struct ColorU { pub r: u8, pub g: u8, diff --git a/webrender_api/src/display_item.rs b/webrender_api/src/display_item.rs index 6932175b3e..0559f4323f 100644 --- a/webrender_api/src/display_item.rs +++ b/webrender_api/src/display_item.rs @@ -247,14 +247,14 @@ pub struct LineDisplayItem { } #[repr(u8)] -#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, Eq, Hash)] +#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash)] pub enum LineOrientation { Vertical, Horizontal, } #[repr(u8)] -#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, Eq, Hash)] +#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash)] pub enum LineStyle { Solid, Dotted, @@ -269,7 +269,7 @@ pub struct TextDisplayItem { pub glyph_options: Option, } // IMPLICIT: glyphs: Vec -#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)] pub struct NormalBorder { pub left: BorderSide, pub right: BorderSide, @@ -328,7 +328,7 @@ impl NormalBorder { } #[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize, Eq, Hash)] +#[derive(Debug, Copy, Clone, MallocSizeOf, PartialEq, Serialize, Deserialize, Eq, Hash)] pub enum RepeatMode { Stretch, Repeat, @@ -410,14 +410,14 @@ pub struct BorderRadius { } #[repr(C)] -#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)] pub struct BorderSide { pub color: ColorF, pub style: BorderStyle, } #[repr(u32)] -#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, Hash, Eq)] +#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Hash, Eq)] pub enum BorderStyle { None = 0, Solid = 1, @@ -438,7 +438,7 @@ impl BorderStyle { } #[repr(u32)] -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] pub enum BoxShadowClipMode { Outset = 0, Inset = 1, @@ -464,7 +464,7 @@ pub struct Shadow { } #[repr(u8)] -#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Ord, PartialOrd)] +#[derive(Debug, Copy, Clone, Hash, Eq, MallocSizeOf, PartialEq, Serialize, Deserialize, Ord, PartialOrd)] pub enum ExtendMode { Clamp, Repeat, @@ -485,7 +485,7 @@ pub struct GradientDisplayItem { } #[repr(C)] -#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)] pub struct GradientStop { pub offset: f32, pub color: ColorF, @@ -659,14 +659,14 @@ pub struct ImageDisplayItem { } #[repr(u32)] -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] pub enum ImageRendering { Auto = 0, CrispEdges = 1, Pixelated = 2, } -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] pub enum AlphaType { Alpha = 0, PremultipliedAlpha = 1, @@ -681,7 +681,7 @@ pub struct YuvImageDisplayItem { } #[repr(u32)] -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] pub enum YuvColorSpace { Rec601 = 0, Rec709 = 1, @@ -704,7 +704,7 @@ impl YuvData { } } -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] pub enum YuvFormat { NV12 = 0, PlanarYCbCr = 1, diff --git a/webrender_api/src/font.rs b/webrender_api/src/font.rs index b8c1cd914e..8ab85721ae 100644 --- a/webrender_api/src/font.rs +++ b/webrender_api/src/font.rs @@ -71,7 +71,7 @@ pub struct GlyphDimensions { } #[repr(C)] -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, Ord, PartialOrd)] +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, Ord, PartialOrd)] pub struct FontKey(pub IdNamespace, pub u32); impl FontKey { @@ -94,7 +94,7 @@ pub enum FontTemplate { } #[repr(u32)] -#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Ord, PartialOrd)] +#[derive(Debug, Copy, Clone, Hash, Eq, MallocSizeOf, PartialEq, Serialize, Deserialize, Ord, PartialOrd)] pub enum FontRenderMode { Mono = 0, Alpha, @@ -112,7 +112,7 @@ impl FontRenderMode { } #[repr(C)] -#[derive(Clone, Copy, Debug, PartialOrd, Deserialize, Serialize)] +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialOrd, Deserialize, Serialize)] pub struct FontVariation { pub tag: u32, pub value: f32, @@ -159,7 +159,7 @@ impl Default for GlyphOptions { bitflags! { #[repr(C)] - #[derive(Deserialize, Serialize)] + #[derive(Deserialize, MallocSizeOf, Serialize)] pub struct FontInstanceFlags: u32 { // Common flags const SYNTHETIC_BOLD = 1 << 1; @@ -204,7 +204,7 @@ impl Default for FontInstanceFlags { #[repr(C)] -#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)] pub struct SyntheticItalics { // Angle in degrees (-90..90) for synthetic italics in 8.8 fixed-point. pub angle: i16, @@ -273,7 +273,7 @@ impl Default for FontInstanceOptions { #[cfg(target_os = "windows")] #[repr(C)] -#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)] pub struct FontInstancePlatformOptions { pub gamma: u16, // percent pub contrast: u16, // percent @@ -291,7 +291,7 @@ impl Default for FontInstancePlatformOptions { #[cfg(target_os = "macos")] #[repr(C)] -#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)] pub struct FontInstancePlatformOptions { pub unused: u32, } @@ -307,7 +307,7 @@ impl Default for FontInstancePlatformOptions { #[cfg(not(any(target_os = "macos", target_os = "windows")))] #[repr(u8)] -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)] pub enum FontLCDFilter { None, Default, @@ -317,7 +317,7 @@ pub enum FontLCDFilter { #[cfg(not(any(target_os = "macos", target_os = "windows")))] #[repr(u8)] -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)] pub enum FontHinting { None, Mono, @@ -328,7 +328,7 @@ pub enum FontHinting { #[cfg(not(any(target_os = "macos", target_os = "windows")))] #[repr(C)] -#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)] pub struct FontInstancePlatformOptions { pub lcd_filter: FontLCDFilter, pub hinting: FontHinting, @@ -370,7 +370,7 @@ pub struct FontInstanceData { pub type GlyphIndex = u32; #[repr(C)] -#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)] pub struct GlyphInstance { pub index: GlyphIndex, pub point: LayoutPoint, diff --git a/webrender_api/src/image.rs b/webrender_api/src/image.rs index d3f4ac8ee7..6ce0401a1e 100644 --- a/webrender_api/src/image.rs +++ b/webrender_api/src/image.rs @@ -17,7 +17,7 @@ use std::ops::{Add, Sub}; /// 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, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] pub struct ImageKey(pub IdNamespace, pub u32); impl ImageKey { @@ -137,7 +137,7 @@ impl ImageFormat { /// Specifies the color depth of an image. Currently only used for YUV images. #[repr(u8)] -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] pub enum ColorDepth { /// 8 bits image (most common) Color8, From 8cedfb794071f6c096f816543658db272596d215 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Sat, 12 Jan 2019 19:22:03 +0000 Subject: [PATCH 4/9] Bug 1519454 - Use a macro to declare interners and hook up memory reporters. r=emilio Depends on D16355 Differential Revision: https://phabricator.services.mozilla.com/D16356 [wrupdater] From https://hg.mozilla.org/mozilla-central/rev/21d74c03c00a986914f5dc6ad44e5027b186f049 --- webrender/src/intern.rs | 18 --------- webrender/src/lib.rs | 1 + webrender/src/render_backend.rs | 59 +++++++++++++---------------- webrender/src/scene_builder.rs | 66 +++++++++++++++------------------ webrender_api/src/api.rs | 59 ++++++++++++++++++++++++++--- 5 files changed, 110 insertions(+), 93 deletions(-) diff --git a/webrender/src/intern.rs b/webrender/src/intern.rs index 0255aa6669..0d51ffb69a 100644 --- a/webrender/src/intern.rs +++ b/webrender/src/intern.rs @@ -3,7 +3,6 @@ * 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; @@ -11,7 +10,6 @@ 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; @@ -198,11 +196,6 @@ where 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 @@ -404,17 +397,6 @@ where 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 diff --git a/webrender/src/lib.rs b/webrender/src/lib.rs index 771d073ea0..65f7dfe743 100644 --- a/webrender/src/lib.rs +++ b/webrender/src/lib.rs @@ -198,6 +198,7 @@ extern crate png; #[cfg(test)] extern crate rand; +#[macro_use] pub extern crate webrender_api; extern crate webrender_build; diff --git a/webrender/src/render_backend.rs b/webrender/src/render_backend.rs index 0ab80dea8b..07a55efc72 100644 --- a/webrender/src/render_backend.rs +++ b/webrender/src/render_backend.rs @@ -14,7 +14,7 @@ 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, VoidPtrToSizeFn}; +use api::{MemoryReport}; use api::{ScrollLocation, ScrollNodeState, TransactionMsg, ResourceUpdate, BlobImageKey}; use api::{NotificationRequest, Checkpoint}; use api::channel::{MsgReceiver, MsgSender, Payload}; @@ -214,30 +214,32 @@ impl FrameStamp { }; } -// 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, - - /// 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, +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, + )+ + } + + 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); + )+ + } + } + } } +enumerate_interners!(declare_frame_resources); + impl FrameResources { pub fn as_common_data( &self, @@ -287,15 +289,6 @@ impl FrameResources { } } } - - /// 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 { @@ -1564,7 +1557,7 @@ impl RenderBackend { } report.hit_testers += doc.hit_tester.size_of(ops); - doc.resources.report_memory(op, &mut report) + doc.resources.report_memory(ops, &mut report) } report += self.resource_cache.report_memory(op); diff --git a/webrender/src/scene_builder.rs b/webrender/src/scene_builder.rs index 4abaf35209..41ca3c75bb 100644 --- a/webrender/src/scene_builder.rs +++ b/webrender/src/scene_builder.rs @@ -194,46 +194,40 @@ pub enum SceneSwapResult { Aborted, } -// 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, -} +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, + )+ + } -impl DocumentResources { - /// Reports CPU heap memory used by the interners. - fn report_memory( - &self, - ops: &mut MallocSizeOfOps, - r: &mut MemoryReport, - ) { - let op = ops.size_of_op; - let eop = ops.enclosing_size_of_op.unwrap(); - 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); + 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); + )+ + } + } } } +enumerate_interners!(declare_document_resources); + // Access to `DocumentResources` interners by `Internable` pub trait InternerMut { diff --git a/webrender_api/src/api.rs b/webrender_api/src/api.rs index eebeabfebb..a72e8e3d60 100644 --- a/webrender_api/src/api.rs +++ b/webrender_api/src/api.rs @@ -816,14 +816,63 @@ impl PipelineId { } } +/// 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, @@ -833,8 +882,7 @@ pub struct MemoryReport { pub images: usize, pub rasterized_blobs: usize, pub shader_cache: usize, - pub data_stores: usize, - pub interners: usize, + pub interning: InterningMemoryReport, // // GPU memory. @@ -849,7 +897,6 @@ pub struct MemoryReport { 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; @@ -859,8 +906,8 @@ impl ::std::ops::AddAssign for MemoryReport { self.images += other.images; self.rasterized_blobs += other.rasterized_blobs; self.shader_cache += other.shader_cache; - self.data_stores += other.data_stores; - self.interners += other.interners; + self.interning += other.interning; + self.gpu_cache_textures += other.gpu_cache_textures; self.vertex_data_textures += other.vertex_data_textures; self.render_target_textures += other.render_target_textures; From d2baa7b9a2ded481c7fc45616c7a067546816e4d Mon Sep 17 00:00:00 2001 From: Bogdan Tara Date: Sat, 12 Jan 2019 21:54:54 +0200 Subject: [PATCH 5/9] 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) [wrupdater] From https://hg.mozilla.org/mozilla-central/rev/5d2e7b3ecb63f0770d409abd397b93af5c0b3fd7 --- Cargo.lock | 35 --- webrender/Cargo.toml | 2 - webrender/src/border.rs | 8 +- webrender/src/box_shadow.rs | 4 +- webrender/src/clip.rs | 36 ++- webrender/src/clip_scroll_tree.rs | 2 +- webrender/src/freelist.rs | 3 +- webrender/src/glyph_rasterizer/mod.rs | 4 +- webrender/src/gpu_cache.rs | 42 ++- webrender/src/gpu_types.rs | 5 +- webrender/src/hit_test.rs | 31 +- webrender/src/intern.rs | 81 +++-- webrender/src/lib.rs | 6 - webrender/src/prim_store/borders.rs | 12 +- webrender/src/prim_store/gradient.rs | 14 +- webrender/src/prim_store/image.rs | 12 +- webrender/src/prim_store/line_dec.rs | 7 +- webrender/src/prim_store/mod.rs | 41 +-- webrender/src/prim_store/picture.rs | 7 +- webrender/src/prim_store/text_run.rs | 5 +- webrender/src/render_backend.rs | 82 ++--- webrender/src/render_task.rs | 2 +- webrender/src/renderer.rs | 29 +- webrender/src/resource_cache.rs | 7 - webrender/src/scene_builder.rs | 84 ++--- webrender/src/util.rs | 4 +- webrender_api/Cargo.toml | 2 - webrender_api/src/api.rs | 71 +---- webrender_api/src/color.rs | 4 +- webrender_api/src/display_item.rs | 30 +- webrender_api/src/font.rs | 22 +- webrender_api/src/image.rs | 4 +- webrender_api/src/lib.rs | 4 - webrender_api/src/units.rs | 4 +- wr_malloc_size_of/Cargo.toml | 12 - wr_malloc_size_of/LICENSE-APACHE | 201 ------------ wr_malloc_size_of/LICENSE-MIT | 23 -- wr_malloc_size_of/lib.rs | 435 -------------------------- 38 files changed, 314 insertions(+), 1063 deletions(-) delete mode 100644 wr_malloc_size_of/Cargo.toml delete mode 100644 wr_malloc_size_of/LICENSE-APACHE delete mode 100644 wr_malloc_size_of/LICENSE-MIT delete mode 100644 wr_malloc_size_of/lib.rs diff --git a/Cargo.lock b/Cargo.lock index f445fdf90d..22c42cb877 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -757,16 +757,6 @@ 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" @@ -1330,17 +1320,6 @@ dependencies = [ "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" @@ -1574,7 +1553,6 @@ dependencies = [ "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)", @@ -1594,7 +1572,6 @@ dependencies = [ "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)", ] @@ -1625,12 +1602,10 @@ dependencies = [ "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]] @@ -1699,14 +1674,6 @@ dependencies = [ "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" @@ -1894,7 +1861,6 @@ dependencies = [ "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" @@ -1959,7 +1925,6 @@ dependencies = [ "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" diff --git a/webrender/Cargo.toml b/webrender/Cargo.toml index 5d83ba28f1..caf620bb7f 100644 --- a/webrender/Cargo.toml +++ b/webrender/Cargo.toml @@ -34,7 +34,6 @@ 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" } @@ -48,7 +47,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] diff --git a/webrender/src/border.rs b/webrender/src/border.rs index 397d696937..c07d1a27ad 100644 --- a/webrender/src/border.rs +++ b/webrender/src/border.rs @@ -34,7 +34,7 @@ pub const MAX_DASH_COUNT: u32 = 2048; // 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 { @@ -66,7 +66,7 @@ impl From for BorderRadius { } } -#[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 { @@ -94,7 +94,7 @@ impl From for BorderSide { #[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, @@ -148,7 +148,7 @@ impl From for ApiNormalBorder { /// 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 { diff --git a/webrender/src/box_shadow.rs b/webrender/src/box_shadow.rs index db04712aa0..f14a526423 100644 --- a/webrender/src/box_shadow.rs +++ b/webrender/src/box_shadow.rs @@ -12,7 +12,7 @@ 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 { @@ -51,7 +51,7 @@ 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 { diff --git a/webrender/src/clip.rs b/webrender/src/clip.rs index 183871f9bf..bfba1ad729 100644 --- a/webrender/src/clip.rs +++ b/webrender/src/clip.rs @@ -6,7 +6,7 @@ use api::{BorderRadius, ClipMode, ComplexClipRegion, DeviceIntRect, DevicePixelS 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}; @@ -22,6 +22,7 @@ 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}; /* @@ -106,7 +107,7 @@ use util::{extract_inner_rect_safe, project_rect, ScaleOffset}; // 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; @@ -133,7 +134,6 @@ enum ClipResult { #[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, @@ -186,7 +186,6 @@ impl From for ClipNode { 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; @@ -196,7 +195,7 @@ bitflags! { // 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 @@ -210,7 +209,7 @@ impl ClipChainId { // 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, @@ -224,7 +223,7 @@ pub struct ClipChainNode { // 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 { @@ -251,7 +250,7 @@ pub struct ClipNodeRange { // todo(gw): optimize: // separate arrays for matrices // cache and only build as needed. -#[derive(Debug, MallocSizeOf)] +#[derive(Debug)] enum ClipSpaceConversion { Local, ScaleOffset(ScaleOffset), @@ -260,7 +259,6 @@ enum ClipSpaceConversion { // Temporary information that is cached and reused // during building of a clip chain instance. -#[derive(MallocSizeOf)] struct ClipNodeInfo { conversion: ClipSpaceConversion, handle: ClipDataHandle, @@ -436,8 +434,7 @@ impl ClipNode { } } -/// 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, clip_node_instances: Vec, @@ -711,6 +708,17 @@ impl ClipStore { 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 { @@ -782,7 +790,7 @@ impl ClipRegion> { // 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 { @@ -845,7 +853,7 @@ impl ClipItemKey { 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 { @@ -1279,7 +1287,7 @@ pub fn project_inner_rect( // 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, diff --git a/webrender/src/clip_scroll_tree.rs b/webrender/src/clip_scroll_tree.rs index 8040d421a6..ea0c212ebc 100644 --- a/webrender/src/clip_scroll_tree.rs +++ b/webrender/src/clip_scroll_tree.rs @@ -41,7 +41,7 @@ impl CoordinateSystem { } } -#[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); diff --git a/webrender/src/freelist.rs b/webrender/src/freelist.rs index bcff127fec..faec9b7109 100644 --- a/webrender/src/freelist.rs +++ b/webrender/src/freelist.rs @@ -23,7 +23,7 @@ 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); @@ -96,7 +96,6 @@ impl PartialEq for WeakFreeListHandle { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(MallocSizeOf)] pub struct WeakFreeListHandle { index: u32, epoch: Epoch, diff --git a/webrender/src/glyph_rasterizer/mod.rs b/webrender/src/glyph_rasterizer/mod.rs index 2c7dc7081c..78b0265908 100644 --- a/webrender/src/glyph_rasterizer/mod.rs +++ b/webrender/src/glyph_rasterizer/mod.rs @@ -28,7 +28,7 @@ pub use self::pathfinder::{ThreadSafePathfinderFontContext, NativeFontHandleWrap #[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 { @@ -164,7 +164,7 @@ impl<'a> From<&'a LayoutToWorldTransform> for FontTransform { // 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 { diff --git a/webrender/src/gpu_cache.rs b/webrender/src/gpu_cache.rs index 1ce2544186..49e9f7dfc6 100644 --- a/webrender/src/gpu_cache.rs +++ b/webrender/src/gpu_cache.rs @@ -25,6 +25,7 @@ //! for this frame. use api::{DebugFlags, DocumentId, PremultipliedColorF, IdNamespace, TexelRect}; +use api::{VoidPtrToSizeFn}; use euclid::TypedRect; use internal_types::{FastHashMap}; use profiler::GpuCacheProfileCounters; @@ -33,6 +34,7 @@ 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}; @@ -53,7 +55,7 @@ const RECLAIM_THRESHOLD: f32 = 0.2; /// 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); @@ -64,7 +66,7 @@ impl Epoch { } } -#[derive(Debug, Copy, Clone, MallocSizeOf)] +#[derive(Debug, Copy, Clone)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] struct CacheLocation { @@ -73,7 +75,7 @@ struct CacheLocation { } /// 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 { @@ -129,7 +131,7 @@ pub trait ToGpuBlocks { } // 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 { @@ -145,7 +147,7 @@ impl GpuCacheHandle { // 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 { @@ -181,7 +183,7 @@ impl Add for GpuCacheAddress { } // 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 { @@ -233,7 +235,7 @@ impl Block { /// /// Because we use Option 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); @@ -252,7 +254,6 @@ impl BlockIndex { // 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. @@ -275,7 +276,6 @@ impl Row { // 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, @@ -286,7 +286,6 @@ pub enum GpuCacheUpdate { /// 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), @@ -294,7 +293,7 @@ pub enum GpuCacheDebugCmd { Free(GpuCacheAddress), } -#[derive(Clone, MallocSizeOf)] +#[derive(Clone)] pub struct GpuCacheDebugChunk { pub address: GpuCacheAddress, pub size: usize, @@ -303,7 +302,6 @@ pub struct GpuCacheDebugChunk { #[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, @@ -327,7 +325,6 @@ pub struct GpuCacheUpdateList { // 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, free_list_2: Option, @@ -395,7 +392,6 @@ impl FreeBlockLists { // 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, @@ -460,6 +456,18 @@ impl Texture { } } + // 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. @@ -664,7 +672,6 @@ impl<'a> Drop for GpuDataRequest<'a> { /// 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, @@ -858,6 +865,11 @@ impl GpuCache { 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] diff --git a/webrender/src/gpu_types.rs b/webrender/src/gpu_types.rs index 6c7d7214c5..5f37271fe7 100644 --- a/webrender/src/gpu_types.rs +++ b/webrender/src/gpu_types.rs @@ -59,7 +59,7 @@ pub enum RasterizationSpace { 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)] @@ -96,7 +96,7 @@ pub struct ScalingInstance { 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))] @@ -317,7 +317,6 @@ bitflags! { /// 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; diff --git a/webrender/src/hit_test.rs b/webrender/src/hit_test.rs index d44f4128f1..56f917b0b2 100644 --- a/webrender/src/hit_test.rs +++ b/webrender/src/hit_test.rs @@ -3,19 +3,19 @@ * 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, @@ -27,7 +27,6 @@ pub struct HitTestSpatialNode { 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. @@ -65,21 +64,20 @@ impl HitTestClipNode { // 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, @@ -98,10 +96,9 @@ impl HitTestingItem { } } -#[derive(Clone, MallocSizeOf)] +#[derive(Clone)] pub struct HitTestingRun(pub Vec, pub ScrollNodeAndClipChain); -#[derive(MallocSizeOf)] enum HitTestRegion { Invalid, Rectangle(LayoutRect, ClipMode), @@ -124,7 +121,6 @@ impl HitTestRegion { } } -#[derive(MallocSizeOf)] pub struct HitTester { runs: Vec, spatial_nodes: Vec, @@ -375,15 +371,28 @@ impl HitTester { 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, point: WorldPoint, diff --git a/webrender/src/intern.rs b/webrender/src/intern.rs index 0d51ffb69a..f37742948f 100644 --- a/webrender/src/intern.rs +++ b/webrender/src/intern.rs @@ -3,13 +3,14 @@ * 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; @@ -50,7 +51,7 @@ use util::VecHelper; /// 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 { @@ -75,7 +76,7 @@ lazy_static! { /// 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, } @@ -89,7 +90,7 @@ impl ItemUid { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Copy, Clone, MallocSizeOf)] +#[derive(Debug, Copy, Clone)] pub struct Handle { index: u32, epoch: Epoch, @@ -105,7 +106,6 @@ impl Handle where M: Copy { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(MallocSizeOf)] pub enum UpdateKind { Insert, Remove, @@ -114,7 +114,6 @@ pub enum UpdateKind { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(MallocSizeOf)] pub struct Update { index: usize, kind: UpdateKind, @@ -124,8 +123,7 @@ pub struct Update { /// correct access patterns. #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(MallocSizeOf)] -struct Item { +struct Item { epoch: Epoch, data: T, } @@ -138,18 +136,13 @@ pub trait InternDebug { /// 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 { +pub struct DataStore { items: Vec>, _source: PhantomData, _marker: PhantomData, } -impl ::std::default::Default for DataStore -where - S: Debug + MallocSizeOf, - T: From + MallocSizeOf, - M: Debug +impl ::std::default::Default for DataStore where S: Debug, T: From, M: Debug { fn default() -> Self { DataStore { @@ -160,11 +153,7 @@ where } } -impl DataStore -where - S: Debug + MallocSizeOf, - T: From + MallocSizeOf, - M: Debug +impl DataStore where S: Debug, T: From, M: Debug { /// Apply any updates from the scene builder thread to /// this data store. @@ -196,14 +185,16 @@ where 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 ops::Index> for DataStore -where - S: MallocSizeOf, - T: MallocSizeOf, - M: Copy +where M: Copy { type Output = T; fn index(&self, handle: Handle) -> &T { @@ -217,8 +208,6 @@ where /// Retrieve an item from the store via handle impl ops::IndexMut> for DataStore where - S: MallocSizeOf, - T: MallocSizeOf, M: Copy { fn index_mut(&mut self, handle: Handle) -> &mut T { @@ -235,12 +224,10 @@ where /// an update list of additions / removals. #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(MallocSizeOf)] pub struct Interner 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>, @@ -259,9 +246,8 @@ where impl ::std::default::Default for Interner 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 { @@ -277,9 +263,8 @@ where impl Interner 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 @@ -397,14 +382,24 @@ where 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 ops::Index> for Interner 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) -> &D { @@ -418,10 +413,10 @@ where /// /// see DisplayListFlattener::add_interned_primitive

pub trait Internable { - type Marker: Copy + Debug + MallocSizeOf; - type Source: Eq + Hash + Clone + Debug + MallocSizeOf; - type StoreData: From + MallocSizeOf; - type InternData: MallocSizeOf; + type Marker: Copy + Debug; + type Source: Eq + Hash + Clone + Debug; + type StoreData: From; + type InternData; /// Build a new key from self with `info`. fn build_key( diff --git a/webrender/src/lib.rs b/webrender/src/lib.rs index 65f7dfe743..c3f8e16dc0 100644 --- a/webrender/src/lib.rs +++ b/webrender/src/lib.rs @@ -58,17 +58,12 @@ extern crate cfg_if; 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; @@ -198,7 +193,6 @@ extern crate png; #[cfg(test)] extern crate rand; -#[macro_use] pub extern crate webrender_api; extern crate webrender_build; diff --git a/webrender/src/prim_store/borders.rs b/webrender/src/prim_store/borders.rs index e18b6f925e..81b39c7dc5 100644 --- a/webrender/src/prim_store/borders.rs +++ b/webrender/src/prim_store/borders.rs @@ -24,7 +24,7 @@ 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, @@ -67,7 +67,6 @@ impl AsInstanceKind for NormalBorderKey { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(MallocSizeOf)] pub struct NormalBorderData { pub brush_segments: Vec, pub border_segments: Vec, @@ -162,7 +161,7 @@ impl From for NormalBorderTemplate { #[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; @@ -210,9 +209,8 @@ impl IsVisible for NormalBorderPrim { #[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, } @@ -253,9 +251,7 @@ impl AsInstanceKind for ImageBorderKey { #[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, } @@ -343,7 +339,7 @@ impl From for ImageBorderTemplate { #[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; diff --git a/webrender/src/prim_store/gradient.rs b/webrender/src/prim_store/gradient.rs index d102ca01df..dd514146c5 100644 --- a/webrender/src/prim_store/gradient.rs +++ b/webrender/src/prim_store/gradient.rs @@ -20,7 +20,7 @@ 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, @@ -38,7 +38,7 @@ impl hash::Hash for GradientStopKey { /// 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, @@ -95,7 +95,6 @@ impl AsInstanceKind for LinearGradientKey { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(MallocSizeOf)] pub struct LinearGradientTemplate { pub common: PrimTemplateCommonData, pub extend_mode: ExtendMode, @@ -229,7 +228,7 @@ impl LinearGradientTemplate { #[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; @@ -280,7 +279,7 @@ 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, @@ -300,7 +299,7 @@ impl hash::Hash for RadialGradientParams { /// 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, @@ -355,7 +354,6 @@ impl AsInstanceKind for RadialGradientKey { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(MallocSizeOf)] pub struct RadialGradientTemplate { pub common: PrimTemplateCommonData, pub extend_mode: ExtendMode, @@ -460,7 +458,7 @@ impl RadialGradientTemplate { #[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; diff --git a/webrender/src/prim_store/image.rs b/webrender/src/prim_store/image.rs index 7c4812493b..afdfc18c3b 100644 --- a/webrender/src/prim_store/image.rs +++ b/webrender/src/prim_store/image.rs @@ -67,7 +67,7 @@ pub struct ImageInstance { #[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, @@ -127,7 +127,7 @@ impl AsInstanceKind for ImageKey { // 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, @@ -141,7 +141,6 @@ pub enum ImageSource { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(MallocSizeOf)] pub struct ImageData { pub key: ApiImageKey, pub stretch_size: LayoutSize, @@ -337,7 +336,7 @@ impl From for ImageTemplate { #[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; @@ -390,7 +389,7 @@ impl IsVisible for Image { #[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], @@ -439,7 +438,6 @@ impl AsInstanceKind for YuvImageKey { #[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], @@ -515,7 +513,7 @@ impl From for YuvImageTemplate { #[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; diff --git a/webrender/src/prim_store/line_dec.rs b/webrender/src/prim_store/line_dec.rs index d56a6022db..8ddcdf085a 100644 --- a/webrender/src/prim_store/line_dec.rs +++ b/webrender/src/prim_store/line_dec.rs @@ -17,7 +17,7 @@ use prim_store::{ }; 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 { @@ -28,7 +28,7 @@ pub struct LineDecorationCacheKey { } /// 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 { @@ -77,7 +77,6 @@ impl AsInstanceKind for LineDecorationKey { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(MallocSizeOf)] pub struct LineDecorationData { pub cache_key: Option, pub color: ColorF, @@ -137,7 +136,7 @@ impl From for LineDecorationTemplate { #[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; diff --git a/webrender/src/prim_store/mod.rs b/webrender/src/prim_store/mod.rs index 0142983ccf..f59d39ab1b 100644 --- a/webrender/src/prim_store/mod.rs +++ b/webrender/src/prim_store/mod.rs @@ -28,7 +28,6 @@ use gpu_cache::{GpuCache, GpuCacheAddress, GpuCacheHandle, GpuDataRequest, ToGpu 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}; @@ -80,7 +79,7 @@ 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, @@ -100,7 +99,7 @@ impl ScrollNodeAndClipChain { #[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, } @@ -348,7 +347,6 @@ impl GpuCacheAddress { /// 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, @@ -359,7 +357,7 @@ pub struct PrimitiveSceneData { /// 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, @@ -370,7 +368,7 @@ pub enum PrimitiveKeyKind { #[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, @@ -412,7 +410,7 @@ impl From for RectangleKey { /// 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, @@ -467,7 +465,7 @@ impl From> for SideOffsetsKey { /// 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, @@ -500,7 +498,7 @@ impl From> for SizeKey { /// 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, @@ -533,7 +531,7 @@ impl From for VectorKey { /// 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, @@ -565,7 +563,7 @@ impl From for PointKey { #[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, @@ -587,15 +585,15 @@ impl PrimKeyCommonData { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)] -pub struct PrimKey { +#[derive(Debug, Clone, Eq, PartialEq, Hash)] +pub struct PrimKey { 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, @@ -650,7 +648,6 @@ impl AsInstanceKind for PrimitiveKey { /// 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, @@ -678,7 +675,6 @@ 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, @@ -705,7 +701,6 @@ impl PrimTemplateCommonData { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(MallocSizeOf)] pub struct PrimTemplate { pub common: PrimTemplateCommonData, pub kind: T, @@ -713,7 +708,6 @@ pub struct PrimTemplate { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(MallocSizeOf)] pub struct PrimitiveTemplate { pub common: PrimTemplateCommonData, pub kind: PrimitiveTemplateKind, @@ -786,7 +780,7 @@ 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 { @@ -852,7 +846,7 @@ impl OpacityBinding { } } -#[derive(Debug, MallocSizeOf)] +#[derive(Debug)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct VisibleMaskImageTile { @@ -871,7 +865,7 @@ pub struct VisibleGradientTile { /// 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, @@ -886,7 +880,6 @@ bitflags! { /// `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; @@ -908,7 +901,7 @@ pub enum ClipMaskKind { #[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, @@ -1198,7 +1191,7 @@ impl ClipData { /// 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 { diff --git a/webrender/src/prim_store/picture.rs b/webrender/src/prim_store/picture.rs index 06a341ec0e..2ea28ccc3b 100644 --- a/webrender/src/prim_store/picture.rs +++ b/webrender/src/prim_store/picture.rs @@ -19,7 +19,7 @@ use prim_store::{ /// 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, @@ -127,7 +127,7 @@ impl From> for PictureCompositeKey { #[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, } @@ -171,7 +171,6 @@ impl AsInstanceKind for PictureKey { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(MallocSizeOf)] pub struct PictureData; pub type PictureTemplate = PrimTemplate; @@ -189,7 +188,7 @@ impl From for PictureTemplate { #[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; diff --git a/webrender/src/prim_store/text_run.rs b/webrender/src/prim_store/text_run.rs index 7deeaf16b4..dc79060bfd 100644 --- a/webrender/src/prim_store/text_run.rs +++ b/webrender/src/prim_store/text_run.rs @@ -23,7 +23,7 @@ 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, @@ -73,7 +73,6 @@ impl AsInstanceKind for TextRunKey { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(MallocSizeOf)] pub struct TextRunTemplate { pub common: PrimTemplateCommonData, pub font: FontInstance, @@ -162,7 +161,7 @@ impl TextRunTemplate { #[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; diff --git a/webrender/src/render_backend.rs b/webrender/src/render_backend.rs index 07a55efc72..e881532cd3 100644 --- a/webrender/src/render_backend.rs +++ b/webrender/src/render_backend.rs @@ -14,7 +14,7 @@ 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}; @@ -30,7 +30,6 @@ 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}; @@ -89,7 +88,7 @@ impl DocumentView { } } -#[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); @@ -143,7 +142,7 @@ impl ::std::ops::Sub for FrameId { /// 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 { @@ -214,32 +213,30 @@ impl FrameStamp { }; } -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, - )+ - } - - 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); - )+ - } - } - } +// 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, + + /// 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, @@ -289,6 +286,15 @@ impl FrameResources { } } } + + /// 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 { @@ -673,7 +679,7 @@ pub struct RenderBackend { notifier: Box, recorder: Option>, sampler: Option>, - size_of_ops: Option, + size_of_op: Option, debug_flags: DebugFlags, namespace_alloc_by_client: bool, } @@ -692,7 +698,7 @@ impl RenderBackend { frame_config: FrameBuilderConfig, recorder: Option>, sampler: Option>, - size_of_ops: Option, + size_of_op: Option, debug_flags: DebugFlags, namespace_alloc_by_client: bool, ) -> RenderBackend { @@ -712,7 +718,7 @@ impl RenderBackend { notifier, recorder, sampler, - size_of_ops, + size_of_op, debug_flags, namespace_alloc_by_client, } @@ -1546,18 +1552,18 @@ impl RenderBackend { serde_json::to_string(&debug_root).unwrap() } - fn report_memory(&mut self, tx: MsgSender) { + fn report_memory(&self, tx: MsgSender) { 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); diff --git a/webrender/src/render_task.rs b/webrender/src/render_task.rs index f590111326..5ef5544447 100644 --- a/webrender/src/render_task.rs +++ b/webrender/src/render_task.rs @@ -1113,7 +1113,7 @@ pub struct RenderTaskCacheEntry { pub handle: TextureCacheHandle, } -#[derive(Debug, MallocSizeOf)] +#[derive(Debug)] pub enum RenderTaskCacheMarker {} // A cache of render tasks that are stored in the texture diff --git a/webrender/src/renderer.rs b/webrender/src/renderer.rs index 2df4124291..8e275175e8 100644 --- a/webrender/src/renderer.rs +++ b/webrender/src/renderer.rs @@ -59,7 +59,6 @@ use internal_types::{TextureSource, ORTHO_FAR_PLANE, ORTHO_NEAR_PLANE, ResourceC 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}; @@ -1557,9 +1556,17 @@ pub struct Renderer { /// copy the WR output to. output_image_handler: Option>, - /// 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, + size_of_op: Option, + + /// 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, // Currently allocated FBOs for output frames. output_targets: FastHashMap, @@ -1825,10 +1832,6 @@ impl Renderer { 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(); @@ -1854,6 +1857,8 @@ impl Renderer { 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(); @@ -1870,7 +1875,8 @@ impl Renderer { 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()); @@ -1943,7 +1949,7 @@ impl Renderer { config, recorder, sampler, - make_size_of_ops(), + size_of_op, debug_flags, namespace_alloc_by_client, ); @@ -2005,7 +2011,8 @@ impl Renderer { 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(), @@ -4565,7 +4572,7 @@ impl Renderer { } fn size_of(&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) } } diff --git a/webrender/src/resource_cache.rs b/webrender/src/resource_cache.rs index 04860c1def..3cb0db61f9 100644 --- a/webrender/src/resource_cache.rs +++ b/webrender/src/resource_cache.rs @@ -1821,13 +1821,6 @@ impl ResourceCache { } /// 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(); diff --git a/webrender/src/scene_builder.rs b/webrender/src/scene_builder.rs index 41ca3c75bb..1e8c4d82f6 100644 --- a/webrender/src/scene_builder.rs +++ b/webrender/src/scene_builder.rs @@ -5,7 +5,7 @@ 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; @@ -15,7 +15,6 @@ 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::{ @@ -194,40 +193,45 @@ pub enum SceneSwapResult { 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 { @@ -289,7 +293,8 @@ pub struct SceneBuilder { config: FrameBuilderConfig, hooks: Option>, simulate_slow_ms: u32, - size_of_ops: Option, + size_of_op: Option, + enclosing_size_of_op: Option, } impl SceneBuilder { @@ -297,7 +302,8 @@ impl SceneBuilder { config: FrameBuilderConfig, api_tx: MsgSender, hooks: Option>, - size_of_ops: Option, + size_of_op: Option, + enclosing_size_of_op: Option, ) -> (Self, Sender, Receiver) { let (in_tx, in_rx) = channel(); let (out_tx, out_rx) = channel(); @@ -309,7 +315,8 @@ impl SceneBuilder { api_tx, config, hooks, - size_of_ops, + size_of_op, + enclosing_size_of_op, simulate_slow_ms: 0, }, in_tx, @@ -756,11 +763,12 @@ impl SceneBuilder { } /// 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 diff --git a/webrender/src/util.rs b/webrender/src/util.rs index 9c6dd4e24f..ba94c2a28f 100644 --- a/webrender/src/util.rs +++ b/webrender/src/util.rs @@ -92,7 +92,7 @@ impl VecHelper for Vec { // 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, pub offset: Vector2D, @@ -556,7 +556,7 @@ impl MaxRect for TypedRect { /// 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 { /// A simple offset, which can be used without doing any matrix math. Offset(TypedVector2D), diff --git a/webrender_api/Cargo.toml b/webrender_api/Cargo.toml index be2d4109f4..db4063d984 100644 --- a/webrender_api/Cargo.toml +++ b/webrender_api/Cargo.toml @@ -19,12 +19,10 @@ 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" diff --git a/webrender_api/src/api.rs b/webrender_api/src/api.rs index a72e8e3d60..5838c24bc3 100644 --- a/webrender_api/src/api.rs +++ b/webrender_api/src/api.rs @@ -561,7 +561,7 @@ pub struct HitTestResult { } bitflags! { - #[derive(Deserialize, MallocSizeOf, Serialize)] + #[derive(Deserialize, Serialize)] pub struct HitTestFlags: u8 { const FIND_ALL = 0b00000001; const POINT_RELATIVE_TO_PIPELINE_VIEWPORT = 0b00000010; @@ -787,11 +787,11 @@ impl Epoch { } #[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 { @@ -807,7 +807,7 @@ 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 { @@ -816,63 +816,14 @@ impl PipelineId { } } -/// 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, @@ -882,7 +833,8 @@ pub struct MemoryReport { pub images: usize, pub rasterized_blobs: usize, pub shader_cache: usize, - pub interning: InterningMemoryReport, + pub data_stores: usize, + pub interners: usize, // // GPU memory. @@ -897,6 +849,7 @@ pub struct MemoryReport { 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; @@ -906,8 +859,8 @@ impl ::std::ops::AddAssign for MemoryReport { 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; @@ -1010,7 +963,7 @@ impl RenderApiSender { } 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; @@ -1336,7 +1289,7 @@ impl ZoomFactor { } #[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, diff --git a/webrender_api/src/color.rs b/webrender_api/src/color.rs index bc8cd07105..bdda69e819 100644 --- a/webrender_api/src/color.rs +++ b/webrender_api/src/color.rs @@ -39,7 +39,7 @@ impl PremultipliedColorF { /// 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, @@ -112,7 +112,7 @@ impl Hash for PremultipliedColorF { /// /// 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, diff --git a/webrender_api/src/display_item.rs b/webrender_api/src/display_item.rs index 0559f4323f..4df5f0a13f 100644 --- a/webrender_api/src/display_item.rs +++ b/webrender_api/src/display_item.rs @@ -247,14 +247,14 @@ pub struct LineDisplayItem { } #[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, @@ -269,7 +269,7 @@ pub struct TextDisplayItem { pub glyph_options: Option, } // IMPLICIT: glyphs: Vec -#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] pub struct NormalBorder { pub left: BorderSide, pub right: BorderSide, @@ -328,7 +328,7 @@ impl NormalBorder { } #[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, @@ -401,7 +401,7 @@ pub enum BorderRadiusKind { } #[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, @@ -410,14 +410,14 @@ pub struct BorderRadius { } #[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, @@ -438,7 +438,7 @@ impl BorderStyle { } #[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, @@ -464,7 +464,7 @@ pub struct Shadow { } #[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, @@ -485,7 +485,7 @@ pub struct GradientDisplayItem { } #[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, @@ -659,14 +659,14 @@ pub struct ImageDisplayItem { } #[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, @@ -681,7 +681,7 @@ pub struct YuvImageDisplayItem { } #[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, @@ -704,7 +704,7 @@ impl YuvData { } } -#[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, @@ -741,7 +741,7 @@ impl ImageMask { } #[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. diff --git a/webrender_api/src/font.rs b/webrender_api/src/font.rs index 8ab85721ae..b8c1cd914e 100644 --- a/webrender_api/src/font.rs +++ b/webrender_api/src/font.rs @@ -71,7 +71,7 @@ pub struct GlyphDimensions { } #[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 { @@ -94,7 +94,7 @@ pub enum FontTemplate { } #[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, @@ -112,7 +112,7 @@ impl FontRenderMode { } #[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, @@ -159,7 +159,7 @@ impl Default for GlyphOptions { bitflags! { #[repr(C)] - #[derive(Deserialize, MallocSizeOf, Serialize)] + #[derive(Deserialize, Serialize)] pub struct FontInstanceFlags: u32 { // Common flags const SYNTHETIC_BOLD = 1 << 1; @@ -204,7 +204,7 @@ impl Default for FontInstanceFlags { #[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, @@ -273,7 +273,7 @@ impl Default for FontInstanceOptions { #[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 @@ -291,7 +291,7 @@ impl Default for FontInstancePlatformOptions { #[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, } @@ -307,7 +307,7 @@ impl Default for FontInstancePlatformOptions { #[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, @@ -317,7 +317,7 @@ pub enum FontLCDFilter { #[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, @@ -328,7 +328,7 @@ pub enum FontHinting { #[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, @@ -370,7 +370,7 @@ pub struct FontInstanceData { 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, diff --git a/webrender_api/src/image.rs b/webrender_api/src/image.rs index 6ce0401a1e..d3f4ac8ee7 100644 --- a/webrender_api/src/image.rs +++ b/webrender_api/src/image.rs @@ -17,7 +17,7 @@ use std::ops::{Add, Sub}; /// 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 { @@ -137,7 +137,7 @@ impl ImageFormat { /// 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, diff --git a/webrender_api/src/lib.rs b/webrender_api/src/lib.rs index 63be1f807a..6da3ff31c1 100644 --- a/webrender_api/src/lib.rs +++ b/webrender_api/src/lib.rs @@ -30,15 +30,11 @@ 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; diff --git a/webrender_api/src/units.rs b/webrender_api/src/units.rs index 3fcf4655de..8939a06075 100644 --- a/webrender_api/src/units.rs +++ b/webrender_api/src/units.rs @@ -65,7 +65,7 @@ pub type RasterVector2D = TypedVector2D; pub type RasterVector3D = TypedVector3D; /// 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; @@ -81,7 +81,7 @@ pub type LayoutIntPoint = TypedPoint2D; pub type LayoutIntSize = TypedSize2D; /// 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; diff --git a/wr_malloc_size_of/Cargo.toml b/wr_malloc_size_of/Cargo.toml deleted file mode 100644 index 48d1814997..0000000000 --- a/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" diff --git a/wr_malloc_size_of/LICENSE-APACHE b/wr_malloc_size_of/LICENSE-APACHE deleted file mode 100644 index 16fe87b06e..0000000000 --- a/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. diff --git a/wr_malloc_size_of/LICENSE-MIT b/wr_malloc_size_of/LICENSE-MIT deleted file mode 100644 index 31aa79387f..0000000000 --- a/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. diff --git a/wr_malloc_size_of/lib.rs b/wr_malloc_size_of/lib.rs deleted file mode 100644 index 1e05a8435b..0000000000 --- a/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 or the MIT license -// , 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, -} - -impl MallocSizeOfOps { - pub fn new( - size_of: VoidPtrToSizeFn, - malloc_enclosing_size_of: Option, - ) -> 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(ptr: *const T) -> bool { - // The correct condition is this: - // `ptr as usize <= ::std::mem::align_of::()` - // 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(&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(&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 MallocShallowSizeOf for Box { - fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize { - unsafe { ops.malloc_size_of(&**self) } - } -} - -impl MallocSizeOf for Box { - 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 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 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 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 MallocSizeOf for Option { - fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { - if let Some(val) = self.as_ref() { - val.size_of(ops) - } else { - 0 - } - } -} - -impl MallocSizeOf for Result { - 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 MallocSizeOf for std::cell::Cell { - fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { - self.get().size_of(ops) - } -} - -impl MallocSizeOf for std::cell::RefCell { - 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 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 MallocShallowSizeOf for Vec { - fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize { - unsafe { ops.malloc_size_of(self.as_ptr()) } - } -} - -impl MallocSizeOf for Vec { - 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 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::() + size_of::()) - } - } - } - - impl 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); - -macro_rules! malloc_size_of_hash_map { - ($ty:ty) => { - impl 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::() + size_of::() + size_of::()) - } - } - } - - impl 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); - -// PhantomData is always 0. -impl MallocSizeOf for std::marker::PhantomData { - fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize { - 0 - } -} - -impl MallocSizeOf for euclid::Length { - fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { - self.0.size_of(ops) - } -} - -impl MallocSizeOf for euclid::TypedScale { - fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { - self.0.size_of(ops) - } -} - -impl MallocSizeOf for euclid::TypedPoint2D { - fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { - self.x.size_of(ops) + self.y.size_of(ops) - } -} - -impl MallocSizeOf for euclid::TypedRect { - fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { - self.origin.size_of(ops) + self.size.size_of(ops) - } -} - -impl MallocSizeOf for euclid::TypedSideOffsets2D { - 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 MallocSizeOf for euclid::TypedSize2D { - fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { - self.width.size_of(ops) + self.height.size_of(ops) - } -} - -impl MallocSizeOf for euclid::TypedTransform2D { - 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 MallocSizeOf for euclid::TypedTransform3D { - 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 MallocSizeOf for euclid::TypedVector2D { - 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, Range, Range, Range, Range); -malloc_size_of_is_0!(Range, Range, Range, Range, Range); -malloc_size_of_is_0!(Range, Range); - -malloc_size_of_is_0!(app_units::Au); From e4b196c3d0a7c46229fc21d8929ba5a486eef76b Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Wed, 9 Jan 2019 12:14:21 -0800 Subject: [PATCH 6/9] Bug 1519454 - Put malloc_size_of_derive on crates.io, and add a reduced fork of malloc_size_of for WebRender. r=emilio Differential Revision: https://phabricator.services.mozilla.com/D16353 [wrupdater] From https://hg.mozilla.org/mozilla-central/rev/d5e192fd022fd4ced320499ba7d2f0229b9fa9f2 --- Cargo.lock | 35 +++ webrender/Cargo.toml | 2 + webrender_api/Cargo.toml | 2 + wr_malloc_size_of/Cargo.toml | 12 + wr_malloc_size_of/LICENSE-APACHE | 201 ++++++++++++++ wr_malloc_size_of/LICENSE-MIT | 23 ++ wr_malloc_size_of/lib.rs | 442 +++++++++++++++++++++++++++++++ 7 files changed, 717 insertions(+) create mode 100644 wr_malloc_size_of/Cargo.toml create mode 100644 wr_malloc_size_of/LICENSE-APACHE create mode 100644 wr_malloc_size_of/LICENSE-MIT create mode 100644 wr_malloc_size_of/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 22c42cb877..f445fdf90d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -757,6 +757,16 @@ 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" @@ -1320,6 +1330,17 @@ dependencies = [ "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" @@ -1553,6 +1574,7 @@ dependencies = [ "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)", @@ -1572,6 +1594,7 @@ dependencies = [ "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)", ] @@ -1602,10 +1625,12 @@ dependencies = [ "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]] @@ -1674,6 +1699,14 @@ dependencies = [ "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" @@ -1861,6 +1894,7 @@ dependencies = [ "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" @@ -1925,6 +1959,7 @@ dependencies = [ "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" diff --git a/webrender/Cargo.toml b/webrender/Cargo.toml index caf620bb7f..5d83ba28f1 100644 --- a/webrender/Cargo.toml +++ b/webrender/Cargo.toml @@ -34,6 +34,7 @@ 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" } @@ -47,6 +48,7 @@ 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] diff --git a/webrender_api/Cargo.toml b/webrender_api/Cargo.toml index db4063d984..be2d4109f4 100644 --- a/webrender_api/Cargo.toml +++ b/webrender_api/Cargo.toml @@ -19,10 +19,12 @@ 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" diff --git a/wr_malloc_size_of/Cargo.toml b/wr_malloc_size_of/Cargo.toml new file mode 100644 index 0000000000..48d1814997 --- /dev/null +++ b/wr_malloc_size_of/Cargo.toml @@ -0,0 +1,12 @@ +[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" diff --git a/wr_malloc_size_of/LICENSE-APACHE b/wr_malloc_size_of/LICENSE-APACHE new file mode 100644 index 0000000000..16fe87b06e --- /dev/null +++ b/wr_malloc_size_of/LICENSE-APACHE @@ -0,0 +1,201 @@ + 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. diff --git a/wr_malloc_size_of/LICENSE-MIT b/wr_malloc_size_of/LICENSE-MIT new file mode 100644 index 0000000000..31aa79387f --- /dev/null +++ b/wr_malloc_size_of/LICENSE-MIT @@ -0,0 +1,23 @@ +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. diff --git a/wr_malloc_size_of/lib.rs b/wr_malloc_size_of/lib.rs new file mode 100644 index 0000000000..e43fdb8d36 --- /dev/null +++ b/wr_malloc_size_of/lib.rs @@ -0,0 +1,442 @@ +// 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 or the MIT license +// , 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, +} + +impl MallocSizeOfOps { + pub fn new( + size_of: VoidPtrToSizeFn, + malloc_enclosing_size_of: Option, + ) -> 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(ptr: *const T) -> bool { + // The correct condition is this: + // `ptr as usize <= ::std::mem::align_of::()` + // 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(&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(&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<'a, T: ?Sized> MallocSizeOf for &'a T { + fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize { + // Zero makes sense for a non-owning reference. + 0 + } +} + +impl MallocShallowSizeOf for Box { + fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + unsafe { ops.malloc_size_of(&**self) } + } +} + +impl MallocSizeOf for Box { + 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 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 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 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 MallocSizeOf for Option { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + if let Some(val) = self.as_ref() { + val.size_of(ops) + } else { + 0 + } + } +} + +impl MallocSizeOf for Result { + 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 MallocSizeOf for std::cell::Cell { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + self.get().size_of(ops) + } +} + +impl MallocSizeOf for std::cell::RefCell { + 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 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 MallocShallowSizeOf for Vec { + fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + unsafe { ops.malloc_size_of(self.as_ptr()) } + } +} + +impl MallocSizeOf for Vec { + 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 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::() + size_of::()) + } + } + } + + impl 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); + +macro_rules! malloc_size_of_hash_map { + ($ty:ty) => { + impl 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::() + size_of::() + size_of::()) + } + } + } + + impl 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); + +// PhantomData is always 0. +impl MallocSizeOf for std::marker::PhantomData { + fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize { + 0 + } +} + +impl MallocSizeOf for euclid::Length { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + self.0.size_of(ops) + } +} + +impl MallocSizeOf for euclid::TypedScale { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + self.0.size_of(ops) + } +} + +impl MallocSizeOf for euclid::TypedPoint2D { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + self.x.size_of(ops) + self.y.size_of(ops) + } +} + +impl MallocSizeOf for euclid::TypedRect { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + self.origin.size_of(ops) + self.size.size_of(ops) + } +} + +impl MallocSizeOf for euclid::TypedSideOffsets2D { + 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 MallocSizeOf for euclid::TypedSize2D { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + self.width.size_of(ops) + self.height.size_of(ops) + } +} + +impl MallocSizeOf for euclid::TypedTransform2D { + 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 MallocSizeOf for euclid::TypedTransform3D { + 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 MallocSizeOf for euclid::TypedVector2D { + 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, Range, Range, Range, Range); +malloc_size_of_is_0!(Range, Range, Range, Range, Range); +malloc_size_of_is_0!(Range, Range); + +malloc_size_of_is_0!(app_units::Au); From b58943f6fcebb6785f1d1d18fb18faa6149479fa Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Wed, 9 Jan 2019 16:54:22 -0800 Subject: [PATCH 7/9] Bug 1519454 - Hook up MallocSizeOf and use it to replace some manual reporting. r=emilio Differential Revision: https://phabricator.services.mozilla.com/D16354 [wrupdater] From https://hg.mozilla.org/mozilla-central/rev/ed1842f02fe2c773dad9c5b7f40b28a8555a0dcd --- webrender/src/clip.rs | 31 +++++++++---------------- webrender/src/clip_scroll_tree.rs | 2 +- webrender/src/gpu_cache.rs | 38 +++++++++++-------------------- webrender/src/hit_test.rs | 31 +++++++++---------------- webrender/src/intern.rs | 6 ++--- webrender/src/lib.rs | 5 ++++ webrender/src/prim_store/mod.rs | 4 ++-- webrender/src/render_backend.rs | 23 ++++++++++--------- webrender/src/renderer.rs | 29 +++++++++-------------- webrender/src/resource_cache.rs | 7 ++++++ webrender/src/scene_builder.rs | 24 +++++++++---------- webrender/src/util.rs | 4 ++-- webrender_api/src/api.rs | 10 ++++---- webrender_api/src/display_item.rs | 4 ++-- webrender_api/src/lib.rs | 4 ++++ webrender_api/src/units.rs | 4 ++-- wr_malloc_size_of/lib.rs | 7 ------ 17 files changed, 102 insertions(+), 131 deletions(-) diff --git a/webrender/src/clip.rs b/webrender/src/clip.rs index bfba1ad729..364cbc888a 100644 --- a/webrender/src/clip.rs +++ b/webrender/src/clip.rs @@ -6,7 +6,7 @@ use api::{BorderRadius, ClipMode, ComplexClipRegion, DeviceIntRect, DevicePixelS use api::{ImageRendering, LayoutRect, LayoutSize, LayoutPoint, LayoutVector2D}; use api::{BoxShadowClipMode, LayoutToWorldScale, PicturePixel, WorldPixel}; use api::{PictureRect, LayoutPixel, WorldPoint, WorldSize, WorldRect, LayoutToWorldTransform}; -use api::{VoidPtrToSizeFn, ImageKey}; +use api::{ImageKey}; use app_units::Au; use border::{ensure_no_corner_overlap, BorderRadiusAu}; use box_shadow::{BLUR_SAMPLE_SCALE, BoxShadowClipSource, BoxShadowCacheKey}; @@ -22,7 +22,6 @@ 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}; /* @@ -107,7 +106,7 @@ use util::{extract_inner_rect_safe, project_rect, ScaleOffset}; // Type definitions for interning clip nodes. #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)] pub struct ClipDataMarker; pub type ClipDataStore = intern::DataStore; @@ -186,6 +185,7 @@ impl From for ClipNode { 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; @@ -195,7 +195,7 @@ bitflags! { // 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, PartialEq, Hash)] +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Hash)] pub struct ClipChainId(pub u32); // The root of each clip chain is the NONE id. The @@ -209,7 +209,7 @@ impl ClipChainId { // 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)] +#[derive(Clone, Debug, MallocSizeOf)] pub struct ClipChainNode { pub handle: ClipDataHandle, pub local_pos: LayoutPoint, @@ -223,7 +223,7 @@ pub struct ClipChainNode { // an index to the node data itself, as well as // some flags describing how this clip node instance // is positioned. -#[derive(Debug)] +#[derive(Debug, MallocSizeOf)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct ClipNodeInstance { @@ -250,7 +250,7 @@ pub struct ClipNodeRange { // todo(gw): optimize: // separate arrays for matrices // cache and only build as needed. -#[derive(Debug)] +#[derive(Debug, MallocSizeOf)] enum ClipSpaceConversion { Local, ScaleOffset(ScaleOffset), @@ -259,6 +259,7 @@ enum ClipSpaceConversion { // Temporary information that is cached and reused // during building of a clip chain instance. +#[derive(MallocSizeOf)] struct ClipNodeInfo { conversion: ClipSpaceConversion, handle: ClipDataHandle, @@ -434,7 +435,8 @@ impl ClipNode { } } -// The main clipping public interface that other modules access. +/// The main clipping public interface that other modules access. +#[derive(MallocSizeOf)] pub struct ClipStore { pub clip_chain_nodes: Vec, clip_node_instances: Vec, @@ -708,17 +710,6 @@ impl ClipStore { 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 { @@ -1287,7 +1278,7 @@ pub fn project_inner_rect( // Collects a list of unique clips to be applied to a rasterization // root at the end of primitive preparation. -#[derive(Debug)] +#[derive(Debug, MallocSizeOf)] pub struct ClipNodeCollector { spatial_node_index: SpatialNodeIndex, clips: FastHashSet, diff --git a/webrender/src/clip_scroll_tree.rs b/webrender/src/clip_scroll_tree.rs index ea0c212ebc..8040d421a6 100644 --- a/webrender/src/clip_scroll_tree.rs +++ b/webrender/src/clip_scroll_tree.rs @@ -41,7 +41,7 @@ impl CoordinateSystem { } } -#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq, PartialOrd, Ord)] +#[derive(Debug, Copy, Clone, Eq, Hash, MallocSizeOf, PartialEq, PartialOrd, Ord)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct SpatialNodeIndex(pub u32); diff --git a/webrender/src/gpu_cache.rs b/webrender/src/gpu_cache.rs index 49e9f7dfc6..969198c970 100644 --- a/webrender/src/gpu_cache.rs +++ b/webrender/src/gpu_cache.rs @@ -25,7 +25,6 @@ //! for this frame. use api::{DebugFlags, DocumentId, PremultipliedColorF, IdNamespace, TexelRect}; -use api::{VoidPtrToSizeFn}; use euclid::TypedRect; use internal_types::{FastHashMap}; use profiler::GpuCacheProfileCounters; @@ -34,7 +33,6 @@ 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}; @@ -55,7 +53,7 @@ const RECLAIM_THRESHOLD: f32 = 0.2; /// blow away the cache and rebuild it. const RECLAIM_DELAY_S: u64 = 5; -#[derive(Debug, Copy, Clone, Eq, PartialEq)] +#[derive(Debug, Copy, Clone, Eq, MallocSizeOf, PartialEq)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] struct Epoch(u32); @@ -75,7 +73,7 @@ struct CacheLocation { } /// A single texel in RGBAF32 texture - 16 bytes. -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, MallocSizeOf)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct GpuBlockData { @@ -147,7 +145,7 @@ impl GpuCacheHandle { // 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, Eq, PartialEq)] +#[derive(Copy, Debug, Clone, MallocSizeOf, Eq, PartialEq)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct GpuCacheAddress { @@ -183,7 +181,7 @@ impl Add for GpuCacheAddress { } // An entry in a free-list of blocks in the GPU cache. -#[derive(Debug)] +#[derive(Debug, MallocSizeOf)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] struct Block { @@ -235,7 +233,7 @@ impl Block { /// /// Because we use Option in a lot of places, we use a NonZeroU32 /// here and avoid ever using the index zero. -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, MallocSizeOf)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] struct BlockIndex(NonZeroU32); @@ -254,6 +252,7 @@ impl BlockIndex { // 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. @@ -276,6 +275,7 @@ impl Row { // 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, @@ -286,6 +286,7 @@ pub enum GpuCacheUpdate { /// 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), @@ -293,7 +294,7 @@ pub enum GpuCacheDebugCmd { Free(GpuCacheAddress), } -#[derive(Clone)] +#[derive(Clone, MallocSizeOf)] pub struct GpuCacheDebugChunk { pub address: GpuCacheAddress, pub size: usize, @@ -302,6 +303,7 @@ pub struct GpuCacheDebugChunk { #[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, @@ -325,6 +327,7 @@ pub struct GpuCacheUpdateList { // 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, free_list_2: Option, @@ -392,6 +395,7 @@ impl FreeBlockLists { // 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, @@ -456,18 +460,6 @@ impl Texture { } } - // 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. @@ -672,6 +664,7 @@ impl<'a> Drop for GpuDataRequest<'a> { /// 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, @@ -865,11 +858,6 @@ impl GpuCache { 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] diff --git a/webrender/src/hit_test.rs b/webrender/src/hit_test.rs index 56f917b0b2..d44f4128f1 100644 --- a/webrender/src/hit_test.rs +++ b/webrender/src/hit_test.rs @@ -3,19 +3,19 @@ * 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, VoidPtrToSizeFn, WorldPoint}; +use api::{LayoutPrimitiveInfo, LayoutRect, PipelineId, 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, @@ -27,6 +27,7 @@ pub struct HitTestSpatialNode { 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. @@ -64,20 +65,21 @@ impl HitTestClipNode { // copy the complete interned clip data store for // hit testing. -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Copy, Clone, MallocSizeOf, 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)] +#[derive(Clone, MallocSizeOf)] pub struct HitTestingItem { rect: LayoutRect, clip_rect: LayoutRect, @@ -96,9 +98,10 @@ impl HitTestingItem { } } -#[derive(Clone)] +#[derive(Clone, MallocSizeOf)] pub struct HitTestingRun(pub Vec, pub ScrollNodeAndClipChain); +#[derive(MallocSizeOf)] enum HitTestRegion { Invalid, Rectangle(LayoutRect, ClipMode), @@ -121,6 +124,7 @@ impl HitTestRegion { } } +#[derive(MallocSizeOf)] pub struct HitTester { runs: Vec, spatial_nodes: Vec, @@ -371,28 +375,15 @@ impl HitTester { 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, PartialEq)] +#[derive(Clone, Copy, MallocSizeOf, PartialEq)] enum ClippedIn { ClippedIn, NotClippedIn, } +#[derive(MallocSizeOf)] pub struct HitTest { pipeline_id: Option, point: WorldPoint, diff --git a/webrender/src/intern.rs b/webrender/src/intern.rs index f37742948f..0df0d204fe 100644 --- a/webrender/src/intern.rs +++ b/webrender/src/intern.rs @@ -51,7 +51,7 @@ use util::VecHelper; /// correctness validation (handle). #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Copy, Clone, PartialEq)] +#[derive(Debug, Copy, Clone, MallocSizeOf, PartialEq)] struct Epoch(u64); impl Epoch { @@ -76,7 +76,7 @@ lazy_static! { /// A globally, unique identifier #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq)] +#[derive(Debug, Copy, Clone, Eq, Hash, MallocSizeOf, PartialEq)] pub struct ItemUid { uid: usize, } @@ -90,7 +90,7 @@ impl ItemUid { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, MallocSizeOf)] pub struct Handle { index: u32, epoch: Epoch, diff --git a/webrender/src/lib.rs b/webrender/src/lib.rs index c3f8e16dc0..771d073ea0 100644 --- a/webrender/src/lib.rs +++ b/webrender/src/lib.rs @@ -58,12 +58,17 @@ extern crate cfg_if; 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; diff --git a/webrender/src/prim_store/mod.rs b/webrender/src/prim_store/mod.rs index f59d39ab1b..68a485b5e1 100644 --- a/webrender/src/prim_store/mod.rs +++ b/webrender/src/prim_store/mod.rs @@ -79,7 +79,7 @@ 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, PartialEq)] +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq)] pub struct ScrollNodeAndClipChain { pub spatial_node_index: SpatialNodeIndex, pub clip_chain_id: ClipChainId, @@ -846,7 +846,7 @@ impl OpacityBinding { } } -#[derive(Debug)] +#[derive(Debug, MallocSizeOf)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct VisibleMaskImageTile { diff --git a/webrender/src/render_backend.rs b/webrender/src/render_backend.rs index e881532cd3..0ab80dea8b 100644 --- a/webrender/src/render_backend.rs +++ b/webrender/src/render_backend.rs @@ -30,6 +30,7 @@ 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}; @@ -88,7 +89,7 @@ impl DocumentView { } } -#[derive(Copy, Clone, Hash, PartialEq, PartialOrd, Debug, Eq, Ord)] +#[derive(Copy, Clone, Hash, MallocSizeOf, PartialEq, PartialOrd, Debug, Eq, Ord)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct FrameId(usize); @@ -142,7 +143,7 @@ impl ::std::ops::Sub for FrameId { /// 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)] +#[derive(Copy, Clone, Debug, MallocSizeOf)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct FrameStamp { @@ -679,7 +680,7 @@ pub struct RenderBackend { notifier: Box, recorder: Option>, sampler: Option>, - size_of_op: Option, + size_of_ops: Option, debug_flags: DebugFlags, namespace_alloc_by_client: bool, } @@ -698,7 +699,7 @@ impl RenderBackend { frame_config: FrameBuilderConfig, recorder: Option>, sampler: Option>, - size_of_op: Option, + size_of_ops: Option, debug_flags: DebugFlags, namespace_alloc_by_client: bool, ) -> RenderBackend { @@ -718,7 +719,7 @@ impl RenderBackend { notifier, recorder, sampler, - size_of_op, + size_of_ops, debug_flags, namespace_alloc_by_client, } @@ -1552,16 +1553,16 @@ impl RenderBackend { serde_json::to_string(&debug_root).unwrap() } - fn report_memory(&self, tx: MsgSender) { + fn report_memory(&mut self, tx: MsgSender) { let mut report = MemoryReport::default(); - let op = self.size_of_op.unwrap(); - report.gpu_cache_metadata = self.gpu_cache.malloc_size_of(op); + 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); for (_id, doc) in &self.documents { if let Some(ref fb) = doc.frame_builder { - report.clip_stores += fb.clip_store.malloc_size_of(op); + report.clip_stores += fb.clip_store.size_of(ops); } - report.hit_testers += - doc.hit_tester.as_ref().map_or(0, |ht| ht.malloc_size_of(op)); + report.hit_testers += doc.hit_tester.size_of(ops); doc.resources.report_memory(op, &mut report) } diff --git a/webrender/src/renderer.rs b/webrender/src/renderer.rs index 8e275175e8..2df4124291 100644 --- a/webrender/src/renderer.rs +++ b/webrender/src/renderer.rs @@ -59,6 +59,7 @@ use internal_types::{TextureSource, ORTHO_FAR_PLANE, ORTHO_NEAR_PLANE, ResourceC 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}; @@ -1556,17 +1557,9 @@ pub struct Renderer { /// copy the WR output to. output_image_handler: Option>, - /// Optional function pointer for measuring memory used by a given + /// Optional function pointers for measuring memory used by a given /// heap-allocated pointer. - size_of_op: Option, - - /// 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, + size_of_ops: Option, // Currently allocated FBOs for output frames. output_targets: FastHashMap, @@ -1832,6 +1825,10 @@ impl Renderer { 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(); @@ -1857,8 +1854,6 @@ impl Renderer { 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(); @@ -1875,8 +1870,7 @@ impl Renderer { config, api_tx.clone(), scene_builder_hooks, - size_of_op, - enclosing_size_of_op, + make_size_of_ops(), ); thread::Builder::new().name(scene_thread_name.clone()).spawn(move || { register_thread_with_profiler(scene_thread_name.clone()); @@ -1949,7 +1943,7 @@ impl Renderer { config, recorder, sampler, - size_of_op, + make_size_of_ops(), debug_flags, namespace_alloc_by_client, ); @@ -2011,8 +2005,7 @@ impl Renderer { dither_matrix_texture, external_image_handler: None, output_image_handler: None, - size_of_op: options.size_of_op, - _enclosing_size_of_op: options.enclosing_size_of_op, + size_of_ops: make_size_of_ops(), output_targets: FastHashMap::default(), cpu_profiles: VecDeque::new(), gpu_profiles: VecDeque::new(), @@ -4572,7 +4565,7 @@ impl Renderer { } fn size_of(&self, ptr: *const T) -> usize { - let op = self.size_of_op.as_ref().unwrap(); + let op = self.size_of_ops.as_ref().unwrap().size_of_op; unsafe { op(ptr as *const c_void) } } diff --git a/webrender/src/resource_cache.rs b/webrender/src/resource_cache.rs index 3cb0db61f9..04860c1def 100644 --- a/webrender/src/resource_cache.rs +++ b/webrender/src/resource_cache.rs @@ -1821,6 +1821,13 @@ impl ResourceCache { } /// 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(); diff --git a/webrender/src/scene_builder.rs b/webrender/src/scene_builder.rs index 1e8c4d82f6..918f7faf1d 100644 --- a/webrender/src/scene_builder.rs +++ b/webrender/src/scene_builder.rs @@ -5,7 +5,7 @@ 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, VoidPtrToSizeFn}; +use api::{MemoryReport}; use api::channel::MsgSender; #[cfg(feature = "capture")] use capture::CaptureConfig; @@ -15,6 +15,7 @@ use clip_scroll_tree::ClipScrollTree; use display_list_flattener::DisplayListFlattener; use intern::{Internable, Interner}; use internal_types::{FastHashMap, FastHashSet}; +use malloc_size_of::MallocSizeOfOps; use prim_store::{PrimitiveDataInterner, PrimitiveDataUpdateList, PrimitiveKeyKind}; use prim_store::PrimitiveStoreStats; use prim_store::borders::{ @@ -220,10 +221,11 @@ impl DocumentResources { /// Reports CPU heap memory used by the interners. fn report_memory( &self, - op: VoidPtrToSizeFn, - eop: VoidPtrToSizeFn, + ops: &mut MallocSizeOfOps, r: &mut MemoryReport, ) { + let op = ops.size_of_op; + let eop = ops.enclosing_size_of_op.unwrap(); 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); @@ -293,8 +295,7 @@ pub struct SceneBuilder { config: FrameBuilderConfig, hooks: Option>, simulate_slow_ms: u32, - size_of_op: Option, - enclosing_size_of_op: Option, + size_of_ops: Option, } impl SceneBuilder { @@ -302,8 +303,7 @@ impl SceneBuilder { config: FrameBuilderConfig, api_tx: MsgSender, hooks: Option>, - size_of_op: Option, - enclosing_size_of_op: Option, + size_of_ops: Option, ) -> (Self, Sender, Receiver) { let (in_tx, in_rx) = channel(); let (out_tx, out_rx) = channel(); @@ -315,8 +315,7 @@ impl SceneBuilder { api_tx, config, hooks, - size_of_op, - enclosing_size_of_op, + size_of_ops, simulate_slow_ms: 0, }, in_tx, @@ -763,12 +762,11 @@ impl SceneBuilder { } /// Reports CPU heap memory used by the SceneBuilder. - fn report_memory(&self) -> MemoryReport { - let op = self.size_of_op.unwrap(); - let eop = self.enclosing_size_of_op.unwrap(); + fn report_memory(&mut self) -> MemoryReport { + let ops = self.size_of_ops.as_mut().unwrap(); let mut report = MemoryReport::default(); for doc in self.documents.values() { - doc.resources.report_memory(op, eop, &mut report); + doc.resources.report_memory(ops, &mut report); } report diff --git a/webrender/src/util.rs b/webrender/src/util.rs index ba94c2a28f..9c6dd4e24f 100644 --- a/webrender/src/util.rs +++ b/webrender/src/util.rs @@ -92,7 +92,7 @@ impl VecHelper for Vec { // 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)] +#[derive(Debug, Clone, Copy, MallocSizeOf)] pub struct ScaleOffset { pub scale: Vector2D, pub offset: Vector2D, @@ -556,7 +556,7 @@ impl MaxRect for TypedRect { /// An enum that tries to avoid expensive transformation matrix calculations /// when possible when dealing with non-perspective axis-aligned transformations. -#[derive(Debug)] +#[derive(Debug, MallocSizeOf)] pub enum FastTransform { /// A simple offset, which can be used without doing any matrix math. Offset(TypedVector2D), diff --git a/webrender_api/src/api.rs b/webrender_api/src/api.rs index 5838c24bc3..dae80eb534 100644 --- a/webrender_api/src/api.rs +++ b/webrender_api/src/api.rs @@ -561,7 +561,7 @@ pub struct HitTestResult { } bitflags! { - #[derive(Deserialize, Serialize)] + #[derive(Deserialize, MallocSizeOf, Serialize)] pub struct HitTestFlags: u8 { const FIND_ALL = 0b00000001; const POINT_RELATIVE_TO_PIPELINE_VIEWPORT = 0b00000010; @@ -787,11 +787,11 @@ impl Epoch { } #[repr(C)] -#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize)] +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Hash, Ord, PartialOrd, Deserialize, Serialize)] pub struct IdNamespace(pub u32); #[repr(C)] -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] pub struct DocumentId(pub IdNamespace, pub u32); impl DocumentId { @@ -807,7 +807,7 @@ 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, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] pub struct PipelineId(pub PipelineSourceId, pub u32); impl PipelineId { @@ -963,7 +963,7 @@ impl RenderApiSender { } bitflags! { - #[derive(Default, Deserialize, Serialize)] + #[derive(Default, Deserialize, MallocSizeOf, Serialize)] pub struct DebugFlags: u32 { /// Display the frame profiler on screen. const PROFILER_DBG = 1 << 0; diff --git a/webrender_api/src/display_item.rs b/webrender_api/src/display_item.rs index 4df5f0a13f..6932175b3e 100644 --- a/webrender_api/src/display_item.rs +++ b/webrender_api/src/display_item.rs @@ -401,7 +401,7 @@ pub enum BorderRadiusKind { } #[repr(C)] -#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)] pub struct BorderRadius { pub top_left: LayoutSize, pub top_right: LayoutSize, @@ -741,7 +741,7 @@ impl ImageMask { } #[repr(C)] -#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)] +#[derive(Copy, Clone, Debug, MallocSizeOf, PartialEq, Serialize, Deserialize, Eq, Hash)] pub enum ClipMode { Clip, // Pixels inside the region are visible. ClipOut, // Pixels outside the region are visible. diff --git a/webrender_api/src/lib.rs b/webrender_api/src/lib.rs index 6da3ff31c1..63be1f807a 100644 --- a/webrender_api/src/lib.rs +++ b/webrender_api/src/lib.rs @@ -30,11 +30,15 @@ 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; diff --git a/webrender_api/src/units.rs b/webrender_api/src/units.rs index 8939a06075..3fcf4655de 100644 --- a/webrender_api/src/units.rs +++ b/webrender_api/src/units.rs @@ -65,7 +65,7 @@ pub type RasterVector2D = TypedVector2D; pub type RasterVector3D = TypedVector3D; /// Geometry in a stacking context's local coordinate space (logical pixels). -#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Deserialize, Serialize)] +#[derive(Hash, Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Ord, PartialOrd, Deserialize, Serialize)] pub struct LayoutPixel; pub type LayoutRect = TypedRect; @@ -81,7 +81,7 @@ pub type LayoutIntPoint = TypedPoint2D; pub type LayoutIntSize = TypedSize2D; /// Geometry in the document's coordinate space (logical pixels). -#[derive(Hash, Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)] +#[derive(Hash, Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, Ord, PartialOrd)] pub struct WorldPixel; pub type WorldRect = TypedRect; diff --git a/wr_malloc_size_of/lib.rs b/wr_malloc_size_of/lib.rs index e43fdb8d36..1e05a8435b 100644 --- a/wr_malloc_size_of/lib.rs +++ b/wr_malloc_size_of/lib.rs @@ -103,13 +103,6 @@ impl MallocSizeOf for String { } } -impl<'a, T: ?Sized> MallocSizeOf for &'a T { - fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize { - // Zero makes sense for a non-owning reference. - 0 - } -} - impl MallocShallowSizeOf for Box { fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize { unsafe { ops.malloc_size_of(&**self) } From d24281aaaf7c4228198a9864308bba9b9b2e1110 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Thu, 10 Jan 2019 12:18:50 -0800 Subject: [PATCH 8/9] Bug 1519454 - Implement MallocSizeOf for Interner and DataStore. r=emilio Differential Revision: https://phabricator.services.mozilla.com/D16355 [wrupdater] From https://hg.mozilla.org/mozilla-central/rev/388b2d191167bbc0dbb12712d0b0454f145afeed --- webrender/src/border.rs | 8 ++-- webrender/src/box_shadow.rs | 4 +- webrender/src/clip.rs | 5 ++- webrender/src/freelist.rs | 3 +- webrender/src/glyph_rasterizer/mod.rs | 4 +- webrender/src/gpu_cache.rs | 4 +- webrender/src/gpu_types.rs | 5 ++- webrender/src/intern.rs | 57 +++++++++++++++++++-------- webrender/src/prim_store/borders.rs | 12 ++++-- webrender/src/prim_store/gradient.rs | 14 ++++--- webrender/src/prim_store/image.rs | 12 +++--- webrender/src/prim_store/line_dec.rs | 7 ++-- webrender/src/prim_store/mod.rs | 37 ++++++++++------- webrender/src/prim_store/picture.rs | 7 ++-- webrender/src/prim_store/text_run.rs | 5 ++- webrender/src/render_task.rs | 2 +- webrender/src/scene_builder.rs | 2 +- webrender_api/src/api.rs | 2 +- webrender_api/src/color.rs | 4 +- webrender_api/src/display_item.rs | 26 ++++++------ webrender_api/src/font.rs | 22 +++++------ webrender_api/src/image.rs | 4 +- 22 files changed, 145 insertions(+), 101 deletions(-) diff --git a/webrender/src/border.rs b/webrender/src/border.rs index c07d1a27ad..397d696937 100644 --- a/webrender/src/border.rs +++ b/webrender/src/border.rs @@ -34,7 +34,7 @@ pub const MAX_DASH_COUNT: u32 = 2048; // all the border structs with hashable // variants... -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Clone, Debug, Hash, MallocSizeOf, PartialEq, Eq)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct BorderRadiusAu { @@ -66,7 +66,7 @@ impl From for BorderRadius { } } -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Clone, Debug, Hash, MallocSizeOf, PartialEq, Eq)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct BorderSideAu { @@ -94,7 +94,7 @@ impl From for BorderSide { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Clone, Hash, Eq, PartialEq)] +#[derive(Debug, Clone, Hash, Eq, MallocSizeOf, PartialEq)] pub struct NormalBorderAu { pub left: BorderSideAu, pub right: BorderSideAu, @@ -148,7 +148,7 @@ impl From for ApiNormalBorder { /// Cache key that uniquely identifies a border /// segment in the render task cache. -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Clone, Debug, Hash, MallocSizeOf, PartialEq, Eq)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct BorderSegmentCacheKey { diff --git a/webrender/src/box_shadow.rs b/webrender/src/box_shadow.rs index f14a526423..db04712aa0 100644 --- a/webrender/src/box_shadow.rs +++ b/webrender/src/box_shadow.rs @@ -12,7 +12,7 @@ use prim_store::{ScrollNodeAndClipChain, PrimitiveKeyKind}; use render_task::RenderTaskCacheEntryHandle; use util::RectHelpers; -#[derive(Debug, Clone)] +#[derive(Debug, Clone, MallocSizeOf)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct BoxShadowClipSource { @@ -51,7 +51,7 @@ 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, PartialEq)] +#[derive(Debug, Clone, Eq, Hash, MallocSizeOf, PartialEq)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct BoxShadowCacheKey { diff --git a/webrender/src/clip.rs b/webrender/src/clip.rs index 364cbc888a..183871f9bf 100644 --- a/webrender/src/clip.rs +++ b/webrender/src/clip.rs @@ -133,6 +133,7 @@ enum ClipResult { #[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, @@ -781,7 +782,7 @@ impl ClipRegion> { // 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, PartialEq, Hash)] +#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub enum ClipItemKey { @@ -844,7 +845,7 @@ impl ClipItemKey { impl intern::InternDebug for ClipItemKey {} -#[derive(Debug)] +#[derive(Debug, MallocSizeOf)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub enum ClipItem { diff --git a/webrender/src/freelist.rs b/webrender/src/freelist.rs index faec9b7109..bcff127fec 100644 --- a/webrender/src/freelist.rs +++ b/webrender/src/freelist.rs @@ -23,7 +23,7 @@ use std::{fmt, u32}; use std::marker::PhantomData; -#[derive(Debug, Copy, Clone, PartialEq)] +#[derive(Debug, Copy, Clone, MallocSizeOf, PartialEq)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] struct Epoch(u32); @@ -96,6 +96,7 @@ impl PartialEq for WeakFreeListHandle { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] +#[derive(MallocSizeOf)] pub struct WeakFreeListHandle { index: u32, epoch: Epoch, diff --git a/webrender/src/glyph_rasterizer/mod.rs b/webrender/src/glyph_rasterizer/mod.rs index 78b0265908..2c7dc7081c 100644 --- a/webrender/src/glyph_rasterizer/mod.rs +++ b/webrender/src/glyph_rasterizer/mod.rs @@ -28,7 +28,7 @@ pub use self::pathfinder::{ThreadSafePathfinderFontContext, NativeFontHandleWrap #[cfg(not(feature = "pathfinder"))] mod no_pathfinder; -#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)] +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, PartialOrd)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct FontTransform { @@ -164,7 +164,7 @@ impl<'a> From<&'a LayoutToWorldTransform> for FontTransform { // 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)] +#[derive(Clone, Hash, PartialEq, Eq, Debug, Ord, PartialOrd, MallocSizeOf)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct FontInstance { diff --git a/webrender/src/gpu_cache.rs b/webrender/src/gpu_cache.rs index 969198c970..1ce2544186 100644 --- a/webrender/src/gpu_cache.rs +++ b/webrender/src/gpu_cache.rs @@ -64,7 +64,7 @@ impl Epoch { } } -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, MallocSizeOf)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] struct CacheLocation { @@ -129,7 +129,7 @@ pub trait ToGpuBlocks { } // A handle to a GPU resource. -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, MallocSizeOf)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct GpuCacheHandle { diff --git a/webrender/src/gpu_types.rs b/webrender/src/gpu_types.rs index 5f37271fe7..6c7d7214c5 100644 --- a/webrender/src/gpu_types.rs +++ b/webrender/src/gpu_types.rs @@ -59,7 +59,7 @@ pub enum RasterizationSpace { Screen = 1, } -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, MallocSizeOf)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] #[repr(C)] @@ -96,7 +96,7 @@ pub struct ScalingInstance { pub src_task_address: RenderTaskAddress, } -#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Hash, MallocSizeOf, PartialEq, Eq)] #[repr(C)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] @@ -317,6 +317,7 @@ bitflags! { /// 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; diff --git a/webrender/src/intern.rs b/webrender/src/intern.rs index 0df0d204fe..0255aa6669 100644 --- a/webrender/src/intern.rs +++ b/webrender/src/intern.rs @@ -5,6 +5,7 @@ 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; @@ -106,6 +107,7 @@ impl Handle where M: Copy { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] +#[derive(MallocSizeOf)] pub enum UpdateKind { Insert, Remove, @@ -114,6 +116,7 @@ pub enum UpdateKind { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] +#[derive(MallocSizeOf)] pub struct Update { index: usize, kind: UpdateKind, @@ -123,7 +126,8 @@ pub struct Update { /// correct access patterns. #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -struct Item { +#[derive(MallocSizeOf)] +struct Item { epoch: Epoch, data: T, } @@ -136,13 +140,18 @@ pub trait InternDebug { /// contains a free-list of items for fast access. #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -pub struct DataStore { +#[derive(MallocSizeOf)] +pub struct DataStore { items: Vec>, _source: PhantomData, _marker: PhantomData, } -impl ::std::default::Default for DataStore where S: Debug, T: From, M: Debug +impl ::std::default::Default for DataStore +where + S: Debug + MallocSizeOf, + T: From + MallocSizeOf, + M: Debug { fn default() -> Self { DataStore { @@ -153,7 +162,11 @@ impl ::std::default::Default for DataStore where S: Debug, T: } } -impl DataStore where S: Debug, T: From, M: Debug +impl DataStore +where + S: Debug + MallocSizeOf, + T: From + MallocSizeOf, + M: Debug { /// Apply any updates from the scene builder thread to /// this data store. @@ -194,7 +207,10 @@ impl DataStore where S: Debug, T: From, M: Debug /// Retrieve an item from the store via handle impl ops::Index> for DataStore -where M: Copy +where + S: MallocSizeOf, + T: MallocSizeOf, + M: Copy { type Output = T; fn index(&self, handle: Handle) -> &T { @@ -208,6 +224,8 @@ where M: Copy /// Retrieve an item from the store via handle impl ops::IndexMut> for DataStore where + S: MallocSizeOf, + T: MallocSizeOf, M: Copy { fn index_mut(&mut self, handle: Handle) -> &mut T { @@ -224,10 +242,12 @@ where /// an update list of additions / removals. #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] +#[derive(MallocSizeOf)] pub struct Interner where - S: Eq + Hash + Clone + Debug, - M: Copy + S: Eq + Hash + Clone + Debug + MallocSizeOf, + D: MallocSizeOf, + M: Copy + MallocSizeOf, { /// Uniquely map an interning key to a handle map: FastHashMap>, @@ -246,8 +266,9 @@ where impl ::std::default::Default for Interner where - S: Eq + Hash + Clone + Debug, - M: Copy + Debug + S: Eq + Hash + Clone + Debug + MallocSizeOf, + D: MallocSizeOf, + M: Copy + Debug + MallocSizeOf, { fn default() -> Self { Interner { @@ -263,8 +284,9 @@ where impl Interner where - S: Eq + Hash + Clone + Debug + InternDebug, - M: Copy + Debug + S: Eq + Hash + Clone + Debug + InternDebug + MallocSizeOf, + D: MallocSizeOf, + M: Copy + Debug + MallocSizeOf { /// Intern a data structure, and return a handle to /// that data. The handle can then be stored in the @@ -398,8 +420,9 @@ where /// Retrieve the local data for an item from the interner via handle impl ops::Index> for Interner where - S: Eq + Clone + Hash + Debug, - M: Copy + Debug + S: Eq + Clone + Hash + Debug + MallocSizeOf, + D: MallocSizeOf, + M: Copy + Debug + MallocSizeOf { type Output = D; fn index(&self, handle: Handle) -> &D { @@ -413,10 +436,10 @@ where /// /// see DisplayListFlattener::add_interned_primitive

pub trait Internable { - type Marker: Copy + Debug; - type Source: Eq + Hash + Clone + Debug; - type StoreData: From; - type InternData; + type Marker: Copy + Debug + MallocSizeOf; + type Source: Eq + Hash + Clone + Debug + MallocSizeOf; + type StoreData: From + MallocSizeOf; + type InternData: MallocSizeOf; /// Build a new key from self with `info`. fn build_key( diff --git a/webrender/src/prim_store/borders.rs b/webrender/src/prim_store/borders.rs index 81b39c7dc5..e18b6f925e 100644 --- a/webrender/src/prim_store/borders.rs +++ b/webrender/src/prim_store/borders.rs @@ -24,7 +24,7 @@ use storage; #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Clone, Eq, PartialEq, Hash)] +#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)] pub struct NormalBorderPrim { pub border: NormalBorderAu, pub widths: LayoutSideOffsetsAu, @@ -67,6 +67,7 @@ impl AsInstanceKind for NormalBorderKey { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] +#[derive(MallocSizeOf)] pub struct NormalBorderData { pub brush_segments: Vec, pub border_segments: Vec, @@ -161,7 +162,7 @@ impl From for NormalBorderTemplate { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)] pub struct NormalBorderDataMarker; pub type NormalBorderDataStore = intern::DataStore; @@ -209,8 +210,9 @@ impl IsVisible for NormalBorderPrim { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Clone, Eq, PartialEq, Hash)] +#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)] pub struct ImageBorder { + #[ignore_malloc_size_of = "Arc"] pub request: ImageRequest, pub nine_patch: NinePatchDescriptor, } @@ -251,7 +253,9 @@ impl AsInstanceKind for ImageBorderKey { #[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, } @@ -339,7 +343,7 @@ impl From for ImageBorderTemplate { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)] pub struct ImageBorderDataMarker; pub type ImageBorderDataStore = intern::DataStore; diff --git a/webrender/src/prim_store/gradient.rs b/webrender/src/prim_store/gradient.rs index dd514146c5..d102ca01df 100644 --- a/webrender/src/prim_store/gradient.rs +++ b/webrender/src/prim_store/gradient.rs @@ -20,7 +20,7 @@ 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, PartialEq)] +#[derive(Debug, Clone, MallocSizeOf, PartialEq)] pub struct GradientStopKey { pub offset: f32, pub color: ColorU, @@ -38,7 +38,7 @@ impl hash::Hash for GradientStopKey { /// Identifying key for a line decoration. #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Clone, Eq, PartialEq, Hash)] +#[derive(Debug, Clone, Eq, PartialEq, Hash, MallocSizeOf)] pub struct LinearGradientKey { pub common: PrimKeyCommonData, pub extend_mode: ExtendMode, @@ -95,6 +95,7 @@ impl AsInstanceKind for LinearGradientKey { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] +#[derive(MallocSizeOf)] pub struct LinearGradientTemplate { pub common: PrimTemplateCommonData, pub extend_mode: ExtendMode, @@ -228,7 +229,7 @@ impl LinearGradientTemplate { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)] pub struct LinearGradientDataMarker; pub type LinearGradientDataStore = DataStore; @@ -279,7 +280,7 @@ 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, PartialEq)] +#[derive(Debug, Clone, MallocSizeOf, PartialEq)] pub struct RadialGradientParams { pub start_radius: f32, pub end_radius: f32, @@ -299,7 +300,7 @@ impl hash::Hash for RadialGradientParams { /// Identifying key for a line decoration. #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Clone, Eq, PartialEq, Hash)] +#[derive(Debug, Clone, Eq, PartialEq, Hash, MallocSizeOf)] pub struct RadialGradientKey { pub common: PrimKeyCommonData, pub extend_mode: ExtendMode, @@ -354,6 +355,7 @@ impl AsInstanceKind for RadialGradientKey { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] +#[derive(MallocSizeOf)] pub struct RadialGradientTemplate { pub common: PrimTemplateCommonData, pub extend_mode: ExtendMode, @@ -458,7 +460,7 @@ impl RadialGradientTemplate { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)] pub struct RadialGradientDataMarker; pub type RadialGradientDataStore = DataStore; diff --git a/webrender/src/prim_store/image.rs b/webrender/src/prim_store/image.rs index afdfc18c3b..7c4812493b 100644 --- a/webrender/src/prim_store/image.rs +++ b/webrender/src/prim_store/image.rs @@ -67,7 +67,7 @@ pub struct ImageInstance { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Clone, Eq, PartialEq, Hash)] +#[derive(Debug, Clone, Eq, PartialEq, MallocSizeOf, Hash)] pub struct Image { pub key: ApiImageKey, pub stretch_size: SizeKey, @@ -127,7 +127,7 @@ impl AsInstanceKind for ImageKey { // Where to find the texture data for an image primitive. #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug)] +#[derive(Debug, MallocSizeOf)] pub enum ImageSource { // A normal image - just reference the texture cache. Default, @@ -141,6 +141,7 @@ pub enum ImageSource { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] +#[derive(MallocSizeOf)] pub struct ImageData { pub key: ApiImageKey, pub stretch_size: LayoutSize, @@ -336,7 +337,7 @@ impl From for ImageTemplate { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)] pub struct ImageDataMarker; pub type ImageDataStore = DataStore; @@ -389,7 +390,7 @@ impl IsVisible for Image { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Clone, Eq, PartialEq, Hash)] +#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)] pub struct YuvImage { pub color_depth: ColorDepth, pub yuv_key: [ApiImageKey; 3], @@ -438,6 +439,7 @@ impl AsInstanceKind for YuvImageKey { #[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], @@ -513,7 +515,7 @@ impl From for YuvImageTemplate { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)] pub struct YuvImageDataMarker; pub type YuvImageDataStore = DataStore; diff --git a/webrender/src/prim_store/line_dec.rs b/webrender/src/prim_store/line_dec.rs index 8ddcdf085a..d56a6022db 100644 --- a/webrender/src/prim_store/line_dec.rs +++ b/webrender/src/prim_store/line_dec.rs @@ -17,7 +17,7 @@ use prim_store::{ }; use prim_store::PrimitiveInstanceKind; -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Clone, Debug, Hash, MallocSizeOf, PartialEq, Eq)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct LineDecorationCacheKey { @@ -28,7 +28,7 @@ pub struct LineDecorationCacheKey { } /// Identifying key for a line decoration. -#[derive(Clone, Debug, Hash, PartialEq, Eq)] +#[derive(Clone, Debug, Hash, MallocSizeOf, PartialEq, Eq)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct LineDecoration { @@ -77,6 +77,7 @@ impl AsInstanceKind for LineDecorationKey { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] +#[derive(MallocSizeOf)] pub struct LineDecorationData { pub cache_key: Option, pub color: ColorF, @@ -136,7 +137,7 @@ impl From for LineDecorationTemplate { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)] pub struct LineDecorationDataMarker; pub type LineDecorationDataStore = intern::DataStore; diff --git a/webrender/src/prim_store/mod.rs b/webrender/src/prim_store/mod.rs index 68a485b5e1..0142983ccf 100644 --- a/webrender/src/prim_store/mod.rs +++ b/webrender/src/prim_store/mod.rs @@ -28,6 +28,7 @@ use gpu_cache::{GpuCache, GpuCacheAddress, GpuCacheHandle, GpuDataRequest, ToGpu 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}; @@ -99,7 +100,7 @@ impl ScrollNodeAndClipChain { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, MallocSizeOf)] pub struct PrimitiveOpacity { pub is_opaque: bool, } @@ -347,6 +348,7 @@ impl GpuCacheAddress { /// 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, @@ -357,7 +359,7 @@ pub struct PrimitiveSceneData { /// uniquely identifies a primitive template by key. #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Clone, Eq, PartialEq, Hash)] +#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)] pub enum PrimitiveKeyKind { /// Clear an existing rect, used for special effects on some platforms. Clear, @@ -368,7 +370,7 @@ pub enum PrimitiveKeyKind { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, MallocSizeOf, PartialEq)] pub struct RectangleKey { x: f32, y: f32, @@ -410,7 +412,7 @@ impl From for RectangleKey { /// 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, PartialEq)] +#[derive(Debug, Clone, MallocSizeOf, PartialEq)] pub struct SideOffsetsKey { pub top: f32, pub right: f32, @@ -465,7 +467,7 @@ impl From> for SideOffsetsKey { /// 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, PartialEq)] +#[derive(Copy, Debug, Clone, MallocSizeOf, PartialEq)] pub struct SizeKey { w: f32, h: f32, @@ -498,7 +500,7 @@ impl From> for SizeKey { /// 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, PartialEq)] +#[derive(Copy, Debug, Clone, MallocSizeOf, PartialEq)] pub struct VectorKey { pub x: f32, pub y: f32, @@ -531,7 +533,7 @@ impl From for VectorKey { /// 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, PartialEq)] +#[derive(Debug, Clone, MallocSizeOf, PartialEq)] pub struct PointKey { pub x: f32, pub y: f32, @@ -563,7 +565,7 @@ impl From for PointKey { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Clone, Eq, PartialEq, Hash)] +#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)] pub struct PrimKeyCommonData { pub is_backface_visible: bool, pub prim_size: SizeKey, @@ -585,15 +587,15 @@ impl PrimKeyCommonData { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Clone, Eq, PartialEq, Hash)] -pub struct PrimKey { +#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)] +pub struct PrimKey { pub common: PrimKeyCommonData, pub kind: T, } #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Clone, Eq, PartialEq, Hash)] +#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)] pub struct PrimitiveKey { pub common: PrimKeyCommonData, pub kind: PrimitiveKeyKind, @@ -648,6 +650,7 @@ impl AsInstanceKind for PrimitiveKey { /// 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, @@ -675,6 +678,7 @@ 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, @@ -701,6 +705,7 @@ impl PrimTemplateCommonData { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] +#[derive(MallocSizeOf)] pub struct PrimTemplate { pub common: PrimTemplateCommonData, pub kind: T, @@ -708,6 +713,7 @@ pub struct PrimTemplate { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] +#[derive(MallocSizeOf)] pub struct PrimitiveTemplate { pub common: PrimTemplateCommonData, pub kind: PrimitiveTemplateKind, @@ -780,7 +786,7 @@ 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, PartialEq)] +#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)] pub struct PrimitiveDataMarker; impl intern::Internable for PrimitiveKeyKind { @@ -865,7 +871,7 @@ pub struct VisibleGradientTile { /// along with the current render task cache entry. #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug)] +#[derive(Debug, MallocSizeOf)] pub struct BorderSegmentInfo { pub local_task_size: LayoutSize, pub cache_key: BorderSegmentCacheKey, @@ -880,6 +886,7 @@ bitflags! { /// `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; @@ -901,7 +908,7 @@ pub enum ClipMaskKind { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Clone)] +#[derive(Debug, Clone, MallocSizeOf)] pub struct BrushSegment { pub local_rect: LayoutRect, pub may_need_clip_mask: bool, @@ -1191,7 +1198,7 @@ impl ClipData { /// A hashable descriptor for nine-patches, used by image and /// gradient borders. -#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, PartialEq, Eq, Hash, MallocSizeOf)] #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] pub struct NinePatchDescriptor { diff --git a/webrender/src/prim_store/picture.rs b/webrender/src/prim_store/picture.rs index 2ea28ccc3b..06a341ec0e 100644 --- a/webrender/src/prim_store/picture.rs +++ b/webrender/src/prim_store/picture.rs @@ -19,7 +19,7 @@ use prim_store::{ /// will be composited into its parent. #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Clone, PartialEq, Hash, Eq)] +#[derive(Debug, Clone, MallocSizeOf, PartialEq, Hash, Eq)] pub enum PictureCompositeKey { // No visual compositing effect Identity, @@ -127,7 +127,7 @@ impl From> for PictureCompositeKey { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Debug, Clone, Eq, PartialEq, Hash)] +#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)] pub struct Picture { pub composite_mode_key: PictureCompositeKey, } @@ -171,6 +171,7 @@ impl AsInstanceKind for PictureKey { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] +#[derive(MallocSizeOf)] pub struct PictureData; pub type PictureTemplate = PrimTemplate; @@ -188,7 +189,7 @@ impl From for PictureTemplate { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)] pub struct PictureDataMarker; pub type PictureDataStore = DataStore; diff --git a/webrender/src/prim_store/text_run.rs b/webrender/src/prim_store/text_run.rs index dc79060bfd..7deeaf16b4 100644 --- a/webrender/src/prim_store/text_run.rs +++ b/webrender/src/prim_store/text_run.rs @@ -23,7 +23,7 @@ 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, PartialEq, Hash)] +#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash)] pub struct TextRunKey { pub common: PrimKeyCommonData, pub font: FontInstance, @@ -73,6 +73,7 @@ impl AsInstanceKind for TextRunKey { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] +#[derive(MallocSizeOf)] pub struct TextRunTemplate { pub common: PrimTemplateCommonData, pub font: FontInstance, @@ -161,7 +162,7 @@ impl TextRunTemplate { #[cfg_attr(feature = "capture", derive(Serialize))] #[cfg_attr(feature = "replay", derive(Deserialize))] -#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)] +#[derive(Clone, Copy, Debug, Hash, Eq, MallocSizeOf, PartialEq)] pub struct TextRunDataMarker; pub type TextRunDataStore = intern::DataStore; diff --git a/webrender/src/render_task.rs b/webrender/src/render_task.rs index 5ef5544447..f590111326 100644 --- a/webrender/src/render_task.rs +++ b/webrender/src/render_task.rs @@ -1113,7 +1113,7 @@ pub struct RenderTaskCacheEntry { pub handle: TextureCacheHandle, } -#[derive(Debug)] +#[derive(Debug, MallocSizeOf)] pub enum RenderTaskCacheMarker {} // A cache of render tasks that are stored in the texture diff --git a/webrender/src/scene_builder.rs b/webrender/src/scene_builder.rs index 918f7faf1d..4abaf35209 100644 --- a/webrender/src/scene_builder.rs +++ b/webrender/src/scene_builder.rs @@ -15,7 +15,7 @@ use clip_scroll_tree::ClipScrollTree; use display_list_flattener::DisplayListFlattener; use intern::{Internable, Interner}; use internal_types::{FastHashMap, FastHashSet}; -use malloc_size_of::MallocSizeOfOps; +use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; use prim_store::{PrimitiveDataInterner, PrimitiveDataUpdateList, PrimitiveKeyKind}; use prim_store::PrimitiveStoreStats; use prim_store::borders::{ diff --git a/webrender_api/src/api.rs b/webrender_api/src/api.rs index dae80eb534..eebeabfebb 100644 --- a/webrender_api/src/api.rs +++ b/webrender_api/src/api.rs @@ -1289,7 +1289,7 @@ impl ZoomFactor { } #[repr(C)] -#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, Eq, Hash)] +#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash)] pub struct PropertyBindingId { namespace: IdNamespace, uid: u32, diff --git a/webrender_api/src/color.rs b/webrender_api/src/color.rs index bdda69e819..bc8cd07105 100644 --- a/webrender_api/src/color.rs +++ b/webrender_api/src/color.rs @@ -39,7 +39,7 @@ impl PremultipliedColorF { /// 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, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)] pub struct ColorF { pub r: f32, pub g: f32, @@ -112,7 +112,7 @@ impl Hash for PremultipliedColorF { /// /// If the alpha value `a` is 255 the color is opaque. #[repr(C)] -#[derive(Clone, Copy, Hash, Eq, Debug, Deserialize, PartialEq, PartialOrd, Ord, Serialize)] +#[derive(Clone, Copy, Hash, Eq, Debug, Deserialize, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)] pub struct ColorU { pub r: u8, pub g: u8, diff --git a/webrender_api/src/display_item.rs b/webrender_api/src/display_item.rs index 6932175b3e..0559f4323f 100644 --- a/webrender_api/src/display_item.rs +++ b/webrender_api/src/display_item.rs @@ -247,14 +247,14 @@ pub struct LineDisplayItem { } #[repr(u8)] -#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, Eq, Hash)] +#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash)] pub enum LineOrientation { Vertical, Horizontal, } #[repr(u8)] -#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, Eq, Hash)] +#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash)] pub enum LineStyle { Solid, Dotted, @@ -269,7 +269,7 @@ pub struct TextDisplayItem { pub glyph_options: Option, } // IMPLICIT: glyphs: Vec -#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)] pub struct NormalBorder { pub left: BorderSide, pub right: BorderSide, @@ -328,7 +328,7 @@ impl NormalBorder { } #[repr(u32)] -#[derive(Debug, Copy, Clone, PartialEq, Serialize, Deserialize, Eq, Hash)] +#[derive(Debug, Copy, Clone, MallocSizeOf, PartialEq, Serialize, Deserialize, Eq, Hash)] pub enum RepeatMode { Stretch, Repeat, @@ -410,14 +410,14 @@ pub struct BorderRadius { } #[repr(C)] -#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)] pub struct BorderSide { pub color: ColorF, pub style: BorderStyle, } #[repr(u32)] -#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, Hash, Eq)] +#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, Hash, Eq)] pub enum BorderStyle { None = 0, Solid = 1, @@ -438,7 +438,7 @@ impl BorderStyle { } #[repr(u32)] -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] pub enum BoxShadowClipMode { Outset = 0, Inset = 1, @@ -464,7 +464,7 @@ pub struct Shadow { } #[repr(u8)] -#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Ord, PartialOrd)] +#[derive(Debug, Copy, Clone, Hash, Eq, MallocSizeOf, PartialEq, Serialize, Deserialize, Ord, PartialOrd)] pub enum ExtendMode { Clamp, Repeat, @@ -485,7 +485,7 @@ pub struct GradientDisplayItem { } #[repr(C)] -#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)] pub struct GradientStop { pub offset: f32, pub color: ColorF, @@ -659,14 +659,14 @@ pub struct ImageDisplayItem { } #[repr(u32)] -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] pub enum ImageRendering { Auto = 0, CrispEdges = 1, Pixelated = 2, } -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] pub enum AlphaType { Alpha = 0, PremultipliedAlpha = 1, @@ -681,7 +681,7 @@ pub struct YuvImageDisplayItem { } #[repr(u32)] -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] pub enum YuvColorSpace { Rec601 = 0, Rec709 = 1, @@ -704,7 +704,7 @@ impl YuvData { } } -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] pub enum YuvFormat { NV12 = 0, PlanarYCbCr = 1, diff --git a/webrender_api/src/font.rs b/webrender_api/src/font.rs index b8c1cd914e..8ab85721ae 100644 --- a/webrender_api/src/font.rs +++ b/webrender_api/src/font.rs @@ -71,7 +71,7 @@ pub struct GlyphDimensions { } #[repr(C)] -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize, Ord, PartialOrd)] +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, Ord, PartialOrd)] pub struct FontKey(pub IdNamespace, pub u32); impl FontKey { @@ -94,7 +94,7 @@ pub enum FontTemplate { } #[repr(u32)] -#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Ord, PartialOrd)] +#[derive(Debug, Copy, Clone, Hash, Eq, MallocSizeOf, PartialEq, Serialize, Deserialize, Ord, PartialOrd)] pub enum FontRenderMode { Mono = 0, Alpha, @@ -112,7 +112,7 @@ impl FontRenderMode { } #[repr(C)] -#[derive(Clone, Copy, Debug, PartialOrd, Deserialize, Serialize)] +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialOrd, Deserialize, Serialize)] pub struct FontVariation { pub tag: u32, pub value: f32, @@ -159,7 +159,7 @@ impl Default for GlyphOptions { bitflags! { #[repr(C)] - #[derive(Deserialize, Serialize)] + #[derive(Deserialize, MallocSizeOf, Serialize)] pub struct FontInstanceFlags: u32 { // Common flags const SYNTHETIC_BOLD = 1 << 1; @@ -204,7 +204,7 @@ impl Default for FontInstanceFlags { #[repr(C)] -#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)] pub struct SyntheticItalics { // Angle in degrees (-90..90) for synthetic italics in 8.8 fixed-point. pub angle: i16, @@ -273,7 +273,7 @@ impl Default for FontInstanceOptions { #[cfg(target_os = "windows")] #[repr(C)] -#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)] pub struct FontInstancePlatformOptions { pub gamma: u16, // percent pub contrast: u16, // percent @@ -291,7 +291,7 @@ impl Default for FontInstancePlatformOptions { #[cfg(target_os = "macos")] #[repr(C)] -#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)] pub struct FontInstancePlatformOptions { pub unused: u32, } @@ -307,7 +307,7 @@ impl Default for FontInstancePlatformOptions { #[cfg(not(any(target_os = "macos", target_os = "windows")))] #[repr(u8)] -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)] pub enum FontLCDFilter { None, Default, @@ -317,7 +317,7 @@ pub enum FontLCDFilter { #[cfg(not(any(target_os = "macos", target_os = "windows")))] #[repr(u8)] -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)] pub enum FontHinting { None, Mono, @@ -328,7 +328,7 @@ pub enum FontHinting { #[cfg(not(any(target_os = "macos", target_os = "windows")))] #[repr(C)] -#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, PartialOrd, Ord, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, MallocSizeOf, PartialEq, PartialOrd, Ord, Serialize)] pub struct FontInstancePlatformOptions { pub lcd_filter: FontLCDFilter, pub hinting: FontHinting, @@ -370,7 +370,7 @@ pub struct FontInstanceData { pub type GlyphIndex = u32; #[repr(C)] -#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)] pub struct GlyphInstance { pub index: GlyphIndex, pub point: LayoutPoint, diff --git a/webrender_api/src/image.rs b/webrender_api/src/image.rs index d3f4ac8ee7..6ce0401a1e 100644 --- a/webrender_api/src/image.rs +++ b/webrender_api/src/image.rs @@ -17,7 +17,7 @@ use std::ops::{Add, Sub}; /// 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, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] pub struct ImageKey(pub IdNamespace, pub u32); impl ImageKey { @@ -137,7 +137,7 @@ impl ImageFormat { /// Specifies the color depth of an image. Currently only used for YUV images. #[repr(u8)] -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] +#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)] pub enum ColorDepth { /// 8 bits image (most common) Color8, From b4d84f0bb944af86d332a3e4156a5491364a7dbd Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Fri, 11 Jan 2019 11:19:59 -0800 Subject: [PATCH 9/9] Bug 1519454 - Use a macro to declare interners and hook up memory reporters. r=emilio Differential Revision: https://phabricator.services.mozilla.com/D16356 [wrupdater] From https://hg.mozilla.org/mozilla-central/rev/33ca54452d38c1a597ee9178acd578304847aded --- webrender/src/intern.rs | 18 --------- webrender/src/lib.rs | 1 + webrender/src/render_backend.rs | 59 +++++++++++++---------------- webrender/src/scene_builder.rs | 66 +++++++++++++++------------------ webrender_api/src/api.rs | 60 +++++++++++++++++++++++++++--- 5 files changed, 111 insertions(+), 93 deletions(-) diff --git a/webrender/src/intern.rs b/webrender/src/intern.rs index 0255aa6669..0d51ffb69a 100644 --- a/webrender/src/intern.rs +++ b/webrender/src/intern.rs @@ -3,7 +3,6 @@ * 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; @@ -11,7 +10,6 @@ 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; @@ -198,11 +196,6 @@ where 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 @@ -404,17 +397,6 @@ where 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 diff --git a/webrender/src/lib.rs b/webrender/src/lib.rs index 771d073ea0..65f7dfe743 100644 --- a/webrender/src/lib.rs +++ b/webrender/src/lib.rs @@ -198,6 +198,7 @@ extern crate png; #[cfg(test)] extern crate rand; +#[macro_use] pub extern crate webrender_api; extern crate webrender_build; diff --git a/webrender/src/render_backend.rs b/webrender/src/render_backend.rs index 0ab80dea8b..07a55efc72 100644 --- a/webrender/src/render_backend.rs +++ b/webrender/src/render_backend.rs @@ -14,7 +14,7 @@ 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, VoidPtrToSizeFn}; +use api::{MemoryReport}; use api::{ScrollLocation, ScrollNodeState, TransactionMsg, ResourceUpdate, BlobImageKey}; use api::{NotificationRequest, Checkpoint}; use api::channel::{MsgReceiver, MsgSender, Payload}; @@ -214,30 +214,32 @@ impl FrameStamp { }; } -// 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, - - /// 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, +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, + )+ + } + + 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); + )+ + } + } + } } +enumerate_interners!(declare_frame_resources); + impl FrameResources { pub fn as_common_data( &self, @@ -287,15 +289,6 @@ impl FrameResources { } } } - - /// 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 { @@ -1564,7 +1557,7 @@ impl RenderBackend { } report.hit_testers += doc.hit_tester.size_of(ops); - doc.resources.report_memory(op, &mut report) + doc.resources.report_memory(ops, &mut report) } report += self.resource_cache.report_memory(op); diff --git a/webrender/src/scene_builder.rs b/webrender/src/scene_builder.rs index 4abaf35209..41ca3c75bb 100644 --- a/webrender/src/scene_builder.rs +++ b/webrender/src/scene_builder.rs @@ -194,46 +194,40 @@ pub enum SceneSwapResult { Aborted, } -// 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, -} +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, + )+ + } -impl DocumentResources { - /// Reports CPU heap memory used by the interners. - fn report_memory( - &self, - ops: &mut MallocSizeOfOps, - r: &mut MemoryReport, - ) { - let op = ops.size_of_op; - let eop = ops.enclosing_size_of_op.unwrap(); - 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); + 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); + )+ + } + } } } +enumerate_interners!(declare_document_resources); + // Access to `DocumentResources` interners by `Internable` pub trait InternerMut { diff --git a/webrender_api/src/api.rs b/webrender_api/src/api.rs index eebeabfebb..80ce10842d 100644 --- a/webrender_api/src/api.rs +++ b/webrender_api/src/api.rs @@ -816,14 +816,64 @@ impl PipelineId { } } +/// 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, @@ -833,8 +883,7 @@ pub struct MemoryReport { pub images: usize, pub rasterized_blobs: usize, pub shader_cache: usize, - pub data_stores: usize, - pub interners: usize, + pub interning: InterningMemoryReport, // // GPU memory. @@ -849,7 +898,6 @@ pub struct MemoryReport { 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; @@ -859,8 +907,8 @@ impl ::std::ops::AddAssign for MemoryReport { self.images += other.images; self.rasterized_blobs += other.rasterized_blobs; self.shader_cache += other.shader_cache; - self.data_stores += other.data_stores; - self.interners += other.interners; + self.interning += other.interning; + self.gpu_cache_textures += other.gpu_cache_textures; self.vertex_data_textures += other.vertex_data_textures; self.render_target_textures += other.render_target_textures;