diff options
-rw-r--r-- | components/style/driver.rs | 60 | ||||
-rw-r--r-- | components/style/gecko/generated/structs.rs | 101 |
2 files changed, 150 insertions, 11 deletions
diff --git a/components/style/driver.rs b/components/style/driver.rs index 6f99b542a5f..17c9fecb3b1 100644 --- a/components/style/driver.rs +++ b/components/style/driver.rs @@ -7,7 +7,8 @@ #![deny(missing_docs)] -use context::{StyleContext, ThreadLocalStyleContext, TraversalStatistics}; +use context::{StyleContext, PerThreadTraversalStatistics}; +use context::{ThreadLocalStyleContext, TraversalStatistics}; use dom::{SendNode, TElement, TNode}; use parallel; use parallel::{DispatchMode, WORK_UNIT_MAX}; @@ -18,6 +19,36 @@ use std::mem; use time; use traversal::{DomTraversal, PerLevelTraversalData, PreTraverseToken}; +#[cfg(feature = "servo")] +fn should_report_statistics() -> bool { + false +} + +#[cfg(feature = "gecko")] +fn should_report_statistics() -> bool { + unsafe { ::gecko_bindings::structs::ServoTraversalStatistics_sActive } +} + +#[cfg(feature = "servo")] +fn report_statistics(_stats: &PerThreadTraversalStatistics) { + unreachable!("Servo never report stats"); +} + +#[cfg(feature = "gecko")] +fn report_statistics(stats: &PerThreadTraversalStatistics) { + // This should only be called in the main thread, or it may be racy + // to update the statistics in a global variable. + debug_assert!(unsafe { ::gecko_bindings::bindings::Gecko_IsMainThread() }); + let gecko_stats = unsafe { + &mut ::gecko_bindings::structs::ServoTraversalStatistics_sSingleton + }; + gecko_stats.mElementsTraversed += stats.elements_traversed; + gecko_stats.mElementsStyled += stats.elements_styled; + gecko_stats.mElementsMatched += stats.elements_matched; + gecko_stats.mStylesShared += stats.styles_shared; + gecko_stats.mStylesReused += stats.styles_reused; +} + /// Do a DOM traversal for top-down and (optionally) bottom-up processing, /// generic over `D`. /// @@ -41,6 +72,7 @@ where let root = token.traversal_root().expect("Should've ensured we needed to traverse"); + let report_stats = should_report_statistics(); let dump_stats = traversal.shared_context().options.dump_style_statistics; let start_time = if dump_stats { Some(time::precise_time_s()) } else { None }; @@ -113,8 +145,8 @@ where } } - // dump statistics to stdout if requested - if dump_stats { + // Collect statistics from thread-locals if requested. + if dump_stats || report_stats { let mut aggregate = mem::replace(&mut context.thread_local.statistics, Default::default()); let parallel = maybe_tls.is_some(); @@ -128,14 +160,20 @@ where }); } - let stats = TraversalStatistics::new( - aggregate, - traversal, - parallel, - start_time.unwrap() - ); - if stats.is_large { - println!("{}", stats); + if report_stats { + report_statistics(&aggregate); + } + // dump statistics to stdout if requested + if dump_stats { + let stats = TraversalStatistics::new( + aggregate, + traversal, + parallel, + start_time.unwrap() + ); + if stats.is_large { + println!("{}", stats); + } } } } diff --git a/components/style/gecko/generated/structs.rs b/components/style/gecko/generated/structs.rs index c20b03d33ca..5374f420c7d 100644 --- a/components/style/gecko/generated/structs.rs +++ b/components/style/gecko/generated/structs.rs @@ -13634,6 +13634,107 @@ pub mod root { ); } #[repr(C)] + #[derive(Debug, Copy)] + pub struct ServoTraversalStatistics { + pub mElementsTraversed: u32, + pub mElementsStyled: u32, + pub mElementsMatched: u32, + pub mStylesShared: u32, + pub mStylesReused: u32, + } + extern "C" { + #[link_name = "\u{1}_ZN7mozilla24ServoTraversalStatistics7sActiveE"] + pub static mut ServoTraversalStatistics_sActive: bool; + } + extern "C" { + #[link_name = "\u{1}_ZN7mozilla24ServoTraversalStatistics10sSingletonE"] + pub static mut ServoTraversalStatistics_sSingleton: + root::mozilla::ServoTraversalStatistics; + } + #[test] + fn bindgen_test_layout_ServoTraversalStatistics() { + assert_eq!( + ::std::mem::size_of::<ServoTraversalStatistics>(), + 20usize, + concat!("Size of: ", stringify!(ServoTraversalStatistics)) + ); + assert_eq!( + ::std::mem::align_of::<ServoTraversalStatistics>(), + 4usize, + concat!("Alignment of ", stringify!(ServoTraversalStatistics)) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::<ServoTraversalStatistics>())).mElementsTraversed + as *const _ as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(ServoTraversalStatistics), + "::", + stringify!(mElementsTraversed) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::<ServoTraversalStatistics>())).mElementsStyled as *const _ + as usize + }, + 4usize, + concat!( + "Offset of field: ", + stringify!(ServoTraversalStatistics), + "::", + stringify!(mElementsStyled) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::<ServoTraversalStatistics>())).mElementsMatched + as *const _ as usize + }, + 8usize, + concat!( + "Offset of field: ", + stringify!(ServoTraversalStatistics), + "::", + stringify!(mElementsMatched) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::<ServoTraversalStatistics>())).mStylesShared as *const _ + as usize + }, + 12usize, + concat!( + "Offset of field: ", + stringify!(ServoTraversalStatistics), + "::", + stringify!(mStylesShared) + ) + ); + assert_eq!( + unsafe { + &(*(::std::ptr::null::<ServoTraversalStatistics>())).mStylesReused as *const _ + as usize + }, + 16usize, + concat!( + "Offset of field: ", + stringify!(ServoTraversalStatistics), + "::", + stringify!(mStylesReused) + ) + ); + } + impl Clone for ServoTraversalStatistics { + fn clone(&self) -> Self { + *self + } + } + #[repr(C)] #[derive(Debug)] pub struct CSSFontFaceDescriptors { pub mFamily: root::nsCSSValue, |