зеркало из https://github.com/mozilla/gecko-dev.git
servo: Merge #18452 - Overhaul MallocSizeOf and related things (from nnethercote:bug-1398737); r=jdm
This patch makes the MallocSizeOf stuff in Stylo work more like the HeapSizeOf stuff already in Servo, except better. In particular, it adds deriving support for MallocSizeOf, which will make it easier to improve coverage. The patch does the following. - Combines servo/components/style/stylesheets/memory.rs and the heapsize crate into a new crate, malloc_size_of. - Forks the heapsize_derive crate, calling it malloc_size_of, so that MallocSizeOf can be derived. - Both the new crates have MIT/Apache licenses, like heapsize, in case they are incorporated into heapsize in the future. - Renames the methods within MallocSizeOf and the related traits so they are more concise. - Removes MallocSizeOfWithGuard. - Adds `derive(MallocSizeOf)` to a lot of types, in some cases replacing an equivalent or almost-equivalent hand-written implementation. - Adds stuff so that Rc/Arc can be handled properly. <!-- Please describe your changes on the following line: --> --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [X] `./mach build -d` does not report any errors - [X] `./mach test-tidy` does not report any errors - [ ] These changes fix #__ (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [X] These changes do not require tests because tested on Gecko side. <!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.--> <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> Source-Repo: https://github.com/servo/servo Source-Revision: 7f4cb1861b172423781a369b2decca6c65d60546 --HG-- rename : servo/components/hashglobe/LICENSE-APACHE => servo/components/malloc_size_of/LICENSE-APACHE rename : servo/components/hashglobe/LICENSE-MIT => servo/components/malloc_size_of/LICENSE-MIT rename : servo/components/jstraceable_derive/Cargo.toml => servo/components/malloc_size_of_derive/Cargo.toml rename : servo/components/hashglobe/LICENSE-APACHE => servo/components/malloc_size_of_derive/LICENSE-APACHE rename : servo/components/hashglobe/LICENSE-MIT => servo/components/malloc_size_of_derive/LICENSE-MIT extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : a8254c4ae15901b764d918355e900a1e74d6eb03
This commit is contained in:
Родитель
8cdad036f1
Коммит
43983aa52e
|
@ -1081,6 +1081,7 @@ dependencies = [
|
|||
"env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"malloc_size_of 0.0.1",
|
||||
"nsstring_vendor 0.1.0",
|
||||
"parking_lot 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"selectors 0.19.0",
|
||||
|
@ -1733,6 +1734,25 @@ dependencies = [
|
|||
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "malloc_size_of"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"hashglobe 0.1.0",
|
||||
"servo_arc 0.0.1",
|
||||
"smallbitvec 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "malloc_size_of_derive"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"synstructure 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "markup5ever"
|
||||
version = "0.4.0"
|
||||
|
@ -2693,6 +2713,8 @@ dependencies = [
|
|||
"cssparser 0.20.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"malloc_size_of 0.0.1",
|
||||
"malloc_size_of_derive 0.0.1",
|
||||
"matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -3107,6 +3129,8 @@ dependencies = [
|
|||
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"malloc_size_of 0.0.1",
|
||||
"malloc_size_of_derive 0.0.1",
|
||||
"matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nsstring_vendor 0.1.0",
|
||||
"num-integer 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -3195,6 +3219,7 @@ dependencies = [
|
|||
"geckoservo 0.0.1",
|
||||
"libc 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"malloc_size_of 0.0.1",
|
||||
"regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"selectors 0.19.0",
|
||||
"size_of_test 0.0.1",
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
[package]
|
||||
name = "malloc_size_of"
|
||||
version = "0.0.1"
|
||||
authors = ["The Servo Project Developers"]
|
||||
license = "MIT/Apache-2.0"
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
||||
[dependencies]
|
||||
hashglobe = { path = "../hashglobe" }
|
||||
servo_arc = { path = "../servo_arc" }
|
||||
smallbitvec = "1.0.3"
|
||||
smallvec = "0.4"
|
|
@ -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.
|
|
@ -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.
|
|
@ -0,0 +1,346 @@
|
|||
// Copyright 2016-2017 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! A 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.
|
||||
//!
|
||||
//! This crate has a lot of overlap with the existing `heapsize` crate, and may
|
||||
//! one day be merged into it. But for now, `heapsize` has the following
|
||||
//! major shortcomings.
|
||||
//! - It basically assumes that the `HeapSizeOf` trait can be used for every
|
||||
//! type, which is not true. Sometimes more than a single size measurement
|
||||
//! needs to be returned for a type, and sometimes additional synchronization
|
||||
//! arguments (such as lock guards) need to be passed in.
|
||||
//! - It has no proper way of measuring some common types, such as `HashSet`
|
||||
//! and `HashMap`, that don't expose internal pointers.
|
||||
//! - It has no proper way of handling values with multiple referents, such as
|
||||
//! `Rc` and `Arc`.
|
||||
//!
|
||||
//! This crate solves those problems.
|
||||
//! - It provides traits for both "shallow" and "deep" measurement, which gives
|
||||
//! more 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 special
|
||||
//! 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_children` 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.
|
||||
//! `<Box<_> as MallocSizeOf>::size_of(field, ops)`.
|
||||
|
||||
extern crate hashglobe;
|
||||
extern crate servo_arc;
|
||||
extern crate smallbitvec;
|
||||
extern crate smallvec;
|
||||
|
||||
use hashglobe::hash_map::HashMap;
|
||||
use servo_arc::Arc;
|
||||
use smallbitvec::SmallBitVec;
|
||||
use smallvec::{Array, SmallVec};
|
||||
use std::collections::HashSet;
|
||||
use std::hash::{BuildHasher, Hash};
|
||||
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;
|
||||
|
||||
/// A closure implementing a stateful predicate on pointers.
|
||||
type VoidPtrToBoolFnMut = FnMut(*const c_void) -> bool;
|
||||
|
||||
/// Operations used when measuring heap usage of data structures.
|
||||
pub struct MallocSizeOfOps {
|
||||
/// A function that returns the size of a heap allocation.
|
||||
size_of_op: VoidPtrToSizeFn,
|
||||
|
||||
/// Like `size_of_op`, but can take an interior pointer. Optional, because
|
||||
/// many places don't need it.
|
||||
enclosing_size_of_op: Option<VoidPtrToSizeFn>,
|
||||
|
||||
/// Check if a pointer has been seen before, and remember it for next time.
|
||||
/// Useful when measuring `Rc`s and `Arc`s. Optional, because many places
|
||||
/// don't need it.
|
||||
have_seen_ptr_op: Option<Box<VoidPtrToBoolFnMut>>,
|
||||
}
|
||||
|
||||
impl MallocSizeOfOps {
|
||||
pub fn new(size_of: VoidPtrToSizeFn,
|
||||
malloc_enclosing_size_of: Option<VoidPtrToSizeFn>,
|
||||
have_seen_ptr: Option<Box<VoidPtrToBoolFnMut>>) -> Self {
|
||||
MallocSizeOfOps {
|
||||
size_of_op: size_of,
|
||||
enclosing_size_of_op: malloc_enclosing_size_of,
|
||||
have_seen_ptr_op: have_seen_ptr,
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if an allocation is empty. This relies on knowledge of how Rust
|
||||
/// handles empty allocations, which may change in the future.
|
||||
fn is_empty<T>(ptr: *const T) -> bool {
|
||||
return ptr as usize <= ::std::mem::align_of::<T>();
|
||||
}
|
||||
|
||||
/// Call `size_of_op` on `ptr`, first checking that the allocation isn't
|
||||
/// empty, because some types (such as `Vec`) utilize empty allocations.
|
||||
pub fn malloc_size_of<T>(&self, ptr: *const T) -> usize {
|
||||
if MallocSizeOfOps::is_empty(ptr) {
|
||||
0
|
||||
} else {
|
||||
unsafe { (self.size_of_op)(ptr as *const c_void) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Call `enclosing_size_of_op` on `ptr`, which must not be empty.
|
||||
pub fn malloc_enclosing_size_of<T>(&self, ptr: *const T) -> usize {
|
||||
assert!(!MallocSizeOfOps::is_empty(ptr));
|
||||
let enclosing_size_of_op = self.enclosing_size_of_op.expect("missing enclosing_size_of_op");
|
||||
unsafe { enclosing_size_of_op(ptr as *const c_void) }
|
||||
}
|
||||
|
||||
/// Call `have_seen_ptr_op` on `ptr`.
|
||||
pub fn have_seen_ptr<T>(&mut self, ptr: *const T) -> bool {
|
||||
let have_seen_ptr_op = self.have_seen_ptr_op.as_mut().expect("missing have_seen_ptr_op");
|
||||
have_seen_ptr_op(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 direct descendant structures, but not the
|
||||
/// space taken up by the value itself. Anything pointed to by the
|
||||
/// immediate children 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;
|
||||
}
|
||||
|
||||
/// 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;
|
||||
}
|
||||
|
||||
impl<T> MallocShallowSizeOf for Box<T> {
|
||||
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
ops.malloc_size_of(&**self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf> MallocSizeOf for Box<T> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.shallow_size_of(ops) + (**self).size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: MallocSizeOf, B: MallocSizeOf> MallocSizeOf for (A, B) {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
self.0.size_of(ops) + self.1.size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf> MallocSizeOf for Option<T> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
if let Some(val) = self.as_ref() {
|
||||
val.size_of(ops)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> MallocShallowSizeOf for Vec<T> {
|
||||
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
ops.malloc_size_of(self.as_ptr())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf> MallocSizeOf for Vec<T> {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
let mut n = self.shallow_size_of(ops);
|
||||
for elem in self.iter() {
|
||||
n += elem.size_of(ops);
|
||||
}
|
||||
n
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Array> MallocShallowSizeOf for SmallVec<A> {
|
||||
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
if self.spilled() {
|
||||
ops.malloc_size_of(self.as_ptr())
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A> MallocSizeOf for SmallVec<A>
|
||||
where A: 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<T, S> MallocShallowSizeOf for HashSet<T, S>
|
||||
where T: Eq + Hash,
|
||||
S: BuildHasher
|
||||
{
|
||||
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
// 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| ops.malloc_enclosing_size_of(t))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, S> MallocSizeOf for HashSet<T, S>
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V, S> MallocShallowSizeOf for HashMap<K, V, S>
|
||||
where K: Eq + Hash,
|
||||
S: BuildHasher
|
||||
{
|
||||
fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
// 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 `HashMap`'s contents (keys, values, and
|
||||
// hashes) are all stored in a single contiguous heap allocation.
|
||||
self.values().next().map_or(0, |v| ops.malloc_enclosing_size_of(v))
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V, S> MallocSizeOf for HashMap<K, V, S>
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: we don't want MallocSizeOf to be defined for Rc and Arc. If negative
|
||||
// trait bounds are ever allowed, this code should be uncommented.
|
||||
// (We do have a compile-fail test for this:
|
||||
// rc_arc_must_not_derive_malloc_size_of.rs)
|
||||
//impl<T> !MallocSizeOf for Arc<T> { }
|
||||
//impl<T> !MallocShallowSizeOf for Arc<T> { }
|
||||
|
||||
impl<T: MallocSizeOf> MallocUnconditionalSizeOf for Arc<T> {
|
||||
fn unconditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
ops.malloc_size_of(self.heap_ptr()) + (**self).size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf> MallocConditionalSizeOf for Arc<T> {
|
||||
fn conditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
if ops.have_seen_ptr(self.heap_ptr()) {
|
||||
0
|
||||
} else {
|
||||
self.unconditional_size_of(ops)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// For use on types where size_of() returns 0.
|
||||
#[macro_export]
|
||||
macro_rules! 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
|
||||
}
|
||||
}
|
||||
)+
|
||||
);
|
||||
);
|
||||
|
||||
size_of_is_0!(char, str);
|
||||
size_of_is_0!(u8, u16, u32, u64, usize);
|
||||
size_of_is_0!(i8, i16, i32, i64, isize);
|
||||
size_of_is_0!(bool, f32, f64);
|
||||
|
||||
// XXX: once we upgrade smallbitvec to 1.0.4, use the new heap_ptr() method to
|
||||
// implement this properly
|
||||
size_of_is_0!(SmallBitVec);
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
[package]
|
||||
name = "malloc_size_of_derive"
|
||||
version = "0.0.1"
|
||||
authors = ["The Servo Project Developers"]
|
||||
license = "MIT/Apache-2.0"
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
quote = "0.3.15"
|
||||
syn = "0.11"
|
||||
synstructure = "0.5"
|
|
@ -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.
|
|
@ -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.
|
|
@ -0,0 +1,117 @@
|
|||
// Copyright 2016-2017 The Servo Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
//! A crate for deriving the MallocSizeOf trait.
|
||||
|
||||
#[cfg(not(test))] extern crate proc_macro;
|
||||
#[macro_use] extern crate quote;
|
||||
extern crate syn;
|
||||
extern crate synstructure;
|
||||
|
||||
#[cfg(not(test))]
|
||||
#[proc_macro_derive(MallocSizeOf, attributes(ignore_malloc_size_of))]
|
||||
pub fn expand_token_stream(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
expand_string(&input.to_string()).parse().unwrap()
|
||||
}
|
||||
|
||||
fn expand_string(input: &str) -> String {
|
||||
let mut type_ = syn::parse_macro_input(input).unwrap();
|
||||
|
||||
let style = synstructure::BindStyle::Ref.into();
|
||||
let match_body = synstructure::each_field(&mut type_, &style, |binding| {
|
||||
let ignore = binding.field.attrs.iter().any(|attr| match attr.value {
|
||||
syn::MetaItem::Word(ref ident) |
|
||||
syn::MetaItem::List(ref ident, _) if ident == "ignore_malloc_size_of" => {
|
||||
panic!("#[ignore_malloc_size_of] should have an explanation, \
|
||||
e.g. #[ignore_malloc_size_of = \"because reasons\"]");
|
||||
}
|
||||
syn::MetaItem::NameValue(ref ident, _) if ident == "ignore_malloc_size_of" => {
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
});
|
||||
if ignore {
|
||||
None
|
||||
} else if let syn::Ty::Array(..) = binding.field.ty {
|
||||
Some(quote! {
|
||||
for item in #binding.iter() {
|
||||
sum += ::malloc_size_of::MallocSizeOf::size_of(item, ops);
|
||||
}
|
||||
})
|
||||
} else {
|
||||
Some(quote! {
|
||||
sum += ::malloc_size_of::MallocSizeOf::size_of(#binding, ops);
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
let name = &type_.ident;
|
||||
let (impl_generics, ty_generics, where_clause) = type_.generics.split_for_impl();
|
||||
let mut where_clause = where_clause.clone();
|
||||
for param in &type_.generics.ty_params {
|
||||
where_clause.predicates.push(syn::WherePredicate::BoundPredicate(syn::WhereBoundPredicate {
|
||||
bound_lifetimes: Vec::new(),
|
||||
bounded_ty: syn::Ty::Path(None, param.ident.clone().into()),
|
||||
bounds: vec![syn::TyParamBound::Trait(
|
||||
syn::PolyTraitRef {
|
||||
bound_lifetimes: Vec::new(),
|
||||
trait_ref: syn::parse_path("::malloc_size_of::MallocSizeOf").unwrap(),
|
||||
},
|
||||
syn::TraitBoundModifier::None
|
||||
)],
|
||||
}))
|
||||
}
|
||||
|
||||
let tokens = quote! {
|
||||
impl #impl_generics ::malloc_size_of::MallocSizeOf for #name #ty_generics #where_clause {
|
||||
#[inline]
|
||||
#[allow(unused_variables, unused_mut, unreachable_code)]
|
||||
fn size_of(&self, ops: &mut ::malloc_size_of::MallocSizeOfOps) -> usize {
|
||||
let mut sum = 0;
|
||||
match *self {
|
||||
#match_body
|
||||
}
|
||||
sum
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
tokens.to_string()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_struct() {
|
||||
let mut source = "struct Foo<T> { bar: Bar, baz: T, #[ignore_malloc_size_of = \"\"] z: Arc<T> }";
|
||||
let mut expanded = expand_string(source);
|
||||
let mut no_space = expanded.replace(" ", "");
|
||||
macro_rules! match_count {
|
||||
($e: expr, $count: expr) => {
|
||||
assert_eq!(no_space.matches(&$e.replace(" ", "")).count(), $count,
|
||||
"counting occurences of {:?} in {:?} (whitespace-insensitive)",
|
||||
$e, expanded)
|
||||
}
|
||||
}
|
||||
match_count!("struct", 0);
|
||||
match_count!("ignore_malloc_size_of", 0);
|
||||
match_count!("impl<T> ::malloc_size_of::MallocSizeOf for Foo<T> where T: ::malloc_size_of::MallocSizeOf {", 1);
|
||||
match_count!("sum += ::malloc_size_of::MallocSizeOf::size_of(", 2);
|
||||
|
||||
source = "struct Bar([Baz; 3]);";
|
||||
expanded = expand_string(source);
|
||||
no_space = expanded.replace(" ", "");
|
||||
match_count!("for item in", 1);
|
||||
}
|
||||
|
||||
#[should_panic(expected = "should have an explanation")]
|
||||
#[test]
|
||||
fn test_no_reason() {
|
||||
expand_string("struct A { #[ignore_malloc_size_of] b: C }");
|
||||
}
|
||||
|
|
@ -28,6 +28,8 @@ matches = "0.1"
|
|||
cssparser = "0.20.2"
|
||||
log = "0.3"
|
||||
fnv = "1.0"
|
||||
malloc_size_of = { path = "../malloc_size_of" }
|
||||
malloc_size_of_derive = { path = "../malloc_size_of_derive" }
|
||||
phf = "0.7.18"
|
||||
precomputed-hash = "0.1"
|
||||
servo_arc = { path = "../servo_arc" }
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#[macro_use] extern crate log;
|
||||
#[macro_use] extern crate matches;
|
||||
extern crate fnv;
|
||||
extern crate malloc_size_of;
|
||||
#[macro_use] extern crate malloc_size_of_derive;
|
||||
extern crate phf;
|
||||
extern crate precomputed_hash;
|
||||
#[cfg(test)] #[macro_use] extern crate size_of_test;
|
||||
|
|
|
@ -218,7 +218,7 @@ impl<Impl: SelectorImpl> SelectorList<Impl> {
|
|||
/// off the upper bits) at the expense of making the fourth somewhat more
|
||||
/// complicated to assemble, because we often bail out before checking all the
|
||||
/// hashes.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq)]
|
||||
pub struct AncestorHashes {
|
||||
pub packed_hashes: [u32; 3],
|
||||
}
|
||||
|
|
|
@ -16,7 +16,8 @@ path = "lib.rs"
|
|||
doctest = false
|
||||
|
||||
[features]
|
||||
gecko = ["nsstring_vendor", "num_cpus", "style_traits/gecko", "fallible/known_system_malloc"]
|
||||
gecko = ["malloc_size_of", "malloc_size_of_derive", "nsstring_vendor", "num_cpus",
|
||||
"style_traits/gecko", "fallible/known_system_malloc"]
|
||||
use_bindgen = ["bindgen", "regex", "toml"]
|
||||
servo = ["serde", "heapsize", "heapsize_derive",
|
||||
"style_traits/servo", "servo_atoms", "servo_config", "html5ever",
|
||||
|
@ -49,6 +50,8 @@ itoa = "0.3"
|
|||
html5ever = {version = "0.19", optional = true}
|
||||
lazy_static = "0.2"
|
||||
log = "0.3"
|
||||
malloc_size_of = { path = "../malloc_size_of", optional=true }
|
||||
malloc_size_of_derive = { path = "../malloc_size_of_derive", optional=true }
|
||||
matches = "0.1"
|
||||
nsstring_vendor = {path = "gecko_bindings/nsstring_vendor", optional = true}
|
||||
num_cpus = {version = "1.1.0", optional = true}
|
||||
|
|
|
@ -8,6 +8,8 @@ use context::{SharedStyleContext, StackLimitChecker};
|
|||
use dom::TElement;
|
||||
use invalidation::element::invalidator::InvalidationResult;
|
||||
use invalidation::element::restyle_hints::RestyleHint;
|
||||
#[cfg(feature = "gecko")]
|
||||
use malloc_size_of::MallocSizeOfOps;
|
||||
use properties::ComputedValues;
|
||||
use properties::longhands::display::computed_value as display;
|
||||
use rule_tree::StrongRuleNode;
|
||||
|
@ -16,8 +18,6 @@ use servo_arc::Arc;
|
|||
use shared_lock::StylesheetGuards;
|
||||
use std::fmt;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
#[cfg(feature = "gecko")]
|
||||
use stylesheets::SizeOfState;
|
||||
|
||||
bitflags! {
|
||||
flags RestyleFlags: u8 {
|
||||
|
@ -272,7 +272,7 @@ impl ElementStyles {
|
|||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
fn malloc_size_of_children_excluding_cvs(&self, _state: &mut SizeOfState) -> usize {
|
||||
fn size_of_excluding_cvs(&self, _ops: &mut MallocSizeOfOps) -> usize {
|
||||
// As the method name suggests, we don't measures the ComputedValues
|
||||
// here, because they are measured on the C++ side.
|
||||
|
||||
|
@ -453,8 +453,8 @@ impl ElementData {
|
|||
|
||||
/// Measures memory usage.
|
||||
#[cfg(feature = "gecko")]
|
||||
pub fn malloc_size_of_children_excluding_cvs(&self, state: &mut SizeOfState) -> usize {
|
||||
let n = self.styles.malloc_size_of_children_excluding_cvs(state);
|
||||
pub fn size_of_excluding_cvs(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
let n = self.styles.size_of_excluding_cvs(ops);
|
||||
|
||||
// We may measure more fields in the future if DMD says it's worth it.
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ bitflags! {
|
|||
///
|
||||
/// TODO(emilio): We really really want to use the NS_EVENT_STATE bindings
|
||||
/// for this.
|
||||
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub flags ElementState: u64 {
|
||||
/// The mouse is down on this element.
|
||||
|
|
|
@ -12,12 +12,12 @@ use gecko_bindings::structs::{StyleSheetInfo, ServoStyleSheetInner};
|
|||
use gecko_bindings::structs::nsIDocument;
|
||||
use gecko_bindings::sugar::ownership::{HasArcFFI, HasBoxFFI, HasFFI, HasSimpleFFI};
|
||||
use invalidation::media_queries::{MediaListKey, ToMediaListKey};
|
||||
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
|
||||
use media_queries::{Device, MediaList};
|
||||
use properties::ComputedValues;
|
||||
use servo_arc::Arc;
|
||||
use shared_lock::{Locked, StylesheetGuards, SharedRwLockReadGuard};
|
||||
use stylesheets::{MallocEnclosingSizeOfFn, MallocSizeOfFn, PerOrigin, StylesheetContents};
|
||||
use stylesheets::StylesheetInDocument;
|
||||
use stylesheets::{PerOrigin, StylesheetContents, StylesheetInDocument};
|
||||
use stylist::{ExtraStyleData, Stylist};
|
||||
|
||||
/// Little wrapper to a Gecko style sheet.
|
||||
|
@ -186,19 +186,10 @@ impl PerDocumentStyleDataImpl {
|
|||
self.visited_links_enabled() && !self.is_private_browsing_enabled()
|
||||
}
|
||||
|
||||
/// Measures heap usage.
|
||||
pub fn malloc_add_size_of_children(&self, malloc_size_of: MallocSizeOfFn,
|
||||
malloc_enclosing_size_of: MallocEnclosingSizeOfFn,
|
||||
sizes: &mut ServoStyleSetSizes) {
|
||||
self.stylist.malloc_add_size_of_children(malloc_size_of, malloc_enclosing_size_of, sizes);
|
||||
|
||||
let data = &self.extra_style_data;
|
||||
sizes.mStylistOther +=
|
||||
data.user_agent.malloc_size_of_children(malloc_size_of, malloc_enclosing_size_of);
|
||||
sizes.mStylistOther +=
|
||||
data.user.malloc_size_of_children(malloc_size_of, malloc_enclosing_size_of);
|
||||
sizes.mStylistOther +=
|
||||
data.author.malloc_size_of_children(malloc_size_of, malloc_enclosing_size_of);
|
||||
/// Measure heap usage.
|
||||
pub fn add_size_of_children(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
|
||||
self.stylist.add_size_of_children(ops, sizes);
|
||||
sizes.mStylistOther += self.extra_style_data.size_of(ops);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -388,3 +388,5 @@ impl From<*mut nsIAtom> for Atom {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_of_is_0!(Atom);
|
||||
|
|
|
@ -16,8 +16,6 @@ use selectors::parser::{Combinator, Component};
|
|||
use selectors::parser::{Selector, SelectorIter, SelectorMethods};
|
||||
use selectors::visitor::SelectorVisitor;
|
||||
use smallvec::SmallVec;
|
||||
#[cfg(feature = "gecko")]
|
||||
use stylesheets::{MallocEnclosingSizeOfFn, MallocSizeOfFn, MallocSizeOfHash, MallocSizeOfVec};
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
/// Gets the element state relevant to the given `:dir` pseudo-class selector.
|
||||
|
@ -58,11 +56,15 @@ pub fn dir_selector_to_state(s: &[u16]) -> ElementState {
|
|||
/// rules and determine the maximum effect that a given state or attribute
|
||||
/// change may have on the style of elements in the document.
|
||||
#[derive(Clone, Debug)]
|
||||
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct Dependency {
|
||||
/// The dependency selector.
|
||||
#[cfg_attr(feature = "gecko",
|
||||
ignore_malloc_size_of = "CssRules have primary refs, we measure there")]
|
||||
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
|
||||
pub selector: Selector<SelectorImpl>,
|
||||
|
||||
/// The offset into the selector that we should match on.
|
||||
pub selector_offset: usize,
|
||||
}
|
||||
|
@ -114,6 +116,7 @@ impl SelectorMapEntry for Dependency {
|
|||
/// The same, but for state selectors, which can track more exactly what state
|
||||
/// do they track.
|
||||
#[derive(Clone, Debug)]
|
||||
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct StateDependency {
|
||||
/// The other dependency fields.
|
||||
|
@ -137,6 +140,7 @@ impl SelectorMapEntry for StateDependency {
|
|||
/// selectors the better, so this looks up by id, class, or looks at the list of
|
||||
/// state/other attribute affecting selectors.
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct InvalidationMap {
|
||||
/// A map from a given class name to all the selectors with that class
|
||||
|
@ -295,34 +299,6 @@ impl InvalidationMap {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Measures heap usage.
|
||||
#[cfg(feature = "gecko")]
|
||||
pub fn malloc_size_of_children(&self, malloc_size_of: MallocSizeOfFn,
|
||||
malloc_enclosing_size_of: MallocEnclosingSizeOfFn)
|
||||
-> usize {
|
||||
// Currently we measure the HashMap storage, but not things pointed to
|
||||
// by keys and values.
|
||||
let mut n = 0;
|
||||
|
||||
n += self.class_to_selector.malloc_shallow_size_of_hash(malloc_enclosing_size_of);
|
||||
for (_, val) in self.class_to_selector.iter() {
|
||||
n += val.malloc_shallow_size_of_vec(malloc_size_of);
|
||||
}
|
||||
|
||||
n += self.id_to_selector.malloc_shallow_size_of_hash(malloc_enclosing_size_of);
|
||||
for (_, val) in self.id_to_selector.iter() {
|
||||
n += val.malloc_shallow_size_of_vec(malloc_size_of);
|
||||
}
|
||||
|
||||
n += self.state_affecting_selectors.malloc_size_of_children(malloc_size_of,
|
||||
malloc_enclosing_size_of);
|
||||
|
||||
n += self.other_attribute_affecting_selectors.malloc_size_of_children(
|
||||
malloc_size_of, malloc_enclosing_size_of);
|
||||
|
||||
n
|
||||
}
|
||||
}
|
||||
|
||||
/// A struct that collects invalidations for a given compound selector.
|
||||
|
|
|
@ -8,7 +8,7 @@ use context::QuirksMode;
|
|||
use fnv::FnvHashSet;
|
||||
use media_queries::Device;
|
||||
use shared_lock::SharedRwLockReadGuard;
|
||||
use stylesheets::{DocumentRule, ImportRule, MallocEnclosingSizeOfFn, MallocSizeOfHash, MediaRule};
|
||||
use stylesheets::{DocumentRule, ImportRule, MediaRule};
|
||||
use stylesheets::{NestedRuleIterationCondition, Stylesheet, SupportsRule};
|
||||
|
||||
/// A key for a given media query result.
|
||||
|
@ -24,6 +24,7 @@ use stylesheets::{NestedRuleIterationCondition, Stylesheet, SupportsRule};
|
|||
/// If this changes, though, we may need to remove the item from the cache if
|
||||
/// present before it goes away.
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct MediaListKey(usize);
|
||||
|
||||
|
@ -53,6 +54,7 @@ impl ToMediaListKey for MediaRule {}
|
|||
/// A struct that holds the result of a media query evaluation pass for the
|
||||
/// media queries that evaluated successfully.
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct EffectiveMediaQueryResults {
|
||||
/// The set of media lists that matched last time.
|
||||
|
@ -88,12 +90,6 @@ impl EffectiveMediaQueryResults {
|
|||
// because of stylesheet reusing... shrug.
|
||||
self.set.insert(item.to_media_list_key());
|
||||
}
|
||||
|
||||
/// Measure heap usage.
|
||||
pub fn malloc_size_of_children(&self, malloc_enclosing_size_of: MallocEnclosingSizeOfFn)
|
||||
-> usize {
|
||||
self.set.malloc_shallow_size_of_hash(malloc_enclosing_size_of)
|
||||
}
|
||||
}
|
||||
|
||||
/// A filter that filters over effective rules, but allowing all potentially
|
||||
|
|
|
@ -59,6 +59,8 @@ extern crate itoa;
|
|||
extern crate lazy_static;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
#[cfg(feature = "gecko")] #[macro_use] extern crate malloc_size_of;
|
||||
#[cfg(feature = "gecko")] #[macro_use] extern crate malloc_size_of_derive;
|
||||
#[allow(unused_extern_crates)]
|
||||
#[macro_use]
|
||||
extern crate matches;
|
||||
|
|
|
@ -21,7 +21,6 @@ use std::iter::{DoubleEndedIterator, Zip};
|
|||
use std::slice::Iter;
|
||||
use style_traits::{PARSING_MODE_DEFAULT, ToCss, ParseError, ParsingMode, StyleParseError};
|
||||
use stylesheets::{CssRuleType, Origin, UrlExtraData};
|
||||
use stylesheets::{MallocSizeOf, MallocSizeOfFn};
|
||||
use super::*;
|
||||
use values::computed::Context;
|
||||
#[cfg(feature = "gecko")] use properties::animated_properties::AnimationValueMap;
|
||||
|
@ -43,6 +42,7 @@ impl AnimationRules {
|
|||
/// A declaration [importance][importance].
|
||||
///
|
||||
/// [importance]: https://drafts.csswg.org/css-cascade/#importance
|
||||
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||
pub enum Importance {
|
||||
|
@ -53,12 +53,6 @@ pub enum Importance {
|
|||
Important,
|
||||
}
|
||||
|
||||
impl MallocSizeOf for Importance {
|
||||
fn malloc_size_of_children(&self, _malloc_size_of: MallocSizeOfFn) -> usize {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
impl Importance {
|
||||
/// Return whether this is an important declaration.
|
||||
pub fn important(self) -> bool {
|
||||
|
@ -70,6 +64,7 @@ impl Importance {
|
|||
}
|
||||
|
||||
/// Overridden declarations are skipped.
|
||||
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
|
||||
#[derive(Clone)]
|
||||
pub struct PropertyDeclarationBlock {
|
||||
/// The group of declarations, along with their importance.
|
||||
|
@ -83,12 +78,6 @@ pub struct PropertyDeclarationBlock {
|
|||
longhands: LonghandIdSet,
|
||||
}
|
||||
|
||||
impl MallocSizeOf for PropertyDeclarationBlock {
|
||||
fn malloc_size_of_children(&self, malloc_size_of: MallocSizeOfFn) -> usize {
|
||||
self.declarations.malloc_size_of_children(malloc_size_of)
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterator over `(PropertyDeclaration, Importance)` pairs.
|
||||
pub struct DeclarationImportanceIterator<'a> {
|
||||
iter: Zip<Iter<'a, PropertyDeclaration>, smallbitvec::Iter<'a>>,
|
||||
|
|
|
@ -74,6 +74,7 @@ pub trait RepeatableListAnimatable: Animate {}
|
|||
/// not animatable from CSS animations or Web Animations. CSS transitions also does not allow
|
||||
/// animating 'display', but for CSS transitions we have the separate TransitionProperty type.
|
||||
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub enum AnimatableLonghand {
|
||||
% for prop in data.longhands:
|
||||
|
|
|
@ -29,6 +29,7 @@ use font_metrics::FontMetricsProvider;
|
|||
#[cfg(feature = "gecko")] use gecko_bindings::structs::{self, nsCSSPropertyID};
|
||||
#[cfg(feature = "servo")] use logical_geometry::{LogicalMargin, PhysicalSide};
|
||||
use logical_geometry::WritingMode;
|
||||
#[cfg(feature = "gecko")] use malloc_size_of::{MallocShallowSizeOf, MallocSizeOf, MallocSizeOfOps};
|
||||
use media_queries::Device;
|
||||
use parser::ParserContext;
|
||||
use properties::animated_properties::AnimatableLonghand;
|
||||
|
@ -39,8 +40,7 @@ use selectors::parser::SelectorParseError;
|
|||
use shared_lock::StylesheetGuards;
|
||||
use style_traits::{PARSING_MODE_DEFAULT, ToCss, ParseError};
|
||||
use style_traits::{PropertyDeclarationParseError, StyleParseError, ValueParseError};
|
||||
use stylesheets::{CssRuleType, MallocSizeOf, MallocSizeOfBox, MallocSizeOfFn, MallocSizeOfVec};
|
||||
use stylesheets::{Origin, UrlExtraData};
|
||||
use stylesheets::{CssRuleType, Origin, UrlExtraData};
|
||||
#[cfg(feature = "servo")] use values::Either;
|
||||
use values::generics::text::LineHeight;
|
||||
use values::computed;
|
||||
|
@ -276,6 +276,7 @@ static ${name}: LonghandIdSet = LonghandIdSet {
|
|||
</%def>
|
||||
|
||||
/// A set of longhand properties
|
||||
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
|
||||
#[derive(Clone, PartialEq)]
|
||||
pub struct LonghandIdSet {
|
||||
storage: [u32; (${len(data.longhands)} - 1 + 32) / 32]
|
||||
|
@ -1313,19 +1314,20 @@ impl ToCss for PropertyDeclaration {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
impl MallocSizeOf for PropertyDeclaration {
|
||||
fn malloc_size_of_children(&self, malloc_size_of: MallocSizeOfFn) -> usize {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
match *self {
|
||||
% for property in data.longhands:
|
||||
% if property.boxed and property.is_vector:
|
||||
<% raise Exception("this should not happen! not smart to box a vector here") %>
|
||||
% elif property.boxed:
|
||||
PropertyDeclaration::${property.camel_case}(ref sv_box) => {
|
||||
sv_box.malloc_shallow_size_of_box(malloc_size_of)
|
||||
<Box<_> as MallocShallowSizeOf>::shallow_size_of(sv_box, ops)
|
||||
}
|
||||
% elif property.is_vector:
|
||||
PropertyDeclaration::${property.camel_case}(ref sv_vec) => {
|
||||
sv_vec.0.malloc_shallow_size_of_vec(malloc_size_of)
|
||||
sv_vec.0.shallow_size_of(ops)
|
||||
}
|
||||
% endif
|
||||
% endfor
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
use applicable_declarations::ApplicableDeclarationList;
|
||||
#[cfg(feature = "servo")]
|
||||
use heapsize::HeapSizeOf;
|
||||
#[cfg(feature = "gecko")]
|
||||
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
|
||||
use properties::{Importance, LonghandIdSet, PropertyDeclarationBlock};
|
||||
use servo_arc::{Arc, ArcBorrow, NonZeroPtrMut};
|
||||
use shared_lock::{Locked, StylesheetGuards, SharedRwLockReadGuard};
|
||||
|
@ -17,7 +19,7 @@ use std::io::{self, Write};
|
|||
use std::mem;
|
||||
use std::ptr;
|
||||
use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
|
||||
use stylesheets::{MallocSizeOf, MallocSizeOfFn, StyleRule};
|
||||
use stylesheets::StyleRule;
|
||||
use thread_state;
|
||||
|
||||
/// The rule tree, the structure servo uses to preserve the results of selector
|
||||
|
@ -62,9 +64,12 @@ impl Drop for RuleTree {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
impl MallocSizeOf for RuleTree {
|
||||
fn malloc_size_of_children(&self, malloc_size_of: MallocSizeOfFn) -> usize {
|
||||
self.root.get().malloc_size_of_including_self(malloc_size_of)
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
let mut n = ops.malloc_size_of(self.root.ptr());
|
||||
n += self.root.get().size_of(ops);
|
||||
n
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -794,11 +799,15 @@ impl RuleNode {
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn malloc_size_of_including_self(&self, malloc_size_of: MallocSizeOfFn) -> usize {
|
||||
let mut n = unsafe { (malloc_size_of.0)(self as *const _ as *const _) };
|
||||
#[cfg(feature = "gecko")]
|
||||
impl MallocSizeOf for RuleNode {
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
let mut n = 0;
|
||||
for child in self.iter_children() {
|
||||
n += unsafe { (*child.ptr()).malloc_size_of_including_self(malloc_size_of) };
|
||||
n += ops.malloc_size_of(child.ptr());
|
||||
n += unsafe { (*child.ptr()).size_of(ops) };
|
||||
}
|
||||
n
|
||||
}
|
||||
|
|
|
@ -21,8 +21,6 @@ use selectors::matching::{matches_selector, MatchingContext, ElementSelectorFlag
|
|||
use selectors::parser::{Component, Combinator, SelectorIter};
|
||||
use smallvec::{SmallVec, VecLike};
|
||||
use std::hash::{BuildHasherDefault, Hash, Hasher};
|
||||
#[cfg(feature = "gecko")]
|
||||
use stylesheets::{MallocEnclosingSizeOfFn, MallocSizeOfFn, MallocSizeOfHash, MallocSizeOfVec};
|
||||
use stylist::Rule;
|
||||
|
||||
/// A hasher implementation that doesn't hash anything, because it expects its
|
||||
|
@ -96,6 +94,7 @@ pub trait SelectorMapEntry : Sized + Clone {
|
|||
///
|
||||
/// TODO: Tune the initial capacity of the HashMap
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct SelectorMap<T: 'static> {
|
||||
/// A hash from an ID to rules which contain that ID selector.
|
||||
|
@ -148,37 +147,6 @@ impl<T: 'static> SelectorMap<T> {
|
|||
pub fn len(&self) -> usize {
|
||||
self.count
|
||||
}
|
||||
|
||||
/// Measures heap usage.
|
||||
#[cfg(feature = "gecko")]
|
||||
pub fn malloc_size_of_children(&self, malloc_size_of: MallocSizeOfFn,
|
||||
malloc_enclosing_size_of: MallocEnclosingSizeOfFn)
|
||||
-> usize {
|
||||
// Currently we measure the storage used by the HashMaps, and any
|
||||
// heap-allocated SmallVec values, but not things pointed to by the T
|
||||
// elements within the SmallVec values.
|
||||
|
||||
let mut n = 0;
|
||||
|
||||
n += self.id_hash.malloc_shallow_size_of_hash(malloc_enclosing_size_of);
|
||||
for (_, val) in self.id_hash.iter() {
|
||||
n += val.malloc_shallow_size_of_vec(malloc_size_of);
|
||||
}
|
||||
|
||||
n += self.class_hash.malloc_shallow_size_of_hash(malloc_enclosing_size_of);
|
||||
for (_, val) in self.class_hash.iter() {
|
||||
n += val.malloc_shallow_size_of_vec(malloc_size_of);
|
||||
}
|
||||
|
||||
n += self.local_name_hash.malloc_shallow_size_of_hash(malloc_enclosing_size_of);
|
||||
for (_, val) in self.local_name_hash.iter() {
|
||||
n += val.malloc_shallow_size_of_vec(malloc_size_of);
|
||||
}
|
||||
|
||||
n += self.other.malloc_shallow_size_of_vec(malloc_size_of);
|
||||
|
||||
n
|
||||
}
|
||||
}
|
||||
|
||||
impl SelectorMap<Rule> {
|
||||
|
@ -493,6 +461,7 @@ fn find_bucket<'a>(mut iter: SelectorIter<'a, SelectorImpl>) -> Bucket<'a> {
|
|||
|
||||
/// Wrapper for PrecomputedHashMap that does ASCII-case-insensitive lookup in quirks mode.
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct MaybeCaseInsensitiveHashMap<K: PrecomputedHash + Hash + Eq, V: 'static>(PrecomputedHashMap<K, V>);
|
||||
|
||||
|
@ -545,13 +514,3 @@ impl<V: 'static> MaybeCaseInsensitiveHashMap<Atom, V> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
impl<K, V> MallocSizeOfHash for MaybeCaseInsensitiveHashMap<K, V>
|
||||
where K: PrecomputedHash + Eq + Hash
|
||||
{
|
||||
fn malloc_shallow_size_of_hash(&self, malloc_enclosing_size_of: MallocEnclosingSizeOfFn)
|
||||
-> usize {
|
||||
self.0.malloc_shallow_size_of_hash(malloc_enclosing_size_of)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,13 +7,15 @@
|
|||
//! We implement the prefixed `@-moz-document`.
|
||||
|
||||
use cssparser::{Parser, Token, SourceLocation, BasicParseError};
|
||||
#[cfg(feature = "gecko")]
|
||||
use malloc_size_of::MallocSizeOfOps;
|
||||
use media_queries::Device;
|
||||
use parser::{Parse, ParserContext};
|
||||
use servo_arc::Arc;
|
||||
use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
|
||||
use std::fmt;
|
||||
use style_traits::{ToCss, ParseError, StyleParseError};
|
||||
use stylesheets::{CssRules, MallocSizeOfFn, MallocSizeOfWithGuard};
|
||||
use stylesheets::CssRules;
|
||||
use values::specified::url::SpecifiedUrl;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -29,10 +31,10 @@ pub struct DocumentRule {
|
|||
|
||||
impl DocumentRule {
|
||||
/// Measure heap usage.
|
||||
pub fn malloc_size_of_children(&self, guard: &SharedRwLockReadGuard,
|
||||
malloc_size_of: MallocSizeOfFn) -> usize {
|
||||
#[cfg(feature = "gecko")]
|
||||
pub fn size_of(&self, guard: &SharedRwLockReadGuard, ops: &mut MallocSizeOfOps) -> usize {
|
||||
// Measurement of other fields may be added later.
|
||||
self.rules.read_with(guard).malloc_size_of_children(guard, malloc_size_of)
|
||||
self.rules.read_with(guard).size_of(guard, ops)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ use shared_lock::{DeepCloneParams, DeepCloneWithLock, SharedRwLock, SharedRwLock
|
|||
use std::fmt;
|
||||
use style_traits::{PARSING_MODE_DEFAULT, ToCss, ParseError, StyleParseError};
|
||||
use style_traits::PropertyDeclarationParseError;
|
||||
use stylesheets::{CssRuleType, MallocSizeOfFn, MallocSizeOfVec, StylesheetContents};
|
||||
use stylesheets::{CssRuleType, StylesheetContents};
|
||||
use stylesheets::rule_parser::{VendorPrefix, get_location_with_offset};
|
||||
use values::{KeyframesName, serialize_percentage};
|
||||
|
||||
|
@ -100,6 +100,7 @@ impl DeepCloneWithLock for KeyframesRule {
|
|||
/// A number from 0 to 1, indicating the percentage of the animation when this
|
||||
/// keyframe should run.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
|
||||
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct KeyframePercentage(pub f32);
|
||||
|
||||
|
@ -263,11 +264,14 @@ impl DeepCloneWithLock for Keyframe {
|
|||
///
|
||||
/// TODO: Find a better name for this?
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub enum KeyframesStepValue {
|
||||
/// A step formed by a declaration block specified by the CSS.
|
||||
Declarations {
|
||||
/// The declaration block per se.
|
||||
#[cfg_attr(feature = "gecko",
|
||||
ignore_malloc_size_of = "XXX: Primary ref, measure if DMD says it's worthwhile")]
|
||||
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
|
||||
block: Arc<Locked<PropertyDeclarationBlock>>
|
||||
},
|
||||
|
@ -278,6 +282,7 @@ pub enum KeyframesStepValue {
|
|||
|
||||
/// A single step from a keyframe animation.
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct KeyframesStep {
|
||||
/// The percentage of the animation duration when this step starts.
|
||||
|
@ -349,6 +354,7 @@ impl KeyframesStep {
|
|||
///
|
||||
/// It only takes into account animable properties.
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct KeyframesAnimation {
|
||||
/// The difference steps of the animation.
|
||||
|
@ -442,14 +448,6 @@ impl KeyframesAnimation {
|
|||
|
||||
result
|
||||
}
|
||||
|
||||
/// Measure heap usage.
|
||||
pub fn malloc_size_of_children(&self, malloc_size_of: MallocSizeOfFn) -> usize {
|
||||
let mut n = 0;
|
||||
n += self.steps.malloc_shallow_size_of_vec(malloc_size_of);
|
||||
n += self.properties_changed.malloc_shallow_size_of_vec(malloc_size_of);
|
||||
n
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses a keyframes list, like:
|
||||
|
|
|
@ -7,12 +7,14 @@
|
|||
//! [media]: https://drafts.csswg.org/css-conditional/#at-ruledef-media
|
||||
|
||||
use cssparser::SourceLocation;
|
||||
#[cfg(feature = "gecko")]
|
||||
use malloc_size_of::MallocSizeOfOps;
|
||||
use media_queries::MediaList;
|
||||
use servo_arc::Arc;
|
||||
use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use stylesheets::{CssRules, MallocSizeOfFn, MallocSizeOfWithGuard};
|
||||
use stylesheets::CssRules;
|
||||
|
||||
/// An [`@media`][media] urle.
|
||||
///
|
||||
|
@ -29,10 +31,10 @@ pub struct MediaRule {
|
|||
|
||||
impl MediaRule {
|
||||
/// Measure heap usage.
|
||||
pub fn malloc_size_of_children(&self, guard: &SharedRwLockReadGuard,
|
||||
malloc_size_of: MallocSizeOfFn) -> usize {
|
||||
#[cfg(feature = "gecko")]
|
||||
pub fn size_of(&self, guard: &SharedRwLockReadGuard, ops: &mut MallocSizeOfOps) -> usize {
|
||||
// Measurement of other fields may be added later.
|
||||
self.rules.read_with(guard).malloc_size_of_children(guard, malloc_size_of)
|
||||
self.rules.read_with(guard).size_of(guard, ops)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,215 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
//! Memory reporting for the style system when running inside of Gecko.
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
use gecko_bindings::bindings::Gecko_HaveSeenPtr;
|
||||
#[cfg(feature = "gecko")]
|
||||
use gecko_bindings::structs::SeenPtrs;
|
||||
#[cfg(feature = "gecko")]
|
||||
use hash::HashMap;
|
||||
#[cfg(feature = "gecko")]
|
||||
use servo_arc::Arc;
|
||||
use shared_lock::SharedRwLockReadGuard;
|
||||
use smallvec::{Array, SmallVec};
|
||||
use std::collections::HashSet;
|
||||
use std::hash::{BuildHasher, Hash};
|
||||
use std::os::raw::c_void;
|
||||
|
||||
/// Like gecko_bindings::structs::MallocSizeOf, but without the Option<>
|
||||
/// wrapper.
|
||||
///
|
||||
/// Note that functions of this type should be called via do_malloc_size_of(),
|
||||
/// rather than directly.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct MallocSizeOfFn(pub unsafe extern "C" fn(ptr: *const c_void) -> usize);
|
||||
|
||||
/// Like MallocSizeOfFn, but can take an interior pointer.
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct MallocEnclosingSizeOfFn(pub unsafe extern "C" fn(ptr: *const c_void) -> usize);
|
||||
|
||||
/// Servo-side counterpart to mozilla::SizeOfState. The only difference is that
|
||||
/// this struct doesn't contain the SeenPtrs table, just a pointer to it.
|
||||
#[cfg(feature = "gecko")]
|
||||
pub struct SizeOfState {
|
||||
/// Function that measures the size of heap blocks.
|
||||
pub malloc_size_of: MallocSizeOfFn,
|
||||
/// Table recording heap blocks that have already been measured.
|
||||
pub seen_ptrs: *mut SeenPtrs,
|
||||
}
|
||||
|
||||
/// Check if an allocation is empty.
|
||||
pub unsafe fn is_empty<T>(ptr: *const T) -> bool {
|
||||
return ptr as usize <= ::std::mem::align_of::<T>();
|
||||
}
|
||||
|
||||
/// Call malloc_size_of on ptr, first checking that the allocation isn't empty.
|
||||
pub unsafe fn do_malloc_size_of<T>(malloc_size_of: MallocSizeOfFn, ptr: *const T) -> usize {
|
||||
if is_empty(ptr) {
|
||||
0
|
||||
} else {
|
||||
(malloc_size_of.0)(ptr as *const c_void)
|
||||
}
|
||||
}
|
||||
|
||||
/// Call malloc_enclosing_size_of on ptr, which must not be empty.
|
||||
pub unsafe fn do_malloc_enclosing_size_of<T>(
|
||||
malloc_enclosing_size_of: MallocEnclosingSizeOfFn, ptr: *const T) -> usize
|
||||
{
|
||||
assert!(!is_empty(ptr));
|
||||
(malloc_enclosing_size_of.0)(ptr as *const c_void)
|
||||
}
|
||||
|
||||
/// Trait for measuring the size of heap data structures.
|
||||
pub trait MallocSizeOf {
|
||||
/// Measure the size of any heap-allocated structures that hang off this
|
||||
/// value, but not the space taken up by the value itself.
|
||||
fn malloc_size_of_children(&self, malloc_size_of: MallocSizeOfFn) -> usize;
|
||||
}
|
||||
|
||||
/// Like MallocSizeOf, but takes a SizeOfState which allows it to measure
|
||||
/// graph-like structures such as those containing Arcs.
|
||||
#[cfg(feature = "gecko")]
|
||||
pub trait MallocSizeOfWithRepeats {
|
||||
/// Measure the size of any heap-allocated structures that hang off this
|
||||
/// value, but not the space taken up by the value itself.
|
||||
fn malloc_size_of_children(&self, state: &mut SizeOfState) -> usize;
|
||||
}
|
||||
|
||||
/// Like MallocSizeOf, but operates with the global SharedRwLockReadGuard
|
||||
/// locked.
|
||||
pub trait MallocSizeOfWithGuard {
|
||||
/// Like MallocSizeOf::malloc_size_of_children, but with a |guard| argument.
|
||||
fn malloc_size_of_children(
|
||||
&self,
|
||||
guard: &SharedRwLockReadGuard,
|
||||
malloc_size_of: MallocSizeOfFn
|
||||
) -> usize;
|
||||
}
|
||||
|
||||
impl<A: MallocSizeOf, B: MallocSizeOf> MallocSizeOf for (A, B) {
|
||||
fn malloc_size_of_children(&self, malloc_size_of: MallocSizeOfFn) -> usize {
|
||||
self.0.malloc_size_of_children(malloc_size_of) +
|
||||
self.1.malloc_size_of_children(malloc_size_of)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOf> MallocSizeOf for Vec<T> {
|
||||
fn malloc_size_of_children(&self, malloc_size_of: MallocSizeOfFn) -> usize {
|
||||
self.iter().fold(
|
||||
unsafe { do_malloc_size_of(malloc_size_of, self.as_ptr()) },
|
||||
|n, elem| n + elem.malloc_size_of_children(malloc_size_of))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
impl<T: MallocSizeOfWithRepeats> MallocSizeOfWithRepeats for Arc<T> {
|
||||
fn malloc_size_of_children(&self, state: &mut SizeOfState) -> usize {
|
||||
let mut n = 0;
|
||||
let heap_ptr = self.heap_ptr();
|
||||
if unsafe { !is_empty(heap_ptr) && !Gecko_HaveSeenPtr(state.seen_ptrs, heap_ptr) } {
|
||||
n += unsafe { (state.malloc_size_of.0)(heap_ptr) };
|
||||
n += (**self).malloc_size_of_children(state);
|
||||
}
|
||||
n
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: MallocSizeOfWithGuard> MallocSizeOfWithGuard for Vec<T> {
|
||||
fn malloc_size_of_children(
|
||||
&self,
|
||||
guard: &SharedRwLockReadGuard,
|
||||
malloc_size_of: MallocSizeOfFn,
|
||||
) -> usize {
|
||||
self.iter().fold(
|
||||
unsafe { do_malloc_size_of(malloc_size_of, self.as_ptr()) },
|
||||
|n, elem| n + elem.malloc_size_of_children(guard, malloc_size_of))
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for measuring the heap usage of a Box<T>.
|
||||
pub trait MallocSizeOfBox {
|
||||
/// Measure shallowly the size of the memory used by the T -- anything
|
||||
/// pointed to by the T must be measured separately.
|
||||
fn malloc_shallow_size_of_box(&self, malloc_size_of: MallocSizeOfFn) -> usize;
|
||||
}
|
||||
|
||||
impl<T> MallocSizeOfBox for Box<T> {
|
||||
fn malloc_shallow_size_of_box(&self, malloc_size_of: MallocSizeOfFn) -> usize {
|
||||
unsafe { do_malloc_size_of(malloc_size_of, &**self as *const T) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for measuring the heap usage of a vector.
|
||||
pub trait MallocSizeOfVec {
|
||||
/// Measure shallowly the size of the memory used by the Vec's elements --
|
||||
/// anything pointed to by the elements must be measured separately, using
|
||||
/// iteration.
|
||||
fn malloc_shallow_size_of_vec(&self, malloc_size_of: MallocSizeOfFn) -> usize;
|
||||
}
|
||||
|
||||
impl<T> MallocSizeOfVec for Vec<T> {
|
||||
fn malloc_shallow_size_of_vec(&self, malloc_size_of: MallocSizeOfFn) -> usize {
|
||||
unsafe { do_malloc_size_of(malloc_size_of, self.as_ptr()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Array> MallocSizeOfVec for SmallVec<A> {
|
||||
fn malloc_shallow_size_of_vec(&self, malloc_size_of: MallocSizeOfFn) -> usize {
|
||||
if self.spilled() {
|
||||
unsafe { do_malloc_size_of(malloc_size_of, self.as_ptr()) }
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for measuring the heap usage of a hash table.
|
||||
pub trait MallocSizeOfHash {
|
||||
/// Measure shallowly the size of the memory used within a hash table --
|
||||
/// anything pointer to by the keys and values must be measured separately,
|
||||
/// using iteration.
|
||||
fn malloc_shallow_size_of_hash(&self, malloc_enclosing_size_of: MallocEnclosingSizeOfFn)
|
||||
-> usize;
|
||||
}
|
||||
|
||||
impl<T, S> MallocSizeOfHash for HashSet<T, S>
|
||||
where T: Eq + Hash,
|
||||
S: BuildHasher
|
||||
{
|
||||
fn malloc_shallow_size_of_hash(&self, malloc_enclosing_size_of: MallocEnclosingSizeOfFn)
|
||||
-> usize {
|
||||
// The first value from the iterator gives us an interior pointer.
|
||||
// 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.
|
||||
let mut n = 0;
|
||||
for v in self.iter() {
|
||||
n += unsafe { do_malloc_enclosing_size_of(malloc_enclosing_size_of, v as *const T) };
|
||||
break;
|
||||
}
|
||||
n
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
impl<K, V, S> MallocSizeOfHash for HashMap<K, V, S>
|
||||
where K: Eq + Hash,
|
||||
S: BuildHasher
|
||||
{
|
||||
fn malloc_shallow_size_of_hash(&self, malloc_enclosing_size_of: MallocEnclosingSizeOfFn)
|
||||
-> usize {
|
||||
// The first value from the iterator gives us an interior pointer.
|
||||
// malloc_enclosing_size_of() then gives us the storage size. This
|
||||
// assumes that the HashMap's contents (keys, values, and hashes) are
|
||||
// all stored in a single contiguous heap allocation.
|
||||
let mut n = 0;
|
||||
for v in self.values() {
|
||||
n += unsafe { do_malloc_enclosing_size_of(malloc_enclosing_size_of, v as *const V) };
|
||||
break;
|
||||
}
|
||||
n
|
||||
}
|
||||
}
|
|
@ -12,7 +12,6 @@ pub mod import_rule;
|
|||
pub mod keyframes_rule;
|
||||
mod loader;
|
||||
mod media_rule;
|
||||
mod memory;
|
||||
mod namespace_rule;
|
||||
pub mod origin;
|
||||
mod page_rule;
|
||||
|
@ -26,6 +25,8 @@ pub mod viewport_rule;
|
|||
|
||||
use cssparser::{parse_one_rule, Parser, ParserInput};
|
||||
use error_reporting::NullReporter;
|
||||
#[cfg(feature = "gecko")]
|
||||
use malloc_size_of::MallocSizeOfOps;
|
||||
use parser::{ParserContext, ParserErrorContext};
|
||||
use servo_arc::Arc;
|
||||
use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
|
||||
|
@ -40,10 +41,6 @@ pub use self::import_rule::ImportRule;
|
|||
pub use self::keyframes_rule::KeyframesRule;
|
||||
pub use self::loader::StylesheetLoader;
|
||||
pub use self::media_rule::MediaRule;
|
||||
pub use self::memory::{MallocEnclosingSizeOfFn, MallocSizeOf, MallocSizeOfBox, MallocSizeOfFn};
|
||||
pub use self::memory::{MallocSizeOfHash, MallocSizeOfVec, MallocSizeOfWithGuard};
|
||||
#[cfg(feature = "gecko")]
|
||||
pub use self::memory::{MallocSizeOfWithRepeats, SizeOfState};
|
||||
pub use self::namespace_rule::NamespaceRule;
|
||||
pub use self::origin::{Origin, OriginSet, PerOrigin, PerOriginIter};
|
||||
pub use self::page_rule::PageRule;
|
||||
|
@ -109,12 +106,10 @@ pub enum CssRule {
|
|||
Document(Arc<Locked<DocumentRule>>),
|
||||
}
|
||||
|
||||
impl MallocSizeOfWithGuard for CssRule {
|
||||
fn malloc_size_of_children(
|
||||
&self,
|
||||
guard: &SharedRwLockReadGuard,
|
||||
malloc_size_of: MallocSizeOfFn
|
||||
) -> usize {
|
||||
impl CssRule {
|
||||
/// Measure heap usage.
|
||||
#[cfg(feature = "gecko")]
|
||||
fn size_of(&self, guard: &SharedRwLockReadGuard, ops: &mut MallocSizeOfOps) -> usize {
|
||||
match *self {
|
||||
// Not all fields are currently fully measured. Extra measurement
|
||||
// may be added later.
|
||||
|
@ -125,13 +120,9 @@ impl MallocSizeOfWithGuard for CssRule {
|
|||
// it on the C++ side in the child list of the ServoStyleSheet.
|
||||
CssRule::Import(_) => 0,
|
||||
|
||||
CssRule::Style(ref lock) => {
|
||||
lock.read_with(guard).malloc_size_of_children(guard, malloc_size_of)
|
||||
},
|
||||
CssRule::Style(ref lock) => lock.read_with(guard).size_of(guard, ops),
|
||||
|
||||
CssRule::Media(ref lock) => {
|
||||
lock.read_with(guard).malloc_size_of_children(guard, malloc_size_of)
|
||||
},
|
||||
CssRule::Media(ref lock) => lock.read_with(guard).size_of(guard, ops),
|
||||
|
||||
CssRule::FontFace(_) => 0,
|
||||
CssRule::FontFeatureValues(_) => 0,
|
||||
|
@ -139,17 +130,11 @@ impl MallocSizeOfWithGuard for CssRule {
|
|||
CssRule::Viewport(_) => 0,
|
||||
CssRule::Keyframes(_) => 0,
|
||||
|
||||
CssRule::Supports(ref lock) => {
|
||||
lock.read_with(guard).malloc_size_of_children(guard, malloc_size_of)
|
||||
},
|
||||
CssRule::Supports(ref lock) => lock.read_with(guard).size_of(guard, ops),
|
||||
|
||||
CssRule::Page(ref lock) => {
|
||||
lock.read_with(guard).malloc_size_of_children(guard, malloc_size_of)
|
||||
},
|
||||
CssRule::Page(ref lock) => lock.read_with(guard).size_of(guard, ops),
|
||||
|
||||
CssRule::Document(ref lock) => {
|
||||
lock.read_with(guard).malloc_size_of_children(guard, malloc_size_of)
|
||||
},
|
||||
CssRule::Document(ref lock) => lock.read_with(guard).size_of(guard, ops),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,6 +103,7 @@ impl Iterator for OriginSetIterator {
|
|||
}
|
||||
|
||||
/// An object that stores a `T` for each origin of the CSS cascade.
|
||||
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct PerOrigin<T> {
|
||||
|
|
|
@ -7,12 +7,13 @@
|
|||
//! [page]: https://drafts.csswg.org/css2/page.html#page-box
|
||||
|
||||
use cssparser::SourceLocation;
|
||||
#[cfg(feature = "gecko")]
|
||||
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
|
||||
use properties::PropertyDeclarationBlock;
|
||||
use servo_arc::Arc;
|
||||
use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use stylesheets::{MallocSizeOf, MallocSizeOfFn};
|
||||
|
||||
/// A [`@page`][page] rule.
|
||||
///
|
||||
|
@ -33,10 +34,10 @@ pub struct PageRule {
|
|||
|
||||
impl PageRule {
|
||||
/// Measure heap usage.
|
||||
pub fn malloc_size_of_children(&self, guard: &SharedRwLockReadGuard,
|
||||
malloc_size_of: MallocSizeOfFn) -> usize {
|
||||
#[cfg(feature = "gecko")]
|
||||
pub fn size_of(&self, guard: &SharedRwLockReadGuard, ops: &mut MallocSizeOfOps) -> usize {
|
||||
// Measurement of other fields may be added later.
|
||||
self.block.read_with(guard).malloc_size_of_children(malloc_size_of)
|
||||
self.block.read_with(guard).size_of(ops)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,11 +4,12 @@
|
|||
|
||||
//! A list of CSS rules.
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
use malloc_size_of::{MallocShallowSizeOf, MallocSizeOfOps};
|
||||
use servo_arc::{Arc, RawOffsetArc};
|
||||
use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard};
|
||||
use stylesheets::{CssRule, RulesMutateError};
|
||||
use stylesheets::loader::StylesheetLoader;
|
||||
use stylesheets::memory::{MallocSizeOfFn, MallocSizeOfWithGuard};
|
||||
use stylesheets::rule_parser::State;
|
||||
use stylesheets::stylesheet::StylesheetContents;
|
||||
|
||||
|
@ -36,17 +37,17 @@ impl DeepCloneWithLock for CssRules {
|
|||
}
|
||||
}
|
||||
|
||||
impl MallocSizeOfWithGuard for CssRules {
|
||||
fn malloc_size_of_children(
|
||||
&self,
|
||||
guard: &SharedRwLockReadGuard,
|
||||
malloc_size_of: MallocSizeOfFn
|
||||
) -> usize {
|
||||
self.0.malloc_size_of_children(guard, malloc_size_of)
|
||||
impl CssRules {
|
||||
/// Measure heap usage.
|
||||
#[cfg(feature = "gecko")]
|
||||
pub fn size_of(&self, guard: &SharedRwLockReadGuard, ops: &mut MallocSizeOfOps) -> usize {
|
||||
let mut n = self.0.shallow_size_of(ops);
|
||||
for rule in self.0.iter() {
|
||||
n += rule.size_of(guard, ops);
|
||||
}
|
||||
n
|
||||
}
|
||||
|
||||
impl CssRules {
|
||||
/// Trivially construct a new set of CSS rules.
|
||||
pub fn new(rules: Vec<CssRule>, shared_lock: &SharedRwLock) -> Arc<Locked<CssRules>> {
|
||||
Arc::new(shared_lock.wrap(CssRules(rules)))
|
||||
|
|
|
@ -102,6 +102,7 @@ pub enum State {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
/// Vendor prefix.
|
||||
pub enum VendorPrefix {
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
//! A style rule.
|
||||
|
||||
use cssparser::SourceLocation;
|
||||
#[cfg(feature = "gecko")]
|
||||
use malloc_size_of::{MallocShallowSizeOf, MallocSizeOf, MallocSizeOfOps};
|
||||
use properties::PropertyDeclarationBlock;
|
||||
use selector_parser::SelectorImpl;
|
||||
use selectors::SelectorList;
|
||||
|
@ -12,7 +14,6 @@ use servo_arc::Arc;
|
|||
use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use stylesheets::{MallocSizeOf, MallocSizeOfFn, MallocSizeOfVec, MallocSizeOfWithGuard};
|
||||
|
||||
/// A style rule, with selectors and declarations.
|
||||
#[derive(Debug)]
|
||||
|
@ -41,26 +42,23 @@ impl DeepCloneWithLock for StyleRule {
|
|||
}
|
||||
}
|
||||
|
||||
impl MallocSizeOfWithGuard for StyleRule {
|
||||
fn malloc_size_of_children(
|
||||
&self,
|
||||
guard: &SharedRwLockReadGuard,
|
||||
malloc_size_of: MallocSizeOfFn
|
||||
) -> usize {
|
||||
impl StyleRule {
|
||||
/// Measure heap usage.
|
||||
#[cfg(feature = "gecko")]
|
||||
pub fn size_of(&self, guard: &SharedRwLockReadGuard, ops: &mut MallocSizeOfOps) -> usize {
|
||||
let mut n = 0;
|
||||
|
||||
// We may add measurement of things hanging off the embedded Components
|
||||
// later.
|
||||
n += self.selectors.0.malloc_shallow_size_of_vec(malloc_size_of);
|
||||
n += self.selectors.0.shallow_size_of(ops);
|
||||
for selector in self.selectors.0.iter() {
|
||||
// It's safe to measure this ThinArc directly because it's the
|
||||
// "primary" reference. (The secondary references are on the
|
||||
// Stylist.)
|
||||
let ptr = selector.thin_arc_heap_ptr();
|
||||
n += unsafe { (malloc_size_of.0)(ptr) };
|
||||
n += ops.malloc_size_of(selector.thin_arc_heap_ptr());
|
||||
}
|
||||
|
||||
n += self.block.read_with(guard).malloc_size_of_children(malloc_size_of);
|
||||
n += self.block.read_with(guard).size_of(ops);
|
||||
|
||||
n
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@ use error_reporting::{ParseErrorReporter, ContextualParseError};
|
|||
use fallible::FallibleVec;
|
||||
use fnv::FnvHashMap;
|
||||
use invalidation::media_queries::{MediaListKey, ToMediaListKey};
|
||||
#[cfg(feature = "gecko")]
|
||||
use malloc_size_of::MallocSizeOfOps;
|
||||
use media_queries::{MediaList, Device};
|
||||
use parking_lot::RwLock;
|
||||
use parser::{ParserContext, ParserErrorContext};
|
||||
|
@ -19,7 +21,6 @@ use std::sync::atomic::{AtomicBool, Ordering};
|
|||
use style_traits::PARSING_MODE_DEFAULT;
|
||||
use stylesheets::{CssRule, CssRules, Origin, UrlExtraData};
|
||||
use stylesheets::loader::StylesheetLoader;
|
||||
use stylesheets::memory::{MallocSizeOfFn, MallocSizeOfWithGuard};
|
||||
use stylesheets::rule_parser::{State, TopLevelRuleParser};
|
||||
use stylesheets::rules_iterator::{EffectiveRules, EffectiveRulesIterator, NestedRuleIterationCondition, RulesIterator};
|
||||
use values::specified::NamespaceId;
|
||||
|
@ -116,6 +117,13 @@ impl StylesheetContents {
|
|||
&self.rules.read_with(guard)
|
||||
)
|
||||
}
|
||||
|
||||
/// Measure heap usage.
|
||||
#[cfg(feature = "gecko")]
|
||||
pub fn size_of(&self, guard: &SharedRwLockReadGuard, ops: &mut MallocSizeOfOps) -> usize {
|
||||
// Measurement of other fields may be added later.
|
||||
self.rules.read_with(guard).size_of(guard, ops)
|
||||
}
|
||||
}
|
||||
|
||||
impl DeepCloneWithLock for StylesheetContents {
|
||||
|
@ -141,17 +149,6 @@ impl DeepCloneWithLock for StylesheetContents {
|
|||
}
|
||||
}
|
||||
|
||||
impl MallocSizeOfWithGuard for StylesheetContents {
|
||||
fn malloc_size_of_children(
|
||||
&self,
|
||||
guard: &SharedRwLockReadGuard,
|
||||
malloc_size_of: MallocSizeOfFn
|
||||
) -> usize {
|
||||
// Measurement of other fields may be added later.
|
||||
self.rules.read_with(guard).malloc_size_of_children(guard, malloc_size_of)
|
||||
}
|
||||
}
|
||||
|
||||
/// The structure servo uses to represent a stylesheet.
|
||||
#[derive(Debug)]
|
||||
pub struct Stylesheet {
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
use cssparser::{BasicParseError, ParseError as CssParseError, ParserInput};
|
||||
use cssparser::{Delimiter, parse_important, Parser, SourceLocation, Token};
|
||||
#[cfg(feature = "gecko")]
|
||||
use malloc_size_of::MallocSizeOfOps;
|
||||
use parser::ParserContext;
|
||||
use properties::{PropertyId, PropertyDeclaration, PropertyParserContext, SourcePropertyDeclaration};
|
||||
use selectors::parser::SelectorParseError;
|
||||
|
@ -13,7 +15,7 @@ use servo_arc::Arc;
|
|||
use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
|
||||
use std::fmt;
|
||||
use style_traits::{ToCss, ParseError, StyleParseError};
|
||||
use stylesheets::{CssRuleType, CssRules, MallocSizeOfFn, MallocSizeOfWithGuard};
|
||||
use stylesheets::{CssRuleType, CssRules};
|
||||
|
||||
/// An [`@supports`][supports] rule.
|
||||
///
|
||||
|
@ -32,10 +34,10 @@ pub struct SupportsRule {
|
|||
|
||||
impl SupportsRule {
|
||||
/// Measure heap usage.
|
||||
pub fn malloc_size_of_children(&self, guard: &SharedRwLockReadGuard,
|
||||
malloc_size_of: MallocSizeOfFn) -> usize {
|
||||
#[cfg(feature = "gecko")]
|
||||
pub fn size_of(&self, guard: &SharedRwLockReadGuard, ops: &mut MallocSizeOfOps) -> usize {
|
||||
// Measurement of other fields may be added later.
|
||||
self.rules.read_with(guard).malloc_size_of_children(guard, malloc_size_of)
|
||||
self.rules.read_with(guard).size_of(guard, ops)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@ use gecko_bindings::structs::{nsIAtom, ServoStyleSetSizes, StyleRuleInclusion};
|
|||
use hashglobe::FailedAllocationError;
|
||||
use invalidation::element::invalidation_map::InvalidationMap;
|
||||
use invalidation::media_queries::{EffectiveMediaQueryResults, ToMediaListKey};
|
||||
#[cfg(feature = "gecko")]
|
||||
use malloc_size_of::{MallocShallowSizeOf, MallocSizeOf, MallocSizeOfOps};
|
||||
use media_queries::Device;
|
||||
use properties::{self, CascadeFlags, ComputedValues};
|
||||
use properties::{AnimationRules, PropertyDeclarationBlock};
|
||||
|
@ -43,10 +45,6 @@ use stylesheet_set::{OriginValidity, SheetRebuildKind, StylesheetSet, Stylesheet
|
|||
#[cfg(feature = "gecko")]
|
||||
use stylesheets::{CounterStyleRule, FontFaceRule, FontFeatureValuesRule, PageRule};
|
||||
use stylesheets::{CssRule, Origin, OriginSet, PerOrigin, PerOriginIter};
|
||||
#[cfg(feature = "gecko")]
|
||||
use stylesheets::{MallocEnclosingSizeOfFn, MallocSizeOf, MallocSizeOfBox, MallocSizeOfFn};
|
||||
#[cfg(feature = "gecko")]
|
||||
use stylesheets::{MallocSizeOfHash, MallocSizeOfVec};
|
||||
use stylesheets::StyleRule;
|
||||
use stylesheets::StylesheetInDocument;
|
||||
use stylesheets::UserAgentStylesheets;
|
||||
|
@ -379,19 +377,14 @@ impl DocumentCascadeData {
|
|||
|
||||
/// Measures heap usage.
|
||||
#[cfg(feature = "gecko")]
|
||||
pub fn malloc_add_size_of_children(&self, malloc_size_of: MallocSizeOfFn,
|
||||
malloc_enclosing_size_of: MallocEnclosingSizeOfFn,
|
||||
sizes: &mut ServoStyleSetSizes) {
|
||||
self.per_origin.user_agent.malloc_add_size_of_children(malloc_size_of,
|
||||
malloc_enclosing_size_of, sizes);
|
||||
self.per_origin.user.malloc_add_size_of_children(malloc_size_of,
|
||||
malloc_enclosing_size_of, sizes);
|
||||
self.per_origin.author.malloc_add_size_of_children(malloc_size_of,
|
||||
malloc_enclosing_size_of, sizes);
|
||||
pub fn add_size_of_children(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
|
||||
self.per_origin.user_agent.add_size_of_children(ops, sizes);
|
||||
self.per_origin.user.add_size_of_children(ops, sizes);
|
||||
self.per_origin.author.add_size_of_children(ops, sizes);
|
||||
|
||||
for elem in self.precomputed_pseudo_element_decls.iter() {
|
||||
if let Some(ref elem) = *elem {
|
||||
sizes.mStylistPrecomputedPseudos += elem.malloc_shallow_size_of_vec(malloc_size_of);
|
||||
sizes.mStylistPrecomputedPseudos += elem.shallow_size_of(ops);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1652,12 +1645,9 @@ impl Stylist {
|
|||
|
||||
/// Measures heap usage.
|
||||
#[cfg(feature = "gecko")]
|
||||
pub fn malloc_add_size_of_children(&self, malloc_size_of: MallocSizeOfFn,
|
||||
malloc_enclosing_size_of: MallocEnclosingSizeOfFn,
|
||||
sizes: &mut ServoStyleSetSizes) {
|
||||
self.cascade_data.malloc_add_size_of_children(malloc_size_of, malloc_enclosing_size_of,
|
||||
sizes);
|
||||
sizes.mStylistRuleTree += self.rule_tree.malloc_size_of_children(malloc_size_of);
|
||||
pub fn add_size_of_children(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
|
||||
self.cascade_data.add_size_of_children(ops, sizes);
|
||||
sizes.mStylistRuleTree += self.rule_tree.size_of(ops);
|
||||
|
||||
// We may measure other fields in the future if DMD says it's worth it.
|
||||
}
|
||||
|
@ -1722,22 +1712,27 @@ impl ExtraStyleData {
|
|||
self.pages.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Measure heap usage.
|
||||
#[cfg(feature = "gecko")]
|
||||
pub fn malloc_size_of_children(&self, malloc_size_of: MallocSizeOfFn,
|
||||
malloc_enclosing_size_of: MallocEnclosingSizeOfFn) -> usize {
|
||||
impl MallocSizeOf for ExtraStyleData {
|
||||
/// Measure heap usage.
|
||||
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
|
||||
let mut n = 0;
|
||||
n += self.font_faces.malloc_shallow_size_of_vec(malloc_size_of);
|
||||
n += self.font_feature_values.malloc_shallow_size_of_vec(malloc_size_of);
|
||||
n += self.counter_styles.malloc_shallow_size_of_hash(malloc_enclosing_size_of);
|
||||
n += self.font_faces.shallow_size_of(ops);
|
||||
n += self.font_feature_values.shallow_size_of(ops);
|
||||
n += self.counter_styles.shallow_size_of(ops);
|
||||
n += self.pages.shallow_size_of(ops);
|
||||
n
|
||||
}
|
||||
}
|
||||
|
||||
/// SelectorMapEntry implementation for use in our revalidation selector map.
|
||||
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
|
||||
#[derive(Clone, Debug)]
|
||||
struct RevalidationSelectorAndHashes {
|
||||
#[cfg_attr(feature = "gecko",
|
||||
ignore_malloc_size_of = "CssRules have primary refs, we measure there")]
|
||||
selector: Selector<SelectorImpl>,
|
||||
selector_offset: usize,
|
||||
hashes: AncestorHashes,
|
||||
|
@ -2029,35 +2024,22 @@ impl CascadeData {
|
|||
|
||||
/// Measures heap usage.
|
||||
#[cfg(feature = "gecko")]
|
||||
pub fn malloc_add_size_of_children(&self, malloc_size_of: MallocSizeOfFn,
|
||||
malloc_enclosing_size_of: MallocEnclosingSizeOfFn,
|
||||
sizes: &mut ServoStyleSetSizes) {
|
||||
sizes.mStylistElementAndPseudosMaps +=
|
||||
self.element_map.malloc_size_of_children(malloc_size_of, malloc_enclosing_size_of);
|
||||
pub fn add_size_of_children(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
|
||||
sizes.mStylistElementAndPseudosMaps += self.element_map.size_of(ops);
|
||||
|
||||
for elem in self.pseudos_map.iter() {
|
||||
if let Some(ref elem) = *elem {
|
||||
sizes.mStylistElementAndPseudosMaps +=
|
||||
elem.malloc_shallow_size_of_box(malloc_size_of) +
|
||||
elem.malloc_size_of_children(malloc_size_of, malloc_enclosing_size_of)
|
||||
sizes.mStylistElementAndPseudosMaps += <Box<_> as MallocSizeOf>::size_of(elem, ops);
|
||||
}
|
||||
}
|
||||
|
||||
sizes.mStylistOther +=
|
||||
self.animations.malloc_shallow_size_of_hash(malloc_enclosing_size_of);
|
||||
for val in self.animations.values() {
|
||||
sizes.mStylistOther += val.malloc_size_of_children(malloc_size_of);
|
||||
}
|
||||
sizes.mStylistOther += self.animations.size_of(ops);
|
||||
|
||||
sizes.mStylistInvalidationMap +=
|
||||
self.invalidation_map.malloc_size_of_children(malloc_size_of, malloc_enclosing_size_of);
|
||||
sizes.mStylistInvalidationMap += self.invalidation_map.size_of(ops);
|
||||
|
||||
sizes.mStylistRevalidationSelectors +=
|
||||
self.selectors_for_cache_revalidation.malloc_size_of_children(malloc_size_of,
|
||||
malloc_enclosing_size_of);
|
||||
sizes.mStylistRevalidationSelectors += self.selectors_for_cache_revalidation.size_of(ops);
|
||||
|
||||
sizes.mStylistOther +=
|
||||
self.effective_media_query_results.malloc_size_of_children(malloc_enclosing_size_of);
|
||||
sizes.mStylistOther += self.effective_media_query_results.size_of(ops);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2069,6 +2051,7 @@ impl Default for CascadeData {
|
|||
|
||||
/// A rule, that wraps a style rule, but represents a single selector of the
|
||||
/// rule.
|
||||
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Rule {
|
||||
|
@ -2076,16 +2059,24 @@ pub struct Rule {
|
|||
/// any_{important,normal} booleans inline in the Rule to avoid
|
||||
/// pointer-chasing when gathering applicable declarations, which
|
||||
/// can ruin performance when there are a lot of rules.
|
||||
#[cfg_attr(feature = "gecko",
|
||||
ignore_malloc_size_of = "CssRules have primary refs, we measure there")]
|
||||
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
|
||||
pub selector: Selector<SelectorImpl>,
|
||||
|
||||
/// The ancestor hashes associated with the selector.
|
||||
#[cfg_attr(feature = "servo", ignore_heap_size_of = "No heap data")]
|
||||
pub hashes: AncestorHashes,
|
||||
|
||||
/// The source order this style rule appears in. Note that we only use
|
||||
/// three bytes to store this value in ApplicableDeclarationsBlock, so
|
||||
/// we could repurpose that storage here if we needed to.
|
||||
pub source_order: u32,
|
||||
|
||||
/// The actual style rule.
|
||||
#[cfg_attr(feature = "gecko",
|
||||
ignore_malloc_size_of =
|
||||
"Secondary ref. Primary ref is in StyleRule under Stylesheet.")]
|
||||
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
|
||||
pub style_rule: Arc<Locked<StyleRule>>,
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ cssparser = "0.20.2"
|
|||
env_logger = {version = "0.4", default-features = false} # disable `regex` to reduce code size
|
||||
libc = "0.2"
|
||||
log = {version = "0.3.5", features = ["release_max_level_info"]}
|
||||
malloc_size_of = {path = "../../components/malloc_size_of"}
|
||||
nsstring_vendor = {path = "../../components/style/gecko_bindings/nsstring_vendor"}
|
||||
parking_lot = "0.4"
|
||||
selectors = {path = "../../components/selectors"}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
use cssparser::{Parser, ParserInput};
|
||||
use cssparser::ToCss as ParserToCss;
|
||||
use env_logger::LogBuilder;
|
||||
use malloc_size_of::MallocSizeOfOps;
|
||||
use selectors::Element;
|
||||
use selectors::matching::{MatchingContext, MatchingMode, matches_selector};
|
||||
use servo_arc::{Arc, ArcBorrow, RawOffsetArc};
|
||||
|
@ -52,6 +53,7 @@ use style::gecko_bindings::bindings::Gecko_ConstructFontFeatureValueSet;
|
|||
use style::gecko_bindings::bindings::Gecko_GetOrCreateFinalKeyframe;
|
||||
use style::gecko_bindings::bindings::Gecko_GetOrCreateInitialKeyframe;
|
||||
use style::gecko_bindings::bindings::Gecko_GetOrCreateKeyframeAtStart;
|
||||
use style::gecko_bindings::bindings::Gecko_HaveSeenPtr;
|
||||
use style::gecko_bindings::bindings::Gecko_NewNoneTransform;
|
||||
use style::gecko_bindings::bindings::RawGeckoAnimationPropertySegmentBorrowed;
|
||||
use style::gecko_bindings::bindings::RawGeckoCSSPropertyIDListBorrowed;
|
||||
|
@ -120,9 +122,8 @@ use style::shared_lock::{SharedRwLockReadGuard, StylesheetGuards, ToCssWithGuard
|
|||
use style::string_cache::Atom;
|
||||
use style::style_adjuster::StyleAdjuster;
|
||||
use style::stylesheets::{CssRule, CssRules, CssRuleType, CssRulesHelpers, DocumentRule};
|
||||
use style::stylesheets::{FontFeatureValuesRule, ImportRule, KeyframesRule, MallocEnclosingSizeOfFn};
|
||||
use style::stylesheets::{MallocSizeOfFn, MallocSizeOfWithGuard, MediaRule};
|
||||
use style::stylesheets::{NamespaceRule, Origin, OriginSet, PageRule, SizeOfState, StyleRule};
|
||||
use style::stylesheets::{FontFeatureValuesRule, ImportRule, KeyframesRule, MediaRule};
|
||||
use style::stylesheets::{NamespaceRule, Origin, OriginSet, PageRule, StyleRule};
|
||||
use style::stylesheets::{StylesheetContents, SupportsRule};
|
||||
use style::stylesheets::StylesheetLoader as StyleStylesheetLoader;
|
||||
use style::stylesheets::keyframes_rule::{Keyframe, KeyframeSelector, KeyframesStepValue};
|
||||
|
@ -778,15 +779,13 @@ pub extern "C" fn Servo_Element_ClearData(element: RawGeckoElementBorrowed) {
|
|||
pub extern "C" fn Servo_Element_SizeOfExcludingThisAndCVs(malloc_size_of: GeckoMallocSizeOf,
|
||||
seen_ptrs: *mut SeenPtrs,
|
||||
element: RawGeckoElementBorrowed) -> usize {
|
||||
let malloc_size_of = MallocSizeOfFn(malloc_size_of.unwrap());
|
||||
let element = GeckoElement(element);
|
||||
let borrow = element.borrow_data();
|
||||
if let Some(data) = borrow {
|
||||
let mut state = SizeOfState {
|
||||
malloc_size_of: malloc_size_of,
|
||||
seen_ptrs: seen_ptrs,
|
||||
};
|
||||
(*data).malloc_size_of_children_excluding_cvs(&mut state)
|
||||
let have_seen_ptr = move |ptr| { unsafe { Gecko_HaveSeenPtr(seen_ptrs, ptr) } };
|
||||
let mut ops = MallocSizeOfOps::new(malloc_size_of.unwrap(), None,
|
||||
Some(Box::new(have_seen_ptr)));
|
||||
(*data).size_of_excluding_cvs(&mut ops)
|
||||
} else {
|
||||
0
|
||||
}
|
||||
|
@ -1086,8 +1085,8 @@ pub extern "C" fn Servo_StyleSheet_SizeOfIncludingThis(
|
|||
) -> usize {
|
||||
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||
let guard = global_style_data.shared_lock.read();
|
||||
let malloc_size_of = MallocSizeOfFn(malloc_size_of.unwrap());
|
||||
StylesheetContents::as_arc(&sheet).malloc_size_of_children(&guard, malloc_size_of)
|
||||
let mut ops = MallocSizeOfOps::new(malloc_size_of.unwrap(), None, None);
|
||||
StylesheetContents::as_arc(&sheet).size_of(&guard, &mut ops)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -3710,10 +3709,10 @@ pub extern "C" fn Servo_StyleSet_AddSizeOfExcludingThis(
|
|||
raw_data: RawServoStyleSetBorrowed
|
||||
) {
|
||||
let data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
|
||||
let malloc_size_of = MallocSizeOfFn(malloc_size_of.unwrap());
|
||||
let malloc_enclosing_size_of = MallocEnclosingSizeOfFn(malloc_enclosing_size_of.unwrap());
|
||||
let mut ops = MallocSizeOfOps::new(malloc_size_of.unwrap(),
|
||||
malloc_enclosing_size_of, None);
|
||||
let sizes = unsafe { sizes.as_mut() }.unwrap();
|
||||
data.malloc_add_size_of_children(malloc_size_of, malloc_enclosing_size_of, sizes);
|
||||
data.add_size_of_children(&mut ops, sizes);
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
|
|
@ -8,6 +8,7 @@ extern crate cssparser;
|
|||
extern crate env_logger;
|
||||
extern crate libc;
|
||||
#[macro_use] extern crate log;
|
||||
extern crate malloc_size_of;
|
||||
extern crate selectors;
|
||||
extern crate servo_arc;
|
||||
#[macro_use] extern crate style;
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
extern crate malloc_size_of;
|
||||
extern crate servo_arc;
|
||||
|
||||
use malloc_size_of::{MallocShallowSizeOf, MallocSizeOf};
|
||||
|
||||
fn sizeable<T: MallocSizeOf>() {
|
||||
}
|
||||
|
||||
fn shallow_sizeable<T: MallocShallowSizeOf>() {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
sizeable::<::servo_arc::Arc<i32>>();
|
||||
//~^ ERROR the trait bound `servo_arc::Arc<i32>: malloc_size_of::MallocSizeOf` is not satisfied
|
||||
|
||||
sizeable::<::std::sync::Arc<i32>>();
|
||||
//~^ ERROR the trait bound `std::sync::Arc<i32>: malloc_size_of::MallocSizeOf` is not satisfied
|
||||
|
||||
sizeable::<::std::rc::Rc<i32>>();
|
||||
//~^ ERROR the trait bound `std::rc::Rc<i32>: malloc_size_of::MallocSizeOf` is not satisfied
|
||||
|
||||
shallow_sizeable::<::servo_arc::Arc<i32>>();
|
||||
//~^ ERROR the trait bound `servo_arc::Arc<i32>: malloc_size_of::MallocShallowSizeOf` is not satisfied
|
||||
|
||||
shallow_sizeable::<::std::sync::Arc<i32>>();
|
||||
//~^ ERROR the trait bound `std::sync::Arc<i32>: malloc_size_of::MallocShallowSizeOf` is not satisfied
|
||||
|
||||
shallow_sizeable::<::std::rc::Rc<i32>>();
|
||||
//~^ ERROR the trait bound `std::rc::Rc<i32>: malloc_size_of::MallocShallowSizeOf` is not satisfied
|
||||
}
|
|
@ -19,6 +19,7 @@ euclid = "0.15"
|
|||
geckoservo = {path = "../../../ports/geckolib"}
|
||||
libc = "0.2"
|
||||
log = {version = "0.3.5", features = ["release_max_level_info"]}
|
||||
malloc_size_of = {path = "../../../components/malloc_size_of"}
|
||||
selectors = {path = "../../../components/selectors", features = ["gecko_like_types"]}
|
||||
size_of_test = {path = "../../../components/size_of_test"}
|
||||
style_traits = {path = "../../../components/style_traits"}
|
||||
|
|
|
@ -7,6 +7,7 @@ extern crate cssparser;
|
|||
extern crate env_logger;
|
||||
extern crate geckoservo;
|
||||
#[macro_use] extern crate log;
|
||||
extern crate malloc_size_of;
|
||||
extern crate selectors;
|
||||
#[macro_use] extern crate size_of_test;
|
||||
#[macro_use] extern crate style;
|
||||
|
|
Загрузка…
Ссылка в новой задаче