Bug 1475191 - Measure heap allocations hanging off selector components. r?emilio
MozReview-Commit-ID: D7vZQ7v8owS
--- a/servo/components/malloc_size_of/lib.rs
+++ b/servo/components/malloc_size_of/lib.rs
@@ -688,16 +688,100 @@ impl<T: MallocSizeOf, U> MallocSizeOf fo
impl MallocSizeOf for selectors::parser::AncestorHashes {
fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
let selectors::parser::AncestorHashes { ref packed_hashes } = *self;
packed_hashes.size_of(ops)
}
}
+impl<Impl: selectors::parser::SelectorImpl> MallocSizeOf
+ for selectors::parser::Selector<Impl>
+where
+ Impl::NonTSPseudoClass: MallocSizeOf,
+ Impl::PseudoElement: MallocSizeOf,
+{
+ fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
+ let mut n = 0;
+
+ // It's OK to measure this ThinArc directly because it's the
+ // "primary" reference. (The secondary references are on the
+ // Stylist.)
+ n += unsafe { ops.malloc_size_of(self.thin_arc_heap_ptr()) };
+ for component in self.iter_raw_match_order() {
+ n += component.size_of(ops);
+ }
+
+ n
+ }
+}
+
+impl<Impl: selectors::parser::SelectorImpl> MallocSizeOf
+ for selectors::parser::Component<Impl>
+where
+ Impl::NonTSPseudoClass: MallocSizeOf,
+ Impl::PseudoElement: MallocSizeOf,
+{
+ fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
+ use selectors::parser::Component;
+
+ match self {
+ Component::AttributeOther(ref attr_selector) => {
+ attr_selector.size_of(ops)
+ }
+ Component::Negation(ref components) => {
+ components.size_of(ops)
+ }
+ Component::NonTSPseudoClass(ref pseudo) => {
+ (*pseudo).size_of(ops)
+ }
+ Component::Slotted(ref selector) |
+ Component::Host(Some(ref selector)) => {
+ selector.size_of(ops)
+ }
+ Component::PseudoElement(ref pseudo) => {
+ (*pseudo).size_of(ops)
+ }
+ Component::Combinator(..) |
+ Component::ExplicitAnyNamespace |
+ Component::ExplicitNoNamespace |
+ Component::DefaultNamespace(..) |
+ Component::Namespace(..) |
+ Component::ExplicitUniversalType |
+ Component::LocalName(..) |
+ Component::ID(..) |
+ Component::Class(..) |
+ Component::AttributeInNoNamespaceExists { .. } |
+ Component::AttributeInNoNamespace { .. } |
+ Component::FirstChild |
+ Component::LastChild |
+ Component::OnlyChild |
+ Component::Root |
+ Component::Empty |
+ Component::Scope |
+ Component::NthChild(..) |
+ Component::NthLastChild(..) |
+ Component::NthOfType(..) |
+ Component::NthLastOfType(..) |
+ Component::FirstOfType |
+ Component::LastOfType |
+ Component::OnlyOfType |
+ Component::Host(None) => 0,
+ }
+ }
+}
+
+impl<Impl: selectors::parser::SelectorImpl> MallocSizeOf
+ for selectors::attr::AttrSelectorWithNamespace<Impl>
+{
+ fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
+ 0
+ }
+}
+
impl MallocSizeOf for Void {
#[inline]
fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize {
void::unreachable(*self)
}
}
#[cfg(feature = "servo")]
--- a/servo/components/style/gecko/pseudo_element_definition.mako.rs
+++ b/servo/components/style/gecko/pseudo_element_definition.mako.rs
@@ -1,14 +1,14 @@
/* 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/. */
/// Gecko's pseudo-element definition.
-#[derive(Clone, Debug, Eq, Hash, PartialEq)]
+#[derive(Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
pub enum PseudoElement {
% for pseudo in PSEUDOS:
/// ${pseudo.value}
% if pseudo.is_tree_pseudo_element():
${pseudo.capitalized()}(Box<[Atom]>),
% else:
${pseudo.capitalized()},
% endif
--- a/servo/components/style/gecko/selector_parser.rs
+++ b/servo/components/style/gecko/selector_parser.rs
@@ -35,17 +35,17 @@ bitflags! {
/// The type used for storing pseudo-class string arguments.
pub type PseudoClassStringArg = Box<[u16]>;
macro_rules! pseudo_class_name {
(bare: [$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*],
string: [$(($s_css:expr, $s_name:ident, $s_gecko_type:tt, $s_state:tt, $s_flags:tt),)*]) => {
/// Our representation of a non tree-structural pseudo-class.
- #[derive(Clone, Debug, Eq, PartialEq)]
+ #[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq)]
pub enum NonTSPseudoClass {
$(
#[doc = $css]
$name,
)*
$(
#[doc = $s_css]
$s_name(PseudoClassStringArg),
--- a/servo/components/style/selector_parser.rs
+++ b/servo/components/style/selector_parser.rs
@@ -167,17 +167,17 @@ impl<T> PerPseudoElementMap<T> {
/// Get an iterator for the entries.
pub fn iter(&self) -> ::std::slice::Iter<Option<T>> {
self.entries.iter()
}
}
/// Values for the :dir() pseudo class
-#[derive(Clone, Debug, Eq, PartialEq)]
+#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq)]
pub enum Direction {
/// left-to-right semantic directionality
Ltr,
/// right-to-left semantic directionality
Rtl,
/// Some other provided directionality value
///
/// TODO(emilio): If we atomize we can then unbox in NonTSPseudoClass.
--- a/servo/components/style/stylesheets/style_rule.rs
+++ b/servo/components/style/stylesheets/style_rule.rs
@@ -1,17 +1,17 @@
/* 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/. */
//! A style rule.
use cssparser::SourceLocation;
#[cfg(feature = "gecko")]
-use malloc_size_of::{MallocShallowSizeOf, MallocSizeOf, MallocSizeOfOps};
+use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
#[cfg(feature = "gecko")]
use malloc_size_of::MallocUnconditionalShallowSizeOf;
use properties::PropertyDeclarationBlock;
use selector_parser::SelectorImpl;
use selectors::SelectorList;
use servo_arc::Arc;
use shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked};
use shared_lock::{SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
@@ -45,30 +45,19 @@ impl DeepCloneWithLock for StyleRule {
}
}
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.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.)
- n += unsafe { ops.malloc_size_of(selector.thin_arc_heap_ptr()) };
- }
-
+ n += self.selectors.0.size_of(ops);
n += self.block.unconditional_shallow_size_of(ops) +
self.block.read_with(guard).size_of(ops);
-
n
}
}
impl ToCssWithGuard for StyleRule {
/// https://drafts.csswg.org/cssom/#serialize-a-css-rule CSSStyleRule
fn to_css(&self, guard: &SharedRwLockReadGuard, dest: &mut CssStringWriter) -> fmt::Result {
use cssparser::ToCss;