Auto merge of #18568 - nnethercote:bug-1400078, r=emilio

Measure the UA cache.

This is the Servo PR for https://bugzilla.mozilla.org/show_bug.cgi?id=1400078

<!-- 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
- [X] These changes fix https://bugzilla.mozilla.org/show_bug.cgi?id=1400078

<!-- 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. -->

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/18568)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2017-09-19 18:46:49 -05:00 committed by GitHub
commit ad4f50270d
7 changed files with 114 additions and 84 deletions

View file

@ -36,6 +36,7 @@ const SOURCE_ORDER_MASK: u32 = (1 << SOURCE_ORDER_BITS) - 1;
const SOURCE_ORDER_MAX: u32 = SOURCE_ORDER_MASK; const SOURCE_ORDER_MAX: u32 = SOURCE_ORDER_MASK;
/// Stores the source order of a block and the cascade level it belongs to. /// Stores the source order of a block and the cascade level it belongs to.
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Copy, Eq, PartialEq)] #[derive(Clone, Copy, Eq, PartialEq)]
struct SourceOrderAndCascadeLevel(u32); struct SourceOrderAndCascadeLevel(u32);
@ -75,10 +76,12 @@ impl Debug for SourceOrderAndCascadeLevel {
/// ///
/// This represents the declarations in a given declaration block for a given /// This represents the declarations in a given declaration block for a given
/// importance. /// importance.
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub struct ApplicableDeclarationBlock { pub struct ApplicableDeclarationBlock {
/// The style source, either a style rule, or a property declaration block. /// The style source, either a style rule, or a property declaration block.
#[cfg_attr(feature = "gecko", ignore_malloc_size_of = "contains Arcs")]
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")] #[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
pub source: StyleSource, pub source: StyleSource,
/// The source order of the block, and the cascade level it belongs to. /// The source order of the block, and the cascade level it belongs to.

View file

@ -2089,6 +2089,11 @@ extern "C" {
set: set:
RawServoStyleSetBorrowed); RawServoStyleSetBorrowed);
} }
extern "C" {
pub fn Servo_UACache_AddSizeOf(malloc_size_of: MallocSizeOf,
malloc_enclosing_size_of: MallocSizeOf,
sizes: *mut ServoStyleSetSizes);
}
extern "C" { extern "C" {
pub fn Servo_StyleContext_AddRef(ctx: ServoStyleContextBorrowed); pub fn Servo_StyleContext_AddRef(ctx: ServoStyleContextBorrowed);
} }

View file

@ -4947,17 +4947,16 @@ pub mod root {
#[repr(C)] #[repr(C)]
#[derive(Debug, Copy)] #[derive(Debug, Copy)]
pub struct ServoStyleSetSizes { pub struct ServoStyleSetSizes {
pub mStylistRuleTree: usize, pub mRuleTree: usize,
pub mStylistPrecomputedPseudos: usize, pub mPrecomputedPseudos: usize,
pub mStylistElementAndPseudosMaps: usize, pub mElementAndPseudosMaps: usize,
pub mStylistInvalidationMap: usize, pub mInvalidationMap: usize,
pub mStylistRevalidationSelectors: usize, pub mRevalidationSelectors: usize,
pub mStylistOther: usize,
pub mOther: usize, pub mOther: usize,
} }
#[test] #[test]
fn bindgen_test_layout_ServoStyleSetSizes() { fn bindgen_test_layout_ServoStyleSetSizes() {
assert_eq!(::std::mem::size_of::<ServoStyleSetSizes>() , 56usize , assert_eq!(::std::mem::size_of::<ServoStyleSetSizes>() , 48usize ,
concat ! ( concat ! (
"Size of: " , stringify ! ( ServoStyleSetSizes ) )); "Size of: " , stringify ! ( ServoStyleSetSizes ) ));
assert_eq! (::std::mem::align_of::<ServoStyleSetSizes>() , 8usize assert_eq! (::std::mem::align_of::<ServoStyleSetSizes>() , 8usize
@ -4966,49 +4965,42 @@ pub mod root {
)); ));
assert_eq! (unsafe { assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) . & ( * ( 0 as * const ServoStyleSetSizes ) ) .
mStylistRuleTree as * const _ as usize } , 0usize , mRuleTree as * const _ as usize } , 0usize , concat !
(
"Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! ( mRuleTree
) ));
assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) .
mPrecomputedPseudos as * const _ as usize } , 8usize ,
concat ! ( concat ! (
"Alignment of field: " , stringify ! ( "Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! ( ServoStyleSetSizes ) , "::" , stringify ! (
mStylistRuleTree ) )); mPrecomputedPseudos ) ));
assert_eq! (unsafe { assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) . & ( * ( 0 as * const ServoStyleSetSizes ) ) .
mStylistPrecomputedPseudos as * const _ as usize } , mElementAndPseudosMaps as * const _ as usize } ,
8usize , concat ! ( 16usize , concat ! (
"Alignment of field: " , stringify ! ( "Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! ( ServoStyleSetSizes ) , "::" , stringify ! (
mStylistPrecomputedPseudos ) )); mElementAndPseudosMaps ) ));
assert_eq! (unsafe { assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) . & ( * ( 0 as * const ServoStyleSetSizes ) ) .
mStylistElementAndPseudosMaps as * const _ as usize } mInvalidationMap as * const _ as usize } , 24usize ,
, 16usize , concat ! (
"Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! (
mStylistElementAndPseudosMaps ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) .
mStylistInvalidationMap as * const _ as usize } ,
24usize , concat ! (
"Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! (
mStylistInvalidationMap ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) .
mStylistRevalidationSelectors as * const _ as usize }
, 32usize , concat ! (
"Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! (
mStylistRevalidationSelectors ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) .
mStylistOther as * const _ as usize } , 40usize ,
concat ! ( concat ! (
"Alignment of field: " , stringify ! ( "Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! ( ServoStyleSetSizes ) , "::" , stringify ! (
mStylistOther ) )); mInvalidationMap ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) .
mRevalidationSelectors as * const _ as usize } ,
32usize , concat ! (
"Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! (
mRevalidationSelectors ) ));
assert_eq! (unsafe { assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) . mOther & ( * ( 0 as * const ServoStyleSetSizes ) ) . mOther
as * const _ as usize } , 48usize , concat ! ( as * const _ as usize } , 40usize , concat ! (
"Alignment of field: " , stringify ! ( "Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! ( mOther ) ServoStyleSetSizes ) , "::" , stringify ! ( mOther )
)); ));

View file

@ -4867,17 +4867,16 @@ pub mod root {
#[repr(C)] #[repr(C)]
#[derive(Debug, Copy)] #[derive(Debug, Copy)]
pub struct ServoStyleSetSizes { pub struct ServoStyleSetSizes {
pub mStylistRuleTree: usize, pub mRuleTree: usize,
pub mStylistPrecomputedPseudos: usize, pub mPrecomputedPseudos: usize,
pub mStylistElementAndPseudosMaps: usize, pub mElementAndPseudosMaps: usize,
pub mStylistInvalidationMap: usize, pub mInvalidationMap: usize,
pub mStylistRevalidationSelectors: usize, pub mRevalidationSelectors: usize,
pub mStylistOther: usize,
pub mOther: usize, pub mOther: usize,
} }
#[test] #[test]
fn bindgen_test_layout_ServoStyleSetSizes() { fn bindgen_test_layout_ServoStyleSetSizes() {
assert_eq!(::std::mem::size_of::<ServoStyleSetSizes>() , 56usize , assert_eq!(::std::mem::size_of::<ServoStyleSetSizes>() , 48usize ,
concat ! ( concat ! (
"Size of: " , stringify ! ( ServoStyleSetSizes ) )); "Size of: " , stringify ! ( ServoStyleSetSizes ) ));
assert_eq! (::std::mem::align_of::<ServoStyleSetSizes>() , 8usize assert_eq! (::std::mem::align_of::<ServoStyleSetSizes>() , 8usize
@ -4886,49 +4885,42 @@ pub mod root {
)); ));
assert_eq! (unsafe { assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) . & ( * ( 0 as * const ServoStyleSetSizes ) ) .
mStylistRuleTree as * const _ as usize } , 0usize , mRuleTree as * const _ as usize } , 0usize , concat !
(
"Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! ( mRuleTree
) ));
assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) .
mPrecomputedPseudos as * const _ as usize } , 8usize ,
concat ! ( concat ! (
"Alignment of field: " , stringify ! ( "Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! ( ServoStyleSetSizes ) , "::" , stringify ! (
mStylistRuleTree ) )); mPrecomputedPseudos ) ));
assert_eq! (unsafe { assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) . & ( * ( 0 as * const ServoStyleSetSizes ) ) .
mStylistPrecomputedPseudos as * const _ as usize } , mElementAndPseudosMaps as * const _ as usize } ,
8usize , concat ! ( 16usize , concat ! (
"Alignment of field: " , stringify ! ( "Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! ( ServoStyleSetSizes ) , "::" , stringify ! (
mStylistPrecomputedPseudos ) )); mElementAndPseudosMaps ) ));
assert_eq! (unsafe { assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) . & ( * ( 0 as * const ServoStyleSetSizes ) ) .
mStylistElementAndPseudosMaps as * const _ as usize } mInvalidationMap as * const _ as usize } , 24usize ,
, 16usize , concat ! (
"Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! (
mStylistElementAndPseudosMaps ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) .
mStylistInvalidationMap as * const _ as usize } ,
24usize , concat ! (
"Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! (
mStylistInvalidationMap ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) .
mStylistRevalidationSelectors as * const _ as usize }
, 32usize , concat ! (
"Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! (
mStylistRevalidationSelectors ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) .
mStylistOther as * const _ as usize } , 40usize ,
concat ! ( concat ! (
"Alignment of field: " , stringify ! ( "Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! ( ServoStyleSetSizes ) , "::" , stringify ! (
mStylistOther ) )); mInvalidationMap ) ));
assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) .
mRevalidationSelectors as * const _ as usize } ,
32usize , concat ! (
"Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! (
mRevalidationSelectors ) ));
assert_eq! (unsafe { assert_eq! (unsafe {
& ( * ( 0 as * const ServoStyleSetSizes ) ) . mOther & ( * ( 0 as * const ServoStyleSetSizes ) ) . mOther
as * const _ as usize } , 48usize , concat ! ( as * const _ as usize } , 40usize , concat ! (
"Alignment of field: " , stringify ! ( "Alignment of field: " , stringify ! (
ServoStyleSetSizes ) , "::" , stringify ! ( mOther ) ServoStyleSetSizes ) , "::" , stringify ! ( mOther )
)); ));

View file

@ -112,6 +112,7 @@ pub trait ElementExt: Element<Impl=SelectorImpl> + Debug {
} }
/// A per-functional-pseudo map, from a given pseudo to a `T`. /// A per-functional-pseudo map, from a given pseudo to a `T`.
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct PerPseudoElementMap<T> { pub struct PerPseudoElementMap<T> {
entries: [Option<T>; SIMPLE_PSEUDO_COUNT], entries: [Option<T>; SIMPLE_PSEUDO_COUNT],

View file

@ -17,6 +17,8 @@ use invalidation::element::invalidation_map::InvalidationMap;
use invalidation::media_queries::{EffectiveMediaQueryResults, ToMediaListKey}; use invalidation::media_queries::{EffectiveMediaQueryResults, ToMediaListKey};
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
use malloc_size_of::{MallocShallowSizeOf, MallocSizeOf, MallocSizeOfOps}; use malloc_size_of::{MallocShallowSizeOf, MallocSizeOf, MallocSizeOfOps};
#[cfg(feature = "gecko")]
use malloc_size_of::MallocUnconditionalShallowSizeOf;
use media_queries::Device; use media_queries::Device;
use properties::{self, CascadeFlags, ComputedValues}; use properties::{self, CascadeFlags, ComputedValues};
use properties::{AnimationRules, PropertyDeclarationBlock}; use properties::{AnimationRules, PropertyDeclarationBlock};
@ -133,6 +135,23 @@ impl UserAgentCascadeDataCache {
fn clear(&mut self) { fn clear(&mut self) {
self.entries.clear(); self.entries.clear();
} }
#[cfg(feature = "gecko")]
pub fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
sizes.mOther += self.entries.shallow_size_of(ops);
for arc in self.entries.iter() {
// These are primary Arc references that can be measured
// unconditionally.
sizes.mOther += arc.unconditional_shallow_size_of(ops);
arc.add_size_of(ops, sizes);
}
}
}
/// Measure heap usage of UA_CASCADE_DATA_CACHE.
#[cfg(feature = "gecko")]
pub fn add_size_of_ua_cache(ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
UA_CASCADE_DATA_CACHE.lock().unwrap().add_size_of(ops, sizes);
} }
type PrecomputedPseudoElementDeclarations = type PrecomputedPseudoElementDeclarations =
@ -151,6 +170,14 @@ struct UserAgentCascadeData {
precomputed_pseudo_element_decls: PrecomputedPseudoElementDeclarations, precomputed_pseudo_element_decls: PrecomputedPseudoElementDeclarations,
} }
impl UserAgentCascadeData {
#[cfg(feature = "gecko")]
fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
self.cascade_data.add_size_of_children(ops, sizes);
sizes.mPrecomputedPseudos += self.precomputed_pseudo_element_decls.size_of(ops);
}
}
/// All the computed information for a stylesheet. /// All the computed information for a stylesheet.
#[derive(Default)] #[derive(Default)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@ -304,9 +331,6 @@ impl DocumentCascadeData {
pub fn add_size_of_children(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) { pub fn add_size_of_children(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
self.user.add_size_of_children(ops, sizes); self.user.add_size_of_children(ops, sizes);
self.author.add_size_of_children(ops, sizes); self.author.add_size_of_children(ops, sizes);
// FIXME(emilio): UA_CASCADE_DATA_CACHE is shared, we should do whatever
// we do for RuleProcessorCache in Gecko.
} }
} }
@ -1500,7 +1524,7 @@ impl Stylist {
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
pub fn add_size_of_children(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) { pub fn add_size_of_children(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
self.cascade_data.add_size_of_children(ops, sizes); self.cascade_data.add_size_of_children(ops, sizes);
sizes.mStylistRuleTree += self.rule_tree.size_of(ops); sizes.mRuleTree += self.rule_tree.size_of(ops);
// We may measure other fields in the future if DMD says it's worth it. // We may measure other fields in the future if DMD says it's worth it.
} }
@ -2194,22 +2218,22 @@ impl CascadeData {
/// Measures heap usage. /// Measures heap usage.
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
pub fn add_size_of_children(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) { pub fn add_size_of_children(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) {
sizes.mStylistElementAndPseudosMaps += self.element_map.size_of(ops); sizes.mElementAndPseudosMaps += self.element_map.size_of(ops);
for elem in self.pseudos_map.iter() { for elem in self.pseudos_map.iter() {
if let Some(ref elem) = *elem { if let Some(ref elem) = *elem {
sizes.mStylistElementAndPseudosMaps += <Box<_> as MallocSizeOf>::size_of(elem, ops); sizes.mElementAndPseudosMaps += <Box<_> as MallocSizeOf>::size_of(elem, ops);
} }
} }
sizes.mStylistOther += self.animations.size_of(ops); sizes.mOther += self.animations.size_of(ops);
sizes.mStylistInvalidationMap += self.invalidation_map.size_of(ops); sizes.mInvalidationMap += self.invalidation_map.size_of(ops);
sizes.mStylistRevalidationSelectors += self.selectors_for_cache_revalidation.size_of(ops); sizes.mRevalidationSelectors += self.selectors_for_cache_revalidation.size_of(ops);
sizes.mStylistOther += self.effective_media_query_results.size_of(ops); sizes.mOther += self.effective_media_query_results.size_of(ops);
sizes.mStylistOther += self.extra_data.size_of(ops); sizes.mOther += self.extra_data.size_of(ops);
} }
} }

View file

@ -131,7 +131,7 @@ use style::stylesheets::{StylesheetContents, SupportsRule};
use style::stylesheets::StylesheetLoader as StyleStylesheetLoader; use style::stylesheets::StylesheetLoader as StyleStylesheetLoader;
use style::stylesheets::keyframes_rule::{Keyframe, KeyframeSelector, KeyframesStepValue}; use style::stylesheets::keyframes_rule::{Keyframe, KeyframeSelector, KeyframesStepValue};
use style::stylesheets::supports_rule::parse_condition_or_declaration; use style::stylesheets::supports_rule::parse_condition_or_declaration;
use style::stylist::{RuleInclusion, Stylist}; use style::stylist::{add_size_of_ua_cache, RuleInclusion, Stylist};
use style::thread_state; use style::thread_state;
use style::timer::Timer; use style::timer::Timer;
use style::traversal::DomTraversal; use style::traversal::DomTraversal;
@ -3768,6 +3768,19 @@ pub extern "C" fn Servo_StyleSet_AddSizeOfExcludingThis(
data.add_size_of_children(&mut ops, sizes); data.add_size_of_children(&mut ops, sizes);
} }
#[no_mangle]
pub extern "C" fn Servo_UACache_AddSizeOf(
malloc_size_of: GeckoMallocSizeOf,
malloc_enclosing_size_of: GeckoMallocSizeOf,
sizes: *mut ServoStyleSetSizes
) {
let mut ops = MallocSizeOfOps::new(malloc_size_of.unwrap(),
malloc_enclosing_size_of.unwrap(),
None);
let sizes = unsafe { sizes.as_mut() }.unwrap();
add_size_of_ua_cache(&mut ops, sizes);
}
#[no_mangle] #[no_mangle]
pub extern "C" fn Servo_StyleSet_MightHaveAttributeDependency( pub extern "C" fn Servo_StyleSet_MightHaveAttributeDependency(
raw_data: RawServoStyleSetBorrowed, raw_data: RawServoStyleSetBorrowed,