mirror of
https://github.com/servo/servo.git
synced 2025-08-09 15:35:34 +01:00
Overhaul MallocSizeOf and related things.
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.
This commit is contained in:
parent
24b2d8d9cf
commit
32548e5312
44 changed files with 1188 additions and 486 deletions
|
@ -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;
|
||||
|
@ -292,6 +292,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]
|
||||
|
@ -1329,19 +1330,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>>,
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue