diff --git a/Cargo.lock b/Cargo.lock index ba972b84971..bfa838b675f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -369,10 +369,10 @@ version = "0.0.1" dependencies = [ "base", "ipc-channel", - "malloc_size_of", "malloc_size_of_derive", "parking_lot", "serde", + "servo_malloc_size_of", "webrender_api", ] @@ -399,10 +399,10 @@ dependencies = [ "ipc-channel", "libc", "mach2", - "malloc_size_of", "malloc_size_of_derive", "parking_lot", "serde", + "servo_malloc_size_of", "static_assertions", "time 0.3.36", "webrender_api", @@ -734,12 +734,12 @@ dependencies = [ "euclid", "glow 0.16.0", "ipc-channel", - "malloc_size_of", "malloc_size_of_derive", "pixels", "serde", "serde_bytes", "servo_config", + "servo_malloc_size_of", "style", "webrender_api", "webxr-api", @@ -1527,10 +1527,10 @@ dependencies = [ "bitflags 2.6.0", "http", "ipc-channel", - "malloc_size_of", "malloc_size_of_derive", "net_traits", "serde", + "servo_malloc_size_of", "servo_url", "uuid", ] @@ -1640,9 +1640,10 @@ dependencies = [ [[package]] name = "dom" version = "0.0.1" -source = "git+https://github.com/servo/stylo?branch=2024-11-01#6605bdbb042735492efaa7530c40378cc1c21afa" +source = "git+https://github.com/servo/stylo?branch=2024-11-01#639802f35677f444a66fa1cf01bb579065cb2a27" dependencies = [ "bitflags 2.6.0", + "malloc_size_of", ] [[package]] @@ -2057,7 +2058,6 @@ dependencies = [ "itertools 0.13.0", "libc", "log", - "malloc_size_of", "malloc_size_of_derive", "memmap2", "net_traits", @@ -2069,6 +2069,7 @@ dependencies = [ "servo_arc", "servo_atoms", "servo_config", + "servo_malloc_size_of", "servo_url", "smallvec", "style", @@ -2091,10 +2092,10 @@ name = "fonts_traits" version = "0.0.1" dependencies = [ "ipc-channel", - "malloc_size_of", "malloc_size_of_derive", "range", "serde", + "servo_malloc_size_of", "webrender_api", ] @@ -3893,7 +3894,6 @@ dependencies = [ "html5ever", "ipc-channel", "log", - "malloc_size_of", "malloc_size_of_derive", "net_traits", "parking_lot", @@ -3909,6 +3909,7 @@ dependencies = [ "servo_atoms", "servo_config", "servo_geometry", + "servo_malloc_size_of", "servo_url", "smallvec", "style", @@ -3984,7 +3985,6 @@ dependencies = [ "ipc-channel", "layout_2013", "log", - "malloc_size_of", "metrics", "net_traits", "parking_lot", @@ -3998,6 +3998,7 @@ dependencies = [ "servo_arc", "servo_atoms", "servo_config", + "servo_malloc_size_of", "servo_url", "style", "style_traits", @@ -4023,7 +4024,6 @@ dependencies = [ "ipc-channel", "layout_2020", "log", - "malloc_size_of", "metrics", "net_traits", "parking_lot", @@ -4035,6 +4035,7 @@ dependencies = [ "servo_arc", "servo_atoms", "servo_config", + "servo_malloc_size_of", "servo_url", "style", "style_traits", @@ -4283,32 +4284,18 @@ dependencies = [ [[package]] name = "malloc_size_of" version = "0.0.1" -source = "git+https://github.com/servo/stylo?branch=2024-11-01#6605bdbb042735492efaa7530c40378cc1c21afa" +source = "git+https://github.com/servo/stylo?branch=2024-11-01#639802f35677f444a66fa1cf01bb579065cb2a27" dependencies = [ - "accountable-refcell", "app_units", - "content-security-policy", - "crossbeam-channel", "cssparser", - "dom", "euclid", - "http", - "indexmap", - "keyboard-types", "selectors", - "serde", - "serde_bytes", "servo_arc", "smallbitvec", "smallvec", "string_cache", "thin-vec", - "tokio", - "url", - "uuid", "void", - "webrender_api", - "xml5ever", ] [[package]] @@ -4326,8 +4313,8 @@ dependencies = [ name = "malloc_size_of_tests" version = "0.0.1" dependencies = [ - "malloc_size_of", "servo_arc", + "servo_malloc_size_of", ] [[package]] @@ -4435,11 +4422,11 @@ dependencies = [ "fonts_traits", "ipc-channel", "log", - "malloc_size_of", "malloc_size_of_derive", "profile_traits", "script_traits", "servo_config", + "servo_malloc_size_of", "servo_url", ] @@ -4704,7 +4691,6 @@ dependencies = [ "imsz", "ipc-channel", "log", - "malloc_size_of", "malloc_size_of_derive", "mime", "mime_guess", @@ -4720,6 +4706,7 @@ dependencies = [ "servo_allocator", "servo_arc", "servo_config", + "servo_malloc_size_of", "servo_url", "sha2", "time 0.3.36", @@ -4752,7 +4739,6 @@ dependencies = [ "image", "ipc-channel", "log", - "malloc_size_of", "malloc_size_of_derive", "mime", "num-traits", @@ -4761,6 +4747,7 @@ dependencies = [ "rustls", "serde", "servo_arc", + "servo_malloc_size_of", "servo_rand", "servo_url", "url", @@ -5496,9 +5483,9 @@ dependencies = [ "image", "ipc-channel", "log", - "malloc_size_of", "malloc_size_of_derive", "serde", + "servo_malloc_size_of", "webrender_api", ] @@ -5834,10 +5821,10 @@ dependencies = [ name = "range" version = "0.0.1" dependencies = [ - "malloc_size_of", "malloc_size_of_derive", "num-traits", "serde", + "servo_malloc_size_of", ] [[package]] @@ -6186,6 +6173,7 @@ dependencies = [ "servo_atoms", "servo_config", "servo_geometry", + "servo_malloc_size_of", "servo_rand", "servo_url", "smallvec", @@ -6224,7 +6212,6 @@ dependencies = [ "html5ever", "ipc-channel", "libc", - "malloc_size_of", "malloc_size_of_derive", "metrics", "net_traits", @@ -6236,6 +6223,7 @@ dependencies = [ "serde", "servo_arc", "servo_atoms", + "servo_malloc_size_of", "servo_url", "style", "style_traits", @@ -6274,7 +6262,6 @@ dependencies = [ "keyboard-types", "libc", "log", - "malloc_size_of", "malloc_size_of_derive", "media", "net_traits", @@ -6282,6 +6269,7 @@ dependencies = [ "profile_traits", "serde", "servo_atoms", + "servo_malloc_size_of", "servo_url", "smallvec", "style_traits", @@ -6319,7 +6307,7 @@ dependencies = [ [[package]] name = "selectors" version = "0.26.0" -source = "git+https://github.com/servo/stylo?branch=2024-11-01#6605bdbb042735492efaa7530c40378cc1c21afa" +source = "git+https://github.com/servo/stylo?branch=2024-11-01#639802f35677f444a66fa1cf01bb579065cb2a27" dependencies = [ "bitflags 2.6.0", "cssparser", @@ -6607,7 +6595,7 @@ dependencies = [ [[package]] name = "servo_arc" version = "0.4.0" -source = "git+https://github.com/servo/stylo?branch=2024-11-01#6605bdbb042735492efaa7530c40378cc1c21afa" +source = "git+https://github.com/servo/stylo?branch=2024-11-01#639802f35677f444a66fa1cf01bb579065cb2a27" dependencies = [ "serde", "stable_deref_trait", @@ -6616,7 +6604,7 @@ dependencies = [ [[package]] name = "servo_atoms" version = "0.0.1" -source = "git+https://github.com/servo/stylo?branch=2024-11-01#6605bdbb042735492efaa7530c40378cc1c21afa" +source = "git+https://github.com/servo/stylo?branch=2024-11-01#639802f35677f444a66fa1cf01bb579065cb2a27" dependencies = [ "string_cache", "string_cache_codegen", @@ -6657,21 +6645,51 @@ version = "0.0.1" dependencies = [ "app_units", "euclid", - "malloc_size_of", "malloc_size_of_derive", + "servo_malloc_size_of", "webrender_api", ] +[[package]] +name = "servo_malloc_size_of" +version = "0.0.1" +dependencies = [ + "accountable-refcell", + "app_units", + "content-security-policy", + "crossbeam-channel", + "dom", + "euclid", + "http", + "indexmap", + "keyboard-types", + "malloc_size_of", + "serde", + "serde_bytes", + "servo_allocator", + "servo_arc", + "smallvec", + "string_cache", + "style", + "thin-vec", + "tokio", + "url", + "uuid", + "webrender_api", + "wr_malloc_size_of", + "xml5ever", +] + [[package]] name = "servo_rand" version = "0.0.1" dependencies = [ "log", - "malloc_size_of", "malloc_size_of_derive", "rand", "rand_core", "rand_isaac", + "servo_malloc_size_of", "uuid", ] @@ -6679,10 +6697,10 @@ dependencies = [ name = "servo_url" version = "0.0.1" dependencies = [ - "malloc_size_of", "malloc_size_of_derive", "serde", "servo_arc", + "servo_malloc_size_of", "servo_rand", "to_shmem", "url", @@ -6960,7 +6978,7 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "static_prefs" version = "0.1.0" -source = "git+https://github.com/servo/stylo?branch=2024-11-01#6605bdbb042735492efaa7530c40378cc1c21afa" +source = "git+https://github.com/servo/stylo?branch=2024-11-01#639802f35677f444a66fa1cf01bb579065cb2a27" [[package]] name = "strck" @@ -7019,7 +7037,7 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "style" version = "0.0.1" -source = "git+https://github.com/servo/stylo?branch=2024-11-01#6605bdbb042735492efaa7530c40378cc1c21afa" +source = "git+https://github.com/servo/stylo?branch=2024-11-01#639802f35677f444a66fa1cf01bb579065cb2a27" dependencies = [ "app_units", "arrayvec", @@ -7077,7 +7095,7 @@ dependencies = [ [[package]] name = "style_config" version = "0.0.1" -source = "git+https://github.com/servo/stylo?branch=2024-11-01#6605bdbb042735492efaa7530c40378cc1c21afa" +source = "git+https://github.com/servo/stylo?branch=2024-11-01#639802f35677f444a66fa1cf01bb579065cb2a27" dependencies = [ "lazy_static", ] @@ -7085,7 +7103,7 @@ dependencies = [ [[package]] name = "style_derive" version = "0.0.1" -source = "git+https://github.com/servo/stylo?branch=2024-11-01#6605bdbb042735492efaa7530c40378cc1c21afa" +source = "git+https://github.com/servo/stylo?branch=2024-11-01#639802f35677f444a66fa1cf01bb579065cb2a27" dependencies = [ "darling", "proc-macro2", @@ -7115,7 +7133,7 @@ dependencies = [ [[package]] name = "style_traits" version = "0.0.1" -source = "git+https://github.com/servo/stylo?branch=2024-11-01#6605bdbb042735492efaa7530c40378cc1c21afa" +source = "git+https://github.com/servo/stylo?branch=2024-11-01#639802f35677f444a66fa1cf01bb579065cb2a27" dependencies = [ "app_units", "bitflags 2.6.0", @@ -7479,7 +7497,7 @@ dependencies = [ [[package]] name = "to_shmem" version = "0.1.0" -source = "git+https://github.com/servo/stylo?branch=2024-11-01#6605bdbb042735492efaa7530c40378cc1c21afa" +source = "git+https://github.com/servo/stylo?branch=2024-11-01#639802f35677f444a66fa1cf01bb579065cb2a27" dependencies = [ "cssparser", "servo_arc", @@ -7492,7 +7510,7 @@ dependencies = [ [[package]] name = "to_shmem_derive" version = "0.1.0" -source = "git+https://github.com/servo/stylo?branch=2024-11-01#6605bdbb042735492efaa7530c40378cc1c21afa" +source = "git+https://github.com/servo/stylo?branch=2024-11-01#639802f35677f444a66fa1cf01bb579065cb2a27" dependencies = [ "darling", "proc-macro2", @@ -8300,9 +8318,9 @@ dependencies = [ "euclid", "ipc-channel", "log", - "malloc_size_of", "serde", "servo_config", + "servo_malloc_size_of", "webrender", "webrender_api", "webrender_traits", diff --git a/Cargo.toml b/Cargo.toml index ae40a1c48f0..60ece24536f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -81,7 +81,7 @@ keyboard-types = "0.7" libc = "0.2" log = "0.4" mach2 = "0.4" -malloc_size_of = { git = "https://github.com/servo/stylo", branch = "2024-11-01", features = ["servo"] } +malloc_size_of = { package = "servo_malloc_size_of", path = "components/malloc_size_of" } malloc_size_of_derive = "0.1" memmap2 = "0.9.5" mime = "0.3.13" @@ -124,6 +124,7 @@ style = { git = "https://github.com/servo/stylo", branch = "2024-11-01", feature style_config = { git = "https://github.com/servo/stylo", branch = "2024-11-01" } style_dom = { git = "https://github.com/servo/stylo", package = "dom", branch = "2024-11-01" } style_traits = { git = "https://github.com/servo/stylo", branch = "2024-11-01", features = ["servo"] } +style_malloc_size_of = { package = "malloc_size_of", git = "https://github.com/servo/stylo", branch = "2024-11-01", features = ["servo"] } surfman = { git = "https://github.com/servo/surfman", rev = "c8d6b4b65aeab739ee7651602e29c8d58ceee123", features = ["chains"] } syn = { version = "2", default-features = false, features = ["clone-impls", "derive", "parsing"] } synstructure = "0.13" @@ -156,6 +157,7 @@ webxr-api = { git = "https://github.com/servo/webxr" } wgpu-core = "23" wgpu-types = "23" windows-sys = "0.59" +wr_malloc_size_of = { git = "https://github.com/servo/webrender", branch = "0.65" } xi-unicode = "0.3.0" xml5ever = "0.20" @@ -197,8 +199,6 @@ codegen-units = 1 # Or for Stylo: # # [patch."https://github.com/servo/stylo"] -# dom = { path = "../stylo/dom" } -# malloc_size_of = { path = "../stylo/malloc_size_of" } # selectors = { path = "../stylo/selectors" } # servo_arc = { path = "../stylo/servo_arc" } # servo_atoms = { path = "../stylo/atoms" } @@ -206,6 +206,8 @@ codegen-units = 1 # style = { path = "../stylo/style" } # style_config = { path = "../stylo/style_config" } # style_derive = { path = "../stylo/style_derive" } +# style_dom = { path = "../stylo/dom", package = "dom" } +# style_malloc_size_of = { path = "../stylo/malloc_size_of", package = "malloc_size_of" } # style_traits = { path = "../stylo/style_traits" } # to_shmem = { path = "../stylo/to_shmem" } # @@ -214,6 +216,7 @@ codegen-units = 1 # [patch."https://github.com/servo/webrender"] # webrender = { path = "../webrender/webrender" } # webrender_api = { path = "../webrender/webrender_api" } +# wr_malloc_size_of = { path = "../webrender/wr_malloc_size_of" } # # Or for another Git dependency: # diff --git a/components/malloc_size_of/Cargo.toml b/components/malloc_size_of/Cargo.toml new file mode 100644 index 00000000000..b4cd3a53e96 --- /dev/null +++ b/components/malloc_size_of/Cargo.toml @@ -0,0 +1,37 @@ +[package] +name = "servo_malloc_size_of" +license = "MIT OR Apache-2.0" +version.workspace = true +authors.workspace = true +edition.workspace = true +publish.workspace = true +rust-version.workspace = true + +[lib] +path = "lib.rs" + +[dependencies] +accountable-refcell = { workspace = true } +app_units = { workspace = true } +content-security-policy = { workspace = true } +crossbeam-channel = { workspace = true } +euclid = { workspace = true } +http = { workspace = true } +indexmap = { workspace = true } +keyboard-types = { workspace = true } +serde = { workspace = true } +serde_bytes = { workspace = true } +servo_allocator = { path = "../allocator" } +servo_arc = { workspace = true } +smallvec = { workspace = true } +string_cache = { workspace = true } +style = { workspace = true } +style_dom = { workspace = true } +style_malloc_size_of = { workspace = true } +thin-vec = { workspace = true } +tokio = { workspace = true } +url = { workspace = true } +uuid = { workspace = true } +webrender_api = { workspace = true } +wr_malloc_size_of = { workspace = true } +xml5ever = { workspace = true } diff --git a/components/malloc_size_of/LICENSE-APACHE b/components/malloc_size_of/LICENSE-APACHE new file mode 100644 index 00000000000..16fe87b06e8 --- /dev/null +++ b/components/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/components/malloc_size_of/LICENSE-MIT b/components/malloc_size_of/LICENSE-MIT new file mode 100644 index 00000000000..31aa79387f2 --- /dev/null +++ b/components/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/components/malloc_size_of/lib.rs b/components/malloc_size_of/lib.rs new file mode 100644 index 00000000000..58df961bb51 --- /dev/null +++ b/components/malloc_size_of/lib.rs @@ -0,0 +1,741 @@ +// 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 crate for measuring the heap usage of data structures in a way that +//! integrates with Firefox's memory reporting, particularly the use of +//! mozjemalloc and DMD. In particular, it has the following features. +//! - It isn't bound to a particular heap allocator. +//! - It provides traits for both "shallow" and "deep" measurement, which gives +//! flexibility in the cases where the traits can't be used. +//! - It allows for measuring blocks even when only an interior pointer can be +//! obtained for heap allocations, e.g. `HashSet` and `HashMap`. (This relies +//! on the heap allocator having suitable support, which mozjemalloc has.) +//! - It allows handling of types like `Rc` and `Arc` by providing traits that +//! are different to the ones for non-graph structures. +//! +//! Suggested uses are as follows. +//! - When possible, use the `MallocSizeOf` trait. (Deriving support is +//! provided by the `malloc_size_of_derive` crate.) +//! - If you need an additional synchronization argument, provide a function +//! that is like the standard trait method, but with the extra argument. +//! - If you need multiple measurements for a type, provide a function named +//! `add_size_of` that takes a mutable reference to a struct that contains +//! the multiple measurement fields. +//! - When deep measurement (via `MallocSizeOf`) cannot be implemented for a +//! type, shallow measurement (via `MallocShallowSizeOf`) in combination with +//! iteration can be a useful substitute. +//! - `Rc` and `Arc` are always tricky, which is why `MallocSizeOf` is not (and +//! should not be) implemented for them. +//! - If an `Rc` or `Arc` is known to be a "primary" reference and can always +//! be measured, it should be measured via the `MallocUnconditionalSizeOf` +//! trait. +//! - If an `Rc` or `Arc` should be measured only if it hasn't been seen +//! before, it should be measured via the `MallocConditionalSizeOf` trait. +//! - Using universal function call syntax is a good idea when measuring boxed +//! fields in structs, because it makes it clear that the Box is being +//! measured as well as the thing it points to. E.g. +//! ` as MallocSizeOf>::size_of(field, ops)`. +//! +//! Note: WebRender has a reduced fork of this crate, so that we can avoid +//! publishing this crate on crates.io. + +use std::hash::{BuildHasher, Hash}; +use std::ops::Range; + +pub use style_malloc_size_of::MallocSizeOfOps; +use uuid::Uuid; + +/// 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; +} + +/// Like `MallocSizeOf`, but with a different name so it cannot be used +/// accidentally with derive(MallocSizeOf). For use with types like `Rc` and +/// `Arc` when appropriate (e.g. when measuring a "primary" reference). +pub trait MallocUnconditionalSizeOf { + /// Measure the heap usage of all heap-allocated descendant structures, but + /// not the space taken up by the value itself. + fn unconditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize; +} + +/// `MallocUnconditionalSizeOf` combined with `MallocShallowSizeOf`. +pub trait MallocUnconditionalShallowSizeOf { + /// `unconditional_size_of` combined with `shallow_size_of`. + fn unconditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize; +} + +/// Like `MallocSizeOf`, but only measures if the value hasn't already been +/// measured. For use with types like `Rc` and `Arc` when appropriate (e.g. +/// when there is no "primary" reference). +pub trait MallocConditionalSizeOf { + /// Measure the heap usage of all heap-allocated descendant structures, but + /// not the space taken up by the value itself, and only if that heap usage + /// hasn't already been measured. + fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize; +} + +/// `MallocConditionalSizeOf` combined with `MallocShallowSizeOf`. +pub trait MallocConditionalShallowSizeOf { + /// `conditional_size_of` combined with `shallow_size_of`. + fn conditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize; +} + +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 + } +} + +/// 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 + } + } + )+ + ); +); + +impl MallocSizeOf for keyboard_types::Key { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + match self { + keyboard_types::Key::Character(ref string) => { + ::size_of(string, ops) + }, + _ => 0, + } + } +} + +impl MallocSizeOf for xml5ever::QualName { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + self.prefix.size_of(ops) + self.ns.size_of(ops) + self.local.size_of(ops) + } +} + +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 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 + } +} + +impl MallocShallowSizeOf for std::collections::VecDeque { + fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + if ops.has_malloc_enclosing_size_of() { + if let Some(front) = self.front() { + // The front element is an interior pointer. + unsafe { ops.malloc_enclosing_size_of(front) } + } else { + // This assumes that no memory is allocated when the VecDeque is empty. + 0 + } + } else { + // An estimate. + self.capacity() * size_of::() + } + } +} + +impl MallocSizeOf for std::collections::VecDeque { + 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 + } +} + +impl MallocShallowSizeOf for smallvec::SmallVec { + fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + if self.spilled() { + unsafe { ops.malloc_size_of(self.as_ptr()) } + } else { + 0 + } + } +} + +impl MallocSizeOf for smallvec::SmallVec +where + A: smallvec::Array, + A::Item: MallocSizeOf, +{ + 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 + } +} + +impl MallocShallowSizeOf for thin_vec::ThinVec { + fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + if self.capacity() == 0 { + // If it's the singleton we might not be a heap pointer. + return 0; + } + + assert_eq!( + std::mem::size_of::(), + std::mem::size_of::<*const ()>() + ); + unsafe { ops.malloc_size_of(*(self as *const Self as *const *const ())) } + } +} + +impl MallocSizeOf for thin_vec::ThinVec { + 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); + +impl MallocShallowSizeOf for std::collections::BTreeMap +where + K: Eq + Hash, +{ + fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + if ops.has_malloc_enclosing_size_of() { + self.values() + .next() + .map_or(0, |v| unsafe { ops.malloc_enclosing_size_of(v) }) + } else { + self.len() * (size_of::() + size_of::() + size_of::()) + } + } +} + +impl MallocSizeOf for std::collections::BTreeMap +where + K: Eq + Hash + MallocSizeOf, + V: MallocSizeOf, +{ + 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 + } +} + +// PhantomData is always 0. +impl MallocSizeOf for std::marker::PhantomData { + fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize { + 0 + } +} + +// See https://github.com/rust-lang/rust/issues/68318: +// We don't want MallocSizeOf to be defined for Rc and Arc. If negative trait bounds are +// ever allowed, this code should be uncommented. Instead, there is a compile-fail test for +// this. +//impl !MallocSizeOf for Arc { } +//impl !MallocShallowSizeOf for Arc { } + +impl MallocUnconditionalShallowSizeOf for servo_arc::Arc { + fn unconditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + unsafe { ops.malloc_size_of(self.heap_ptr()) } + } +} + +impl MallocUnconditionalSizeOf for servo_arc::Arc { + fn unconditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + self.unconditional_shallow_size_of(ops) + (**self).size_of(ops) + } +} + +impl MallocConditionalShallowSizeOf for servo_arc::Arc { + fn conditional_shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + if ops.have_seen_ptr(self.heap_ptr()) { + 0 + } else { + self.unconditional_shallow_size_of(ops) + } + } +} + +impl MallocConditionalSizeOf for servo_arc::Arc { + fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + if ops.have_seen_ptr(self.heap_ptr()) { + 0 + } else { + self.unconditional_size_of(ops) + } + } +} + +/// If a mutex is stored directly as a member of a data type that is being measured, +/// it is the unique owner of its contents and deserves to be measured. +/// +/// If a mutex is stored inside of an Arc value as a member of a data type that is being measured, +/// the Arc will not be automatically measured so there is no risk of overcounting the mutex's +/// contents. +impl MallocSizeOf for std::sync::Mutex { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + (*self.lock().unwrap()).size_of(ops) + } +} + +impl MallocSizeOf for euclid::Length { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + self.0.size_of(ops) + } +} + +impl MallocSizeOf for euclid::Scale { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + self.0.size_of(ops) + } +} + +impl MallocSizeOf for euclid::Point2D { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + self.x.size_of(ops) + self.y.size_of(ops) + } +} + +impl MallocSizeOf for euclid::Rect { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + self.origin.size_of(ops) + self.size.size_of(ops) + } +} + +impl MallocSizeOf for euclid::SideOffsets2D { + 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::Size2D { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + self.width.size_of(ops) + self.height.size_of(ops) + } +} + +impl MallocSizeOf for euclid::Transform2D { + 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::Transform3D { + 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 url::Host { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + match *self { + url::Host::Domain(ref s) => s.size_of(ops), + _ => 0, + } + } +} + +impl MallocSizeOf for euclid::Vector2D { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + self.x.size_of(ops) + self.y.size_of(ops) + } +} + +impl MallocSizeOf for string_cache::Atom { + fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize { + 0 + } +} + +// Placeholder for unique case where internals of Sender cannot be measured. +// malloc size of is 0 macro complains about type supplied! +impl MallocSizeOf for crossbeam_channel::Sender { + fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize { + 0 + } +} + +impl MallocSizeOf for tokio::sync::mpsc::UnboundedSender { + fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize { + 0 + } +} + +impl MallocSizeOf for accountable_refcell::RefCell { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + self.borrow().size_of(ops) + } +} + +malloc_size_of_hash_map!(indexmap::IndexMap); +malloc_size_of_hash_set!(indexmap::IndexSet); + +malloc_size_of_is_0!(bool, char, str); +malloc_size_of_is_0!(f32, f64); +malloc_size_of_is_0!(i8, i16, i32, i64, i128, isize); +malloc_size_of_is_0!(u8, u16, u32, u64, u128, usize); + +malloc_size_of_is_0!(Range, Range); +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!(Uuid); +malloc_size_of_is_0!(content_security_policy::Destination); +malloc_size_of_is_0!(http::StatusCode); +malloc_size_of_is_0!(app_units::Au); +malloc_size_of_is_0!(keyboard_types::Modifiers); +malloc_size_of_is_0!(std::num::NonZeroU64); +malloc_size_of_is_0!(std::num::NonZeroUsize); +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::time::Duration); +malloc_size_of_is_0!(std::time::Instant); +malloc_size_of_is_0!(std::time::SystemTime); + +macro_rules! malloc_size_of_is_webrender_malloc_size_of( + ($($ty:ty),+) => ( + $( + impl MallocSizeOf for $ty { + fn size_of(&self, _: &mut MallocSizeOfOps) -> usize { + let mut ops = wr_malloc_size_of::MallocSizeOfOps::new(servo_allocator::usable_size, None); + <$ty as wr_malloc_size_of::MallocSizeOf>::size_of(self, &mut ops) + } + } + )+ + ); +); + +malloc_size_of_is_webrender_malloc_size_of!(webrender_api::BorderRadius); +malloc_size_of_is_webrender_malloc_size_of!(webrender_api::BorderStyle); +malloc_size_of_is_webrender_malloc_size_of!(webrender_api::BoxShadowClipMode); +malloc_size_of_is_webrender_malloc_size_of!(webrender_api::ColorF); +malloc_size_of_is_webrender_malloc_size_of!(webrender_api::ExtendMode); +malloc_size_of_is_webrender_malloc_size_of!(webrender_api::FontInstanceKey); +malloc_size_of_is_webrender_malloc_size_of!(webrender_api::GlyphInstance); +malloc_size_of_is_webrender_malloc_size_of!(webrender_api::GradientStop); +malloc_size_of_is_webrender_malloc_size_of!(webrender_api::ImageKey); +malloc_size_of_is_webrender_malloc_size_of!(webrender_api::ImageRendering); +malloc_size_of_is_webrender_malloc_size_of!(webrender_api::LineStyle); +malloc_size_of_is_webrender_malloc_size_of!(webrender_api::MixBlendMode); +malloc_size_of_is_webrender_malloc_size_of!(webrender_api::NormalBorder); +malloc_size_of_is_webrender_malloc_size_of!(webrender_api::RepeatMode); + +macro_rules! malloc_size_of_is_style_malloc_size_of( + ($($ty:ty),+) => ( + $( + impl MallocSizeOf for $ty { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + <$ty as style_malloc_size_of::MallocSizeOf>::size_of(self, ops) + } + } + )+ + ); +); + +impl MallocSizeOf for style::author_styles::GenericAuthorStyles +where + S: style::stylesheets::StylesheetInDocument + + std::cmp::PartialEq + + style_malloc_size_of::MallocSizeOf, +{ + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + as style_malloc_size_of::MallocSizeOf>::size_of(self, ops) + } +} + +impl MallocSizeOf for style::stylesheet_set::DocumentStylesheetSet +where + S: style::stylesheets::StylesheetInDocument + + std::cmp::PartialEq + + style_malloc_size_of::MallocSizeOf, +{ + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + as style_malloc_size_of::MallocSizeOf>::size_of(self, ops) + } +} + +malloc_size_of_is_style_malloc_size_of!(style::animation::DocumentAnimationSet); +malloc_size_of_is_style_malloc_size_of!(style::attr::AttrIdentifier); +malloc_size_of_is_style_malloc_size_of!(style::attr::AttrValue); +malloc_size_of_is_style_malloc_size_of!(style::color::AbsoluteColor); +malloc_size_of_is_style_malloc_size_of!(style::computed_values::font_variant_caps::T); +malloc_size_of_is_style_malloc_size_of!(style::dom::OpaqueNode); +malloc_size_of_is_style_malloc_size_of!(style::invalidation::element::restyle_hints::RestyleHint); +malloc_size_of_is_style_malloc_size_of!(style::media_queries::MediaList); +malloc_size_of_is_style_malloc_size_of!(style::properties::style_structs::Font); +malloc_size_of_is_style_malloc_size_of!(style::selector_parser::PseudoElement); +malloc_size_of_is_style_malloc_size_of!(style::selector_parser::RestyleDamage); +malloc_size_of_is_style_malloc_size_of!(style::selector_parser::Snapshot); +malloc_size_of_is_style_malloc_size_of!(style::shared_lock::SharedRwLock); +malloc_size_of_is_style_malloc_size_of!(style::stylesheets::DocumentStyleSheet); +malloc_size_of_is_style_malloc_size_of!(style::stylist::Stylist); +malloc_size_of_is_style_malloc_size_of!(style::values::computed::FontStretch); +malloc_size_of_is_style_malloc_size_of!(style::values::computed::FontStyle); +malloc_size_of_is_style_malloc_size_of!(style::values::computed::FontWeight); +malloc_size_of_is_style_malloc_size_of!(style::values::computed::font::SingleFontFamily); +malloc_size_of_is_style_malloc_size_of!(style_dom::ElementState); diff --git a/components/net/http_cache.rs b/components/net/http_cache.rs index c158464c5bb..8f479801c08 100644 --- a/components/net/http_cache.rs +++ b/components/net/http_cache.rs @@ -19,10 +19,7 @@ use headers::{ use http::header::HeaderValue; use http::{header, HeaderMap, Method, StatusCode}; use log::debug; -use malloc_size_of::{ - MallocSizeOf, MallocSizeOfOps, MallocUnconditionalShallowSizeOf, MallocUnconditionalSizeOf, - Measurable, -}; +use malloc_size_of::{MallocSizeOf, MallocSizeOfOps, MallocUnconditionalSizeOf}; use malloc_size_of_derive::MallocSizeOf; use net_traits::http_status::HttpStatus; use net_traits::request::Request; @@ -63,11 +60,6 @@ struct CachedResource { body: Arc>, aborted: Arc, awaiting_body: Arc>>>, - data: Measurable, -} - -#[derive(Clone, MallocSizeOf)] -struct MeasurableCachedResource { metadata: CachedMetadata, location_url: Option>, https_state: HttpsState, @@ -83,21 +75,22 @@ impl MallocSizeOf for CachedResource { self.body.unconditional_size_of(ops) + self.aborted.unconditional_size_of(ops) + self.awaiting_body.unconditional_size_of(ops) + - self.data.size_of(ops) + self.metadata.size_of(ops) + + self.location_url.size_of(ops) + + self.https_state.size_of(ops) + + self.status.size_of(ops) + + self.url_list.size_of(ops) + + self.expires.size_of(ops) + + self.last_validated.size_of(ops) } } /// Metadata about a loaded resource, such as is obtained from HTTP headers. -#[derive(Clone)] +#[derive(Clone, MallocSizeOf)] struct CachedMetadata { /// Headers + #[ignore_malloc_size_of = "Defined in `http` and has private members"] pub headers: Arc>, - /// Fields that implement MallocSizeOf - pub data: Measurable, -} - -#[derive(Clone, MallocSizeOf)] -struct MeasurableCachedMetadata { /// Final URL after redirects. pub final_url: ServoUrl, /// MIME type / subtype. @@ -107,15 +100,6 @@ struct MeasurableCachedMetadata { /// HTTP Status pub status: HttpStatus, } - -impl MallocSizeOf for CachedMetadata { - fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { - self.headers.unconditional_shallow_size_of(ops) + - // TODO: self.headers.size_of(ops) + - self.data.size_of(ops) - } -} - /// Wrapper around a cached response, including information on re-validation needs pub struct CachedResponse { /// The response constructed from the cached resource @@ -298,10 +282,7 @@ fn create_cached_response( return None; } let resource_timing = ResourceFetchTiming::new(request.timing_type()); - let mut response = Response::new( - cached_resource.data.metadata.data.final_url.clone(), - resource_timing, - ); + let mut response = Response::new(cached_resource.metadata.final_url.clone(), resource_timing); response.headers = cached_headers.clone(); response.body = cached_resource.body.clone(); if let ResponseBody::Receiving(_) = *cached_resource.body.lock().unwrap() { @@ -316,17 +297,17 @@ fn create_cached_response( } response .location_url - .clone_from(&cached_resource.data.location_url); - response.status.clone_from(&cached_resource.data.status); - response.url_list.clone_from(&cached_resource.data.url_list); - response.https_state = cached_resource.data.https_state; + .clone_from(&cached_resource.location_url); + response.status.clone_from(&cached_resource.status); + response.url_list.clone_from(&cached_resource.url_list); + response.https_state = cached_resource.https_state; response.referrer = request.referrer.to_url().cloned(); response.referrer_policy = request.referrer_policy; response.aborted = cached_resource.aborted.clone(); - let expires = cached_resource.data.expires; + let expires = cached_resource.expires; let adjusted_expires = get_expiry_adjustment_from_request_headers(request, expires); - let time_since_validated = Instant::now() - cached_resource.data.last_validated; + let time_since_validated = Instant::now() - cached_resource.last_validated; // TODO: take must-revalidate into account // TODO: if this cache is to be considered shared, take proxy-revalidate into account @@ -350,15 +331,13 @@ fn create_resource_with_bytes_from_resource( body: Arc::new(Mutex::new(ResponseBody::Done(bytes.to_owned()))), aborted: Arc::new(AtomicBool::new(false)), awaiting_body: Arc::new(Mutex::new(vec![])), - data: Measurable(MeasurableCachedResource { - metadata: resource.data.metadata.clone(), - location_url: resource.data.location_url.clone(), - https_state: resource.data.https_state, - status: StatusCode::PARTIAL_CONTENT.into(), - url_list: resource.data.url_list.clone(), - expires: resource.data.expires, - last_validated: resource.data.last_validated, - }), + metadata: resource.metadata.clone(), + location_url: resource.location_url.clone(), + https_state: resource.https_state, + status: StatusCode::PARTIAL_CONTENT.into(), + url_list: resource.url_list.clone(), + expires: resource.expires, + last_validated: resource.last_validated, } } @@ -371,10 +350,10 @@ fn handle_range_request( ) -> Option { let mut complete_cached_resources = candidates .iter() - .filter(|resource| resource.data.status == StatusCode::OK); + .filter(|resource| resource.status == StatusCode::OK); let partial_cached_resources = candidates .iter() - .filter(|resource| resource.data.status == StatusCode::PARTIAL_CONTENT); + .filter(|resource| resource.status == StatusCode::PARTIAL_CONTENT); match ( range_spec.first().unwrap(), complete_cached_resources.next(), @@ -399,7 +378,7 @@ fn handle_range_request( if let Some(bytes) = requested { let new_resource = create_resource_with_bytes_from_resource(bytes, complete_resource); - let cached_headers = new_resource.data.metadata.headers.lock().unwrap(); + let cached_headers = new_resource.metadata.headers.lock().unwrap(); let cached_response = create_cached_response(request, &new_resource, &cached_headers, done_chan); if let Some(cached_response) = cached_response { @@ -410,7 +389,7 @@ fn handle_range_request( }, (&(Bound::Included(beginning), Bound::Included(end)), None) => { for partial_resource in partial_cached_resources { - let headers = partial_resource.data.metadata.headers.lock().unwrap(); + let headers = partial_resource.metadata.headers.lock().unwrap(); let content_range = headers.typed_get::(); let (res_beginning, res_end) = match content_range { Some(range) => { @@ -451,7 +430,7 @@ fn handle_range_request( if let Some(bytes) = requested { let new_resource = create_resource_with_bytes_from_resource(bytes, complete_resource); - let cached_headers = new_resource.data.metadata.headers.lock().unwrap(); + let cached_headers = new_resource.metadata.headers.lock().unwrap(); let cached_response = create_cached_response(request, &new_resource, &cached_headers, done_chan); if let Some(cached_response) = cached_response { @@ -462,7 +441,7 @@ fn handle_range_request( }, (&(Bound::Included(beginning), Bound::Unbounded), None) => { for partial_resource in partial_cached_resources { - let headers = partial_resource.data.metadata.headers.lock().unwrap(); + let headers = partial_resource.metadata.headers.lock().unwrap(); let content_range = headers.typed_get::(); let (res_beginning, res_end, total) = if let Some(range) = content_range { match (range.bytes_range(), range.bytes_len()) { @@ -504,7 +483,7 @@ fn handle_range_request( if let Some(bytes) = requested { let new_resource = create_resource_with_bytes_from_resource(bytes, complete_resource); - let cached_headers = new_resource.data.metadata.headers.lock().unwrap(); + let cached_headers = new_resource.metadata.headers.lock().unwrap(); let cached_response = create_cached_response(request, &new_resource, &cached_headers, done_chan); if let Some(cached_response) = cached_response { @@ -515,7 +494,7 @@ fn handle_range_request( }, (&(Bound::Unbounded, Bound::Included(offset)), None) => { for partial_resource in partial_cached_resources { - let headers = partial_resource.data.metadata.headers.lock().unwrap(); + let headers = partial_resource.metadata.headers.lock().unwrap(); let content_range = headers.typed_get::(); let (res_beginning, res_end, total) = if let Some(range) = content_range { match (range.bytes_range(), range.bytes_len()) { @@ -580,7 +559,7 @@ impl HttpCache { let mut candidates = vec![]; for cached_resource in resources { let mut can_be_constructed = true; - let cached_headers = cached_resource.data.metadata.headers.lock().unwrap(); + let cached_headers = cached_resource.metadata.headers.lock().unwrap(); let original_request_headers = cached_resource.request_headers.lock().unwrap(); if let Some(vary_value) = cached_headers.typed_get::() { if vary_value.is_any() { @@ -647,7 +626,7 @@ impl HttpCache { // // TODO: Combining partial content to fulfill a non-Range request // see https://tools.ietf.org/html/rfc7234#section-3.3 - match cached_resource.data.status.try_code() { + match cached_resource.status.try_code() { Some(ref code) => { if *code == StatusCode::PARTIAL_CONTENT { continue; @@ -658,7 +637,7 @@ impl HttpCache { // Returning a response that can be constructed // TODO: select the most appropriate one, using a known mechanism from a selecting header field, // or using the Date header to return the most recent one. - let cached_headers = cached_resource.data.metadata.headers.lock().unwrap(); + let cached_headers = cached_resource.metadata.headers.lock().unwrap(); let cached_response = create_cached_response(request, cached_resource, &cached_headers, done_chan); if let Some(cached_response) = cached_response { @@ -687,7 +666,7 @@ impl HttpCache { if response.actual_response().is_network_error() { return *resource.body.lock().unwrap() == ResponseBody::Empty; } - resource.data.status == response.status + resource.status == response.status }); for cached_resource in relevant_cached_resources { @@ -750,25 +729,23 @@ impl HttpCache { // 1. update the headers of the cached resource. // 2. return a response, constructed from the cached resource. let resource_timing = ResourceFetchTiming::new(request.timing_type()); - let mut constructed_response = Response::new( - cached_resource.data.metadata.data.final_url.clone(), - resource_timing, - ); + let mut constructed_response = + Response::new(cached_resource.metadata.final_url.clone(), resource_timing); constructed_response.body = cached_resource.body.clone(); constructed_response .status - .clone_from(&cached_resource.data.status); - constructed_response.https_state = cached_resource.data.https_state; + .clone_from(&cached_resource.status); + constructed_response.https_state = cached_resource.https_state; constructed_response.referrer = request.referrer.to_url().cloned(); constructed_response.referrer_policy = request.referrer_policy; constructed_response .status - .clone_from(&cached_resource.data.status); + .clone_from(&cached_resource.status); constructed_response .url_list - .clone_from(&cached_resource.data.url_list); - cached_resource.data.expires = get_response_expiry(&constructed_response); - let mut stored_headers = cached_resource.data.metadata.headers.lock().unwrap(); + .clone_from(&cached_resource.url_list); + cached_resource.expires = get_response_expiry(&constructed_response); + let mut stored_headers = cached_resource.metadata.headers.lock().unwrap(); stored_headers.extend(response.headers); constructed_response.headers = stored_headers.clone(); return Some(constructed_response); @@ -781,7 +758,7 @@ impl HttpCache { let entry_key = CacheKey::from_servo_url(url); if let Some(cached_resources) = self.entries.get_mut(&entry_key) { for cached_resource in cached_resources.iter_mut() { - cached_resource.data.expires = Duration::ZERO; + cached_resource.expires = Duration::ZERO; } } } @@ -845,27 +822,23 @@ impl HttpCache { let expiry = get_response_expiry(response); let cacheable_metadata = CachedMetadata { headers: Arc::new(Mutex::new(response.headers.clone())), - data: Measurable(MeasurableCachedMetadata { - final_url: metadata.final_url, - content_type: metadata.content_type.map(|v| v.0.to_string()), - charset: metadata.charset, - status: metadata.status, - }), + final_url: metadata.final_url, + content_type: metadata.content_type.map(|v| v.0.to_string()), + charset: metadata.charset, + status: metadata.status, }; let entry_resource = CachedResource { request_headers: Arc::new(Mutex::new(request.headers.clone())), body: response.body.clone(), aborted: response.aborted.clone(), awaiting_body: Arc::new(Mutex::new(vec![])), - data: Measurable(MeasurableCachedResource { - metadata: cacheable_metadata, - location_url: response.location_url.clone(), - https_state: response.https_state, - status: response.status.clone(), - url_list: response.url_list.clone(), - expires: expiry, - last_validated: Instant::now(), - }), + metadata: cacheable_metadata, + location_url: response.location_url.clone(), + https_state: response.https_state, + status: response.status.clone(), + url_list: response.url_list.clone(), + expires: expiry, + last_validated: Instant::now(), }; let entry = self.entries.entry(entry_key).or_default(); entry.push(entry_resource); diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml index c1b8bed89b6..cf003639e67 100644 --- a/components/script/Cargo.toml +++ b/components/script/Cargo.toml @@ -107,6 +107,7 @@ servo_geometry = { path = "../geometry" } servo_rand = { path = "../rand" } servo_url = { path = "../url" } smallvec = { workspace = true, features = ["union"] } +style_malloc_size_of = { workspace = true } glow = { workspace = true } style = { workspace = true } style_dom = { workspace = true } diff --git a/components/script/dom/documentorshadowroot.rs b/components/script/dom/documentorshadowroot.rs index 7e9e58fe3a3..96323156ba8 100644 --- a/components/script/dom/documentorshadowroot.rs +++ b/components/script/dom/documentorshadowroot.rs @@ -37,6 +37,14 @@ pub struct StyleSheetInDocument { pub owner: Dom, } +// This is necessary because this type is contained within a Stylo type which needs +// Stylo's version of MallocSizeOf. +impl style_malloc_size_of::MallocSizeOf for StyleSheetInDocument { + fn size_of(&self, ops: &mut style_malloc_size_of::MallocSizeOfOps) -> usize { + ::size_of(self, ops) + } +} + impl fmt::Debug for StyleSheetInDocument { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.sheet.fmt(formatter)