зеркало из https://github.com/mozilla/gecko-dev.git
servo: Merge #16369 - Store style system options in the global style data and shared style context (from bholley:style_system_options); r=SimonSapin
I wanted to add an environmental variable to disable the style sharing cache for gecko, but the current pattern involves lazy_static!, which involves an atomic operation on lookup, which is a bit hot to do each time we try to share styles. This makes that work happen once per process. Source-Repo: https://github.com/servo/servo Source-Revision: 54ecfb155dba40382764ee20186a31f067a507be --HG-- extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear extra : subtree_revision : 35cbfe0f6490eadf25d9de020f0d2ea851badaba
This commit is contained in:
Родитель
372552d50a
Коммит
9ab23a87f3
|
@ -107,7 +107,8 @@ use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
use std::sync::mpsc::{Receiver, Sender, channel};
|
use std::sync::mpsc::{Receiver, Sender, channel};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use style::animation::Animation;
|
use style::animation::Animation;
|
||||||
use style::context::{QuirksMode, ReflowGoal, SharedStyleContext, ThreadLocalStyleContextCreationInfo};
|
use style::context::{QuirksMode, ReflowGoal, SharedStyleContext};
|
||||||
|
use style::context::{StyleSystemOptions, ThreadLocalStyleContextCreationInfo};
|
||||||
use style::data::StoredRestyleHint;
|
use style::data::StoredRestyleHint;
|
||||||
use style::dom::{ShowSubtree, ShowSubtreeDataAndPrimaryValues, TElement, TNode};
|
use style::dom::{ShowSubtree, ShowSubtreeDataAndPrimaryValues, TElement, TNode};
|
||||||
use style::error_reporting::StdoutErrorReporter;
|
use style::error_reporting::StdoutErrorReporter;
|
||||||
|
@ -516,6 +517,7 @@ impl LayoutThread {
|
||||||
LayoutContext {
|
LayoutContext {
|
||||||
style_context: SharedStyleContext {
|
style_context: SharedStyleContext {
|
||||||
stylist: rw_data.stylist.clone(),
|
stylist: rw_data.stylist.clone(),
|
||||||
|
options: StyleSystemOptions::default(),
|
||||||
guards: guards,
|
guards: guards,
|
||||||
running_animations: self.running_animations.clone(),
|
running_animations: self.running_animations.clone(),
|
||||||
expired_animations: self.expired_animations.clone(),
|
expired_animations: self.expired_animations.clone(),
|
||||||
|
|
|
@ -61,6 +61,42 @@ pub enum QuirksMode {
|
||||||
NoQuirks,
|
NoQuirks,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A global options structure for the style system. We use this instead of
|
||||||
|
/// opts to abstract across Gecko and Servo.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct StyleSystemOptions {
|
||||||
|
/// Whether the style sharing cache is disabled.
|
||||||
|
pub disable_style_sharing_cache: bool,
|
||||||
|
/// Whether we should dump statistics about the style system.
|
||||||
|
pub dump_style_statistics: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
fn get_env(name: &str) -> bool {
|
||||||
|
match env::var(name) {
|
||||||
|
Ok(s) => !s.is_empty(),
|
||||||
|
Err(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for StyleSystemOptions {
|
||||||
|
#[cfg(feature = "servo")]
|
||||||
|
fn default() -> Self {
|
||||||
|
StyleSystemOptions {
|
||||||
|
disable_style_sharing_cache: opts::get().disable_share_style_cache,
|
||||||
|
dump_style_statistics: opts::get().style_sharing_stats,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "gecko")]
|
||||||
|
fn default() -> Self {
|
||||||
|
StyleSystemOptions {
|
||||||
|
disable_style_sharing_cache: get_env("DISABLE_STYLE_SHARING_CACHE"),
|
||||||
|
dump_style_statistics: get_env("DUMP_STYLE_STATISTICS"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A shared style context.
|
/// A shared style context.
|
||||||
///
|
///
|
||||||
/// There's exactly one of these during a given restyle traversal, and it's
|
/// There's exactly one of these during a given restyle traversal, and it's
|
||||||
|
@ -69,6 +105,9 @@ pub struct SharedStyleContext<'a> {
|
||||||
/// The CSS selector stylist.
|
/// The CSS selector stylist.
|
||||||
pub stylist: Arc<Stylist>,
|
pub stylist: Arc<Stylist>,
|
||||||
|
|
||||||
|
/// Configuration options.
|
||||||
|
pub options: StyleSystemOptions,
|
||||||
|
|
||||||
/// Guards for pre-acquired locks
|
/// Guards for pre-acquired locks
|
||||||
pub guards: StylesheetGuards<'a>,
|
pub guards: StylesheetGuards<'a>,
|
||||||
|
|
||||||
|
@ -175,35 +214,7 @@ impl fmt::Display for TraversalStatistics {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "servo"))]
|
|
||||||
lazy_static! {
|
|
||||||
/// Whether to dump style statistics, computed statically. We use an environmental
|
|
||||||
/// variable so that this is easy to set for Gecko builds, and matches the
|
|
||||||
/// mechanism we use to dump statistics on the Gecko style system.
|
|
||||||
static ref DUMP_STYLE_STATISTICS: bool = {
|
|
||||||
match env::var("DUMP_STYLE_STATISTICS") {
|
|
||||||
Ok(s) => !s.is_empty(),
|
|
||||||
Err(_) => false,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "servo")]
|
|
||||||
fn shall_stat_style_sharing() -> bool {
|
|
||||||
opts::get().style_sharing_stats
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "servo"))]
|
|
||||||
fn shall_stat_style_sharing() -> bool {
|
|
||||||
*DUMP_STYLE_STATISTICS
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TraversalStatistics {
|
impl TraversalStatistics {
|
||||||
/// Returns whether statistics dumping is enabled.
|
|
||||||
pub fn should_dump() -> bool {
|
|
||||||
shall_stat_style_sharing()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Computes the traversal time given the start time in seconds.
|
/// Computes the traversal time given the start time in seconds.
|
||||||
pub fn finish<E, D>(&mut self, traversal: &D, start: f64)
|
pub fn finish<E, D>(&mut self, traversal: &D, start: f64)
|
||||||
where E: TElement,
|
where E: TElement,
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
//! Global style data
|
//! Global style data
|
||||||
|
|
||||||
|
use context::StyleSystemOptions;
|
||||||
use num_cpus;
|
use num_cpus;
|
||||||
use rayon;
|
use rayon;
|
||||||
use shared_lock::SharedRwLock;
|
use shared_lock::SharedRwLock;
|
||||||
|
@ -20,6 +21,9 @@ pub struct GlobalStyleData {
|
||||||
|
|
||||||
/// Shared RWLock for CSSOM objects
|
/// Shared RWLock for CSSOM objects
|
||||||
pub shared_lock: SharedRwLock,
|
pub shared_lock: SharedRwLock,
|
||||||
|
|
||||||
|
/// Global style system options determined by env vars.
|
||||||
|
pub options: StyleSystemOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
|
@ -45,6 +49,7 @@ lazy_static! {
|
||||||
num_threads: num_threads,
|
num_threads: num_threads,
|
||||||
style_thread_pool: pool,
|
style_thread_pool: pool,
|
||||||
shared_lock: SharedRwLock::new(),
|
shared_lock: SharedRwLock::new(),
|
||||||
|
options: StyleSystemOptions::default(),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,6 @@ use selector_parser::{PseudoElement, RestyleDamage, SelectorImpl};
|
||||||
use selectors::bloom::BloomFilter;
|
use selectors::bloom::BloomFilter;
|
||||||
use selectors::matching::{ElementSelectorFlags, StyleRelations};
|
use selectors::matching::{ElementSelectorFlags, StyleRelations};
|
||||||
use selectors::matching::AFFECTED_BY_PSEUDO_ELEMENTS;
|
use selectors::matching::AFFECTED_BY_PSEUDO_ELEMENTS;
|
||||||
#[cfg(feature = "servo")] use servo_config::opts;
|
|
||||||
use sink::ForgetfulSink;
|
use sink::ForgetfulSink;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use stylist::ApplicableDeclarationBlock;
|
use stylist::ApplicableDeclarationBlock;
|
||||||
|
@ -727,16 +726,6 @@ pub enum StyleSharingBehavior {
|
||||||
Disallow,
|
Disallow,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "servo")]
|
|
||||||
fn is_share_style_cache_disabled() -> bool {
|
|
||||||
opts::get().disable_share_style_cache
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "servo"))]
|
|
||||||
fn is_share_style_cache_disabled() -> bool {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The public API that elements expose for selector matching.
|
/// The public API that elements expose for selector matching.
|
||||||
pub trait MatchMethods : TElement {
|
pub trait MatchMethods : TElement {
|
||||||
/// Performs selector matching and property cascading on an element and its eager pseudos.
|
/// Performs selector matching and property cascading on an element and its eager pseudos.
|
||||||
|
@ -1033,7 +1022,7 @@ pub trait MatchMethods : TElement {
|
||||||
context: &mut StyleContext<Self>,
|
context: &mut StyleContext<Self>,
|
||||||
data: &mut AtomicRefMut<ElementData>)
|
data: &mut AtomicRefMut<ElementData>)
|
||||||
-> StyleSharingResult {
|
-> StyleSharingResult {
|
||||||
if is_share_style_cache_disabled() {
|
if context.shared.options.disable_style_sharing_cache {
|
||||||
debug!("{:?} Cannot share style: style sharing cache disabled", self);
|
debug!("{:?} Cannot share style: style sharing cache disabled", self);
|
||||||
return StyleSharingResult::CannotShare
|
return StyleSharingResult::CannotShare
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ pub fn traverse_dom<E, D>(traversal: &D,
|
||||||
where E: TElement,
|
where E: TElement,
|
||||||
D: DomTraversal<E>,
|
D: DomTraversal<E>,
|
||||||
{
|
{
|
||||||
let dump_stats = TraversalStatistics::should_dump();
|
let dump_stats = traversal.shared_context().options.dump_style_statistics;
|
||||||
let start_time = if dump_stats { Some(time::precise_time_s()) } else { None };
|
let start_time = if dump_stats { Some(time::precise_time_s()) } else { None };
|
||||||
|
|
||||||
debug_assert!(traversal.is_parallel());
|
debug_assert!(traversal.is_parallel());
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
#![deny(missing_docs)]
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
use context::TraversalStatistics;
|
|
||||||
use dom::{TElement, TNode};
|
use dom::{TElement, TNode};
|
||||||
use std::borrow::BorrowMut;
|
use std::borrow::BorrowMut;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
@ -22,7 +21,7 @@ pub fn traverse_dom<E, D>(traversal: &D,
|
||||||
where E: TElement,
|
where E: TElement,
|
||||||
D: DomTraversal<E>,
|
D: DomTraversal<E>,
|
||||||
{
|
{
|
||||||
let dump_stats = TraversalStatistics::should_dump();
|
let dump_stats = traversal.shared_context().options.dump_style_statistics;
|
||||||
let start_time = if dump_stats { Some(time::precise_time_s()) } else { None };
|
let start_time = if dump_stats { Some(time::precise_time_s()) } else { None };
|
||||||
|
|
||||||
debug_assert!(!traversal.is_parallel());
|
debug_assert!(!traversal.is_parallel());
|
||||||
|
|
|
@ -22,7 +22,7 @@ use style::dom::{ShowSubtreeData, TElement, TNode};
|
||||||
use style::error_reporting::StdoutErrorReporter;
|
use style::error_reporting::StdoutErrorReporter;
|
||||||
use style::font_metrics::get_metrics_provider_for_product;
|
use style::font_metrics::get_metrics_provider_for_product;
|
||||||
use style::gecko::data::{PerDocumentStyleData, PerDocumentStyleDataImpl};
|
use style::gecko::data::{PerDocumentStyleData, PerDocumentStyleDataImpl};
|
||||||
use style::gecko::global_style_data::GLOBAL_STYLE_DATA;
|
use style::gecko::global_style_data::{GLOBAL_STYLE_DATA, GlobalStyleData};
|
||||||
use style::gecko::restyle_damage::GeckoRestyleDamage;
|
use style::gecko::restyle_damage::GeckoRestyleDamage;
|
||||||
use style::gecko::selector_parser::{SelectorImpl, PseudoElement};
|
use style::gecko::selector_parser::{SelectorImpl, PseudoElement};
|
||||||
use style::gecko::traversal::RecalcStyleOnly;
|
use style::gecko::traversal::RecalcStyleOnly;
|
||||||
|
@ -143,7 +143,8 @@ unsafe fn dummy_url_data() -> &'static RefPtr<URLExtraData> {
|
||||||
RefPtr::from_ptr_ref(&DUMMY_URL_DATA)
|
RefPtr::from_ptr_ref(&DUMMY_URL_DATA)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_shared_context<'a>(guard: &'a SharedRwLockReadGuard,
|
fn create_shared_context<'a>(global_style_data: &GlobalStyleData,
|
||||||
|
guard: &'a SharedRwLockReadGuard,
|
||||||
per_doc_data: &PerDocumentStyleDataImpl,
|
per_doc_data: &PerDocumentStyleDataImpl,
|
||||||
traversal_flags: TraversalFlags) -> SharedStyleContext<'a> {
|
traversal_flags: TraversalFlags) -> SharedStyleContext<'a> {
|
||||||
let local_context_data =
|
let local_context_data =
|
||||||
|
@ -151,6 +152,7 @@ fn create_shared_context<'a>(guard: &'a SharedRwLockReadGuard,
|
||||||
|
|
||||||
SharedStyleContext {
|
SharedStyleContext {
|
||||||
stylist: per_doc_data.stylist.clone(),
|
stylist: per_doc_data.stylist.clone(),
|
||||||
|
options: global_style_data.options.clone(),
|
||||||
guards: StylesheetGuards::same(guard),
|
guards: StylesheetGuards::same(guard),
|
||||||
running_animations: per_doc_data.running_animations.clone(),
|
running_animations: per_doc_data.running_animations.clone(),
|
||||||
expired_animations: per_doc_data.expired_animations.clone(),
|
expired_animations: per_doc_data.expired_animations.clone(),
|
||||||
|
@ -187,7 +189,10 @@ fn traverse_subtree(element: GeckoElement, raw_data: RawServoStyleSetBorrowed,
|
||||||
|
|
||||||
let global_style_data = &*GLOBAL_STYLE_DATA;
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||||
let guard = global_style_data.shared_lock.read();
|
let guard = global_style_data.shared_lock.read();
|
||||||
let shared_style_context = create_shared_context(&guard, &per_doc_data, traversal_flags);
|
let shared_style_context = create_shared_context(&global_style_data,
|
||||||
|
&guard,
|
||||||
|
&per_doc_data,
|
||||||
|
traversal_flags);
|
||||||
|
|
||||||
let traversal_driver = if global_style_data.style_thread_pool.is_none() {
|
let traversal_driver = if global_style_data.style_thread_pool.is_none() {
|
||||||
TraversalDriver::Sequential
|
TraversalDriver::Sequential
|
||||||
|
@ -407,8 +412,10 @@ pub extern "C" fn Servo_StyleSet_GetBaseComputedValuesForElement(raw_data: RawSe
|
||||||
let doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
let doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
||||||
let global_style_data = &*GLOBAL_STYLE_DATA;
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
||||||
let guard = global_style_data.shared_lock.read();
|
let guard = global_style_data.shared_lock.read();
|
||||||
let shared_context = &create_shared_context(&guard, &doc_data, TraversalFlags::empty());
|
let shared_context = &create_shared_context(&global_style_data,
|
||||||
|
&guard,
|
||||||
|
&doc_data,
|
||||||
|
TraversalFlags::empty());
|
||||||
let element = GeckoElement(element);
|
let element = GeckoElement(element);
|
||||||
let element_data = element.borrow_data().unwrap();
|
let element_data = element.borrow_data().unwrap();
|
||||||
let styles = element_data.styles();
|
let styles = element_data.styles();
|
||||||
|
@ -1691,7 +1698,10 @@ pub extern "C" fn Servo_ResolveStyleLazily(element: RawGeckoElementBorrowed,
|
||||||
}
|
}
|
||||||
|
|
||||||
// We don't have the style ready. Go ahead and compute it as necessary.
|
// We don't have the style ready. Go ahead and compute it as necessary.
|
||||||
let shared = create_shared_context(&guard, &mut doc_data.borrow_mut(), TraversalFlags::empty());
|
let shared = create_shared_context(&global_style_data,
|
||||||
|
&guard,
|
||||||
|
&mut doc_data.borrow_mut(),
|
||||||
|
TraversalFlags::empty());
|
||||||
let mut tlc = ThreadLocalStyleContext::new(&shared);
|
let mut tlc = ThreadLocalStyleContext::new(&shared);
|
||||||
let mut context = StyleContext {
|
let mut context = StyleContext {
|
||||||
shared: &shared,
|
shared: &shared,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче