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:
Nicholas Nethercote 2017-09-11 22:11:25 -05:00
Родитель 8cdad036f1
Коммит 43983aa52e
44 изменённых файлов: 1188 добавлений и 486 удалений

25
servo/Cargo.lock сгенерированный
Просмотреть файл

@ -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
}
/// 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();
}
}
}
#[cfg(feature = "gecko")]
impl MallocSizeOf for ExtraStyleData {
/// Measure heap usage.
#[cfg(feature = "gecko")]
pub fn malloc_size_of_children(&self, malloc_size_of: MallocSizeOfFn,
malloc_enclosing_size_of: MallocEnclosingSizeOfFn) -> usize {
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;