aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/style/driver.rs60
-rw-r--r--components/style/gecko/generated/structs.rs101
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,