From c34c92e904c69012fffbf5ad988aa640cbe75145 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Wed, 23 Aug 2017 20:04:11 +0800 Subject: [PATCH] style: Add a TLS-based style struct caching mechanism. --- components/servo_arc/lib.rs | 6 + components/style/animation.rs | 4 +- components/style/context.rs | 5 + components/style/gecko/media_queries.rs | 4 + components/style/lib.rs | 1 + .../style/properties/computed_value_flags.rs | 3 + components/style/properties/gecko.mako.rs | 7 +- components/style/properties/helpers.mako.rs | 5 + .../style/properties/properties.mako.rs | 60 +++++++- components/style/rule_cache.rs | 143 ++++++++++++++++++ components/style/rule_tree/mod.rs | 2 +- components/style/servo/media_queries.rs | 4 + components/style/style_resolver.rs | 8 + components/style/stylesheets/viewport_rule.rs | 4 + components/style/stylist.rs | 8 + components/style/values/computed/mod.rs | 7 + components/style/values/specified/length.rs | 6 + ports/geckolib/glue.rs | 14 +- 18 files changed, 278 insertions(+), 13 deletions(-) create mode 100644 components/style/rule_cache.rs diff --git a/components/servo_arc/lib.rs b/components/servo_arc/lib.rs index 5cac8c9b9bb..9ed2801ac2c 100644 --- a/components/servo_arc/lib.rs +++ b/components/servo_arc/lib.rs @@ -122,6 +122,12 @@ impl PartialEq for NonZeroPtrMut { impl Eq for NonZeroPtrMut {} +impl Hash for NonZeroPtrMut { + fn hash(&self, state: &mut H) { + self.ptr().hash(state) + } +} + pub struct Arc { p: NonZeroPtrMut>, } diff --git a/components/style/animation.rs b/components/style/animation.rs index 4dbb7b6474e..e29236186c7 100644 --- a/components/style/animation.rs +++ b/components/style/animation.rs @@ -502,7 +502,9 @@ fn compute_style_for_animation_step(context: &SharedStyleContext, /* visited_style = */ None, font_metrics_provider, CascadeFlags::empty(), - context.quirks_mode()); + context.quirks_mode(), + /* rule_cache = */ None, + &mut Default::default()); computed } } diff --git a/components/style/context.rs b/components/style/context.rs index b94f7049129..88cf90c33e6 100644 --- a/components/style/context.rs +++ b/components/style/context.rs @@ -20,6 +20,7 @@ use parallel::{STACK_SAFETY_MARGIN_KB, STYLE_THREAD_STACK_SIZE_KB}; #[cfg(feature = "servo")] use parking_lot::RwLock; use properties::ComputedValues; #[cfg(feature = "servo")] use properties::PropertyId; +use rule_cache::RuleCache; use rule_tree::StrongRuleNode; use selector_parser::{EAGER_PSEUDO_COUNT, SnapshotMap}; use selectors::matching::ElementSelectorFlags; @@ -685,6 +686,8 @@ impl StackLimitChecker { pub struct ThreadLocalStyleContext { /// A cache to share style among siblings. pub sharing_cache: StyleSharingCache, + /// A cache from matched properties to elements that match those. + pub rule_cache: RuleCache, /// The bloom filter used to fast-reject selector-matching. pub bloom_filter: StyleBloom, /// A channel on which new animations that have been triggered by style @@ -722,6 +725,7 @@ impl ThreadLocalStyleContext { pub fn new(shared: &SharedStyleContext) -> Self { ThreadLocalStyleContext { sharing_cache: StyleSharingCache::new(), + rule_cache: RuleCache::new(), bloom_filter: StyleBloom::new(), new_animations_sender: shared.local_context_creation_data.lock().unwrap().new_animations_sender.clone(), tasks: SequentialTaskList(Vec::new()), @@ -739,6 +743,7 @@ impl ThreadLocalStyleContext { pub fn new(shared: &SharedStyleContext) -> Self { ThreadLocalStyleContext { sharing_cache: StyleSharingCache::new(), + rule_cache: RuleCache::new(), bloom_filter: StyleBloom::new(), tasks: SequentialTaskList(Vec::new()), selector_flags: SelectorFlagsMap::new(), diff --git a/components/style/gecko/media_queries.rs b/components/style/gecko/media_queries.rs index 1f9a5585fcb..52983c76287 100644 --- a/components/style/gecko/media_queries.rs +++ b/components/style/gecko/media_queries.rs @@ -23,7 +23,9 @@ use media_queries::MediaType; use parser::ParserContext; use properties::{ComputedValues, StyleBuilder}; use properties::longhands::font_size; +use rule_cache::RuleCacheConditions; use servo_arc::Arc; +use std::cell::RefCell; use std::fmt::{self, Write}; use std::sync::atomic::{AtomicBool, AtomicIsize, Ordering}; use str::starts_with_ignore_ascii_case; @@ -694,6 +696,7 @@ impl Expression { // http://dev.w3.org/csswg/mediaqueries3/#units // em units are relative to the initial font-size. + let mut conditions = RuleCacheConditions::default(); let context = computed::Context { is_root_element: false, builder: StyleBuilder::for_derived_style(device, default_values, None, None), @@ -703,6 +706,7 @@ impl Expression { // TODO: pass the correct value here. quirks_mode: quirks_mode, for_smil_animation: false, + rule_cache_conditions: RefCell::new(&mut conditions), }; let required_value = match self.value { diff --git a/components/style/lib.rs b/components/style/lib.rs index 8aa3ce9507a..5ae4f1633a6 100644 --- a/components/style/lib.rs +++ b/components/style/lib.rs @@ -124,6 +124,7 @@ pub mod matching; pub mod media_queries; pub mod parallel; pub mod parser; +pub mod rule_cache; pub mod rule_tree; pub mod scoped_tls; pub mod selector_map; diff --git a/components/style/properties/computed_value_flags.rs b/components/style/properties/computed_value_flags.rs index 3ee32cd89de..0e5e5ecd266 100644 --- a/components/style/properties/computed_value_flags.rs +++ b/components/style/properties/computed_value_flags.rs @@ -59,5 +59,8 @@ bitflags! { /// Whether the child explicitly inherits any reset property. const INHERITS_RESET_STYLE = 1 << 8, + + /// A flag to mark a style which is a visited style. + const IS_STYLE_IF_VISITED = 1 << 9, } } diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 965bf955127..3a046010f15 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -52,7 +52,7 @@ use gecko::values::round_border_to_device_pixels; use logical_geometry::WritingMode; use media_queries::Device; use properties::animated_properties::TransitionProperty; -use properties::computed_value_flags::ComputedValueFlags; +use properties::computed_value_flags::*; use properties::{default_font_size_keyword, longhands, FontComputationData, Importance, LonghandId}; use properties::{PropertyDeclaration, PropertyDeclarationBlock, PropertyDeclarationId}; use rule_tree::StrongRuleNode; @@ -259,6 +259,11 @@ impl ops::DerefMut for ComputedValues { } impl ComputedValuesInner { + /// Whether we're a visited style. + pub fn is_style_if_visited(&self) -> bool { + self.flags.contains(IS_STYLE_IF_VISITED) + } + #[inline] pub fn is_display_contents(&self) -> bool { self.get_box().clone_display() == longhands::display::computed_value::T::contents diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs index 3e24a08103b..4db6053375f 100644 --- a/components/style/properties/helpers.mako.rs +++ b/components/style/properties/helpers.mako.rs @@ -322,6 +322,10 @@ longhands::system_font::resolve_system_font(sf, context); } % endif + % if property.logical: + context.rule_cache_conditions.borrow_mut() + .set_writing_mode_dependency(context.builder.writing_mode); + % endif % if property.is_vector: // In the case of a vector property we want to pass // down an iterator so that this can be computed @@ -363,6 +367,7 @@ CSSWideKeyword::Unset | % endif CSSWideKeyword::Initial => { + context.rule_cache_conditions.borrow_mut().set_uncacheable(); % if property.ident == "font_size": longhands::font_size::cascade_initial_font_size(context); % else: diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index 44da289ca0f..abe972ef4b2 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -16,6 +16,7 @@ use smallbitvec::SmallBitVec; use std::borrow::Cow; use hash::HashSet; use std::{fmt, mem, ops}; +use std::cell::RefCell; #[cfg(feature = "gecko")] use std::ptr; #[cfg(feature = "servo")] use cssparser::RGBA; @@ -34,6 +35,7 @@ use media_queries::Device; use parser::ParserContext; use properties::animated_properties::AnimatableLonghand; #[cfg(feature = "gecko")] use properties::longhands::system_font::SystemFont; +use rule_cache::{RuleCache, RuleCacheConditions}; use selector_parser::PseudoElement; use selectors::parser::SelectorParseError; #[cfg(feature = "servo")] use servo_config::prefs::PREFS; @@ -46,7 +48,7 @@ use values::generics::text::LineHeight; use values::computed; use values::computed::NonNegativeLength; use rule_tree::{CascadeLevel, StrongRuleNode}; -use self::computed_value_flags::ComputedValueFlags; +use self::computed_value_flags::*; use style_adjuster::StyleAdjuster; #[cfg(feature = "servo")] use values::specified::BorderStyle; @@ -2156,6 +2158,11 @@ impl ComputedValuesInner { /// Servo for obvious reasons. pub fn has_moz_binding(&self) -> bool { false } + /// Whether we're a visited style. + pub fn is_style_if_visited(&self) -> bool { + self.flags.contains(IS_STYLE_IF_VISITED) + } + /// Returns whether this style's display value is equal to contents. /// /// Since this isn't supported in Servo, this is always false for Servo. @@ -2558,7 +2565,7 @@ pub struct StyleBuilder<'a> { /// The rule node representing the ordered list of rules matched for this /// node. - rules: Option, + pub rules: Option, custom_properties: Option>, @@ -2594,7 +2601,7 @@ impl<'a> StyleBuilder<'a> { custom_properties: Option>, writing_mode: WritingMode, font_size_keyword: FontComputationData, - flags: ComputedValueFlags, + mut flags: ComputedValueFlags, visited_style: Option>, ) -> Self { debug_assert_eq!(parent_style.is_some(), parent_style_ignoring_first_line.is_some()); @@ -2616,6 +2623,10 @@ impl<'a> StyleBuilder<'a> { reset_style }; + if cascade_flags.contains(VISITED_DEPENDENT_ONLY) { + flags.insert(IS_STYLE_IF_VISITED); + } + StyleBuilder { device, parent_style, @@ -2639,6 +2650,11 @@ impl<'a> StyleBuilder<'a> { } } + /// Whether we're a visited style. + pub fn is_style_if_visited(&self) -> bool { + self.flags.contains(IS_STYLE_IF_VISITED) + } + /// Creates a StyleBuilder holding only references to the structs of `s`, in /// order to create a derived style. pub fn for_derived_style( @@ -2674,6 +2690,16 @@ impl<'a> StyleBuilder<'a> { } } + /// Copy the reset properties from `style`. + pub fn copy_reset_from(&mut self, style: &'a ComputedValues) { + % for style_struct in data.active_style_structs(): + % if not style_struct.inherited: + self.${style_struct.ident} = + StyleStructRef::Borrowed(style.${style_struct.name_lower}_arc()); + % endif + % endfor + } + % for property in data.longhands: % if property.ident != "font_size": /// Inherit `${property.ident}` from our parent style. @@ -2683,7 +2709,8 @@ impl<'a> StyleBuilder<'a> { % if property.style_struct.inherited: self.inherited_style.get_${property.style_struct.name_lower}(); % else: - self.inherited_style_ignoring_first_line.get_${property.style_struct.name_lower}(); + self.inherited_style_ignoring_first_line + .get_${property.style_struct.name_lower}(); % endif % if not property.style_struct.inherited: @@ -3029,7 +3056,9 @@ pub fn cascade( visited_style: Option>, font_metrics_provider: &FontMetricsProvider, flags: CascadeFlags, - quirks_mode: QuirksMode + quirks_mode: QuirksMode, + rule_cache: Option<<&RuleCache>, + rule_cache_conditions: &mut RuleCacheConditions, ) -> Arc { debug_assert_eq!(parent_style.is_some(), parent_style_ignoring_first_line.is_some()); #[cfg(feature = "gecko")] @@ -3089,6 +3118,8 @@ pub fn cascade( font_metrics_provider, flags, quirks_mode, + rule_cache, + rule_cache_conditions, ) } @@ -3107,6 +3138,8 @@ pub fn apply_declarations<'a, F, I>( font_metrics_provider: &FontMetricsProvider, flags: CascadeFlags, quirks_mode: QuirksMode, + rule_cache: Option<<&RuleCache>, + rule_cache_conditions: &mut RuleCacheConditions, ) -> Arc where F: Fn() -> I, @@ -3163,11 +3196,12 @@ where ComputedValueFlags::empty(), visited_style, ), - font_metrics_provider: font_metrics_provider, cached_system_font: None, in_media_query: false, - quirks_mode: quirks_mode, for_smil_animation: false, + font_metrics_provider, + quirks_mode, + rule_cache_conditions: RefCell::new(rule_cache_conditions), }; let ignore_colors = !device.use_document_colors(); @@ -3190,6 +3224,7 @@ where // // To improve i-cache behavior, we outline the individual functions and use // virtual dispatch instead. + let mut apply_reset = true; % for category_to_cascade_now in ["early", "other"]: % if category_to_cascade_now == "early": // Pull these out so that we can compute them in a specific order @@ -3222,6 +3257,10 @@ where continue } + if !apply_reset && !longhand_id.inherited() { + continue; + } + // When document colors are disabled, skip properties that are // marked as ignored in that mode, if they come from a UA or // user style sheet. @@ -3389,7 +3428,12 @@ where (CASCADE_PROPERTY[discriminant])(&size, &mut context); % endif } - % endif + + if let Some(style) = rule_cache.and_then(|c| c.find(&context.builder)) { + context.builder.copy_reset_from(style); + apply_reset = false; + } + % endif // category == "early" % endfor let mut builder = context.builder; diff --git a/components/style/rule_cache.rs b/components/style/rule_cache.rs new file mode 100644 index 00000000000..511c7301fba --- /dev/null +++ b/components/style/rule_cache.rs @@ -0,0 +1,143 @@ +/* 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/. */ + +//! A cache from rule node to computed values, in order to cache reset +//! properties. + +use fnv::FnvHashMap; +use logical_geometry::WritingMode; +use properties::{ComputedValues, StyleBuilder}; +use rule_tree::StrongRuleNode; +use servo_arc::Arc; +use smallvec::SmallVec; +use values::computed::NonNegativeLength; + +/// The conditions for caching and matching a style in the rule cache. +#[derive(Clone, Debug, Default)] +pub struct RuleCacheConditions { + uncacheable: bool, + font_size: Option, + writing_mode: Option, +} + +impl RuleCacheConditions { + /// Sets the style as depending in the font-size value. + pub fn set_font_size_dependency(&mut self, font_size: NonNegativeLength) { + debug_assert!(self.font_size.map_or(true, |f| f == font_size)); + self.font_size = Some(font_size); + } + + /// Sets the style as uncacheable. + pub fn set_uncacheable(&mut self) { + self.uncacheable = true; + } + + /// Sets the style as depending in the writing-mode value `writing_mode`. + pub fn set_writing_mode_dependency(&mut self, writing_mode: WritingMode) { + debug_assert!(self.writing_mode.map_or(true, |wm| wm == writing_mode)); + self.writing_mode = Some(writing_mode); + } + + /// Returns whether the current style's reset properties are cacheable. + fn cacheable(&self) -> bool { + !self.uncacheable + } + + /// Returns whether `style` matches the conditions. + fn matches(&self, style: &StyleBuilder) -> bool { + if self.uncacheable { + return false; + } + + if let Some(fs) = self.font_size { + if style.get_font().clone_font_size() != fs { + return false; + } + } + + if let Some(wm) = self.writing_mode { + if style.writing_mode != wm { + return false; + } + } + + true + } +} + +/// A TLS cache from rules matched to computed values. +pub struct RuleCache { + // FIXME(emilio): Consider using LRUCache or something like that? + map: FnvHashMap); 1]>>, +} + +impl RuleCache { + /// Creates an empty `RuleCache`. + pub fn new() -> Self { + Self { + map: FnvHashMap::default(), + } + } + + /// Finds a node in the properties matched cache. + /// + /// This needs to receive a `StyleBuilder` with the `early` properties + /// already applied. + pub fn find( + &self, + builder_with_early_props: &StyleBuilder, + ) -> Option<&ComputedValues> { + if builder_with_early_props.is_style_if_visited() { + // FIXME(emilio): We can probably do better, does it matter much? + return None; + } + + let rules = match builder_with_early_props.rules { + Some(ref rules) => rules, + None => return None, + }; + + self.map.get(rules).and_then(|cached_values| { + for &(ref conditions, ref values) in cached_values.iter() { + if conditions.matches(builder_with_early_props) { + debug!("Using cached reset style with conditions {:?}", conditions); + return Some(&**values) + } + } + None + }) + } + + /// Inserts a node into the rules cache if possible. + /// + /// Returns whether the style was inserted into the cache. + pub fn insert_if_possible( + &mut self, + style: &Arc, + conditions: &RuleCacheConditions, + ) -> bool { + if !conditions.cacheable() { + return false; + } + + if style.is_style_if_visited() { + // FIXME(emilio): We can probably do better, does it matter much? + return false; + } + + let rules = match style.rules { + Some(ref r) => r.clone(), + None => return false, + }; + + debug!("Inserting cached reset style with conditions {:?}", conditions); + self.map + .entry(rules) + .or_insert_with(SmallVec::new) + .push((conditions.clone(), style.clone())); + + true + } + +} diff --git a/components/style/rule_tree/mod.rs b/components/style/rule_tree/mod.rs index 81e51ecc5e1..51d70913e66 100644 --- a/components/style/rule_tree/mod.rs +++ b/components/style/rule_tree/mod.rs @@ -819,7 +819,7 @@ struct WeakRuleNode { } /// A strong reference to a rule node. -#[derive(Debug, PartialEq)] +#[derive(Debug, Eq, Hash, PartialEq)] pub struct StrongRuleNode { p: NonZeroPtrMut, } diff --git a/components/style/servo/media_queries.rs b/components/style/servo/media_queries.rs index dff545e1746..fcd0c04c863 100644 --- a/components/style/servo/media_queries.rs +++ b/components/style/servo/media_queries.rs @@ -13,7 +13,9 @@ use media_queries::MediaType; use parser::ParserContext; use properties::{ComputedValues, StyleBuilder}; use properties::longhands::font_size; +use rule_cache::RuleCacheConditions; use selectors::parser::SelectorParseError; +use std::cell::RefCell; use std::fmt; use std::sync::atomic::{AtomicBool, AtomicIsize, Ordering}; use style_traits::{CSSPixel, DevicePixel, ToCss, ParseError}; @@ -244,6 +246,7 @@ pub enum Range { impl Range { fn to_computed_range(&self, device: &Device, quirks_mode: QuirksMode) -> Range { let default_values = device.default_computed_values(); + let mut conditions = RuleCacheConditions::default(); // http://dev.w3.org/csswg/mediaqueries3/#units // em units are relative to the initial font-size. let context = computed::Context { @@ -257,6 +260,7 @@ impl Range { cached_system_font: None, quirks_mode: quirks_mode, for_smil_animation: false, + rule_cache_conditions: RefCell::new(&mut conditions), }; match *self { diff --git a/components/style/style_resolver.rs b/components/style/style_resolver.rs index f236d9dfb1f..8830fd1a45a 100644 --- a/components/style/style_resolver.rs +++ b/components/style/style_resolver.rs @@ -574,6 +574,7 @@ where } let implemented_pseudo = self.element.implemented_pseudo_element(); + let mut conditions = Default::default(); let values = cascade( self.context.shared.stylist.device(), @@ -587,8 +588,15 @@ where &self.context.thread_local.font_metrics_provider, cascade_flags, self.context.shared.quirks_mode(), + Some(&self.context.thread_local.rule_cache), + &mut conditions, ); + self.context + .thread_local + .rule_cache + .insert_if_possible(&values, &conditions); + values } } diff --git a/components/style/stylesheets/viewport_rule.rs b/components/style/stylesheets/viewport_rule.rs index a3dd8183e0a..89952d46a66 100644 --- a/components/style/stylesheets/viewport_rule.rs +++ b/components/style/stylesheets/viewport_rule.rs @@ -17,10 +17,12 @@ use font_metrics::get_metrics_provider_for_product; use media_queries::Device; use parser::{ParserContext, ParserErrorContext}; use properties::StyleBuilder; +use rule_cache::RuleCacheConditions; use selectors::parser::SelectorParseError; use shared_lock::{SharedRwLockReadGuard, ToCssWithGuard}; use std::ascii::AsciiExt; use std::borrow::Cow; +use std::cell::RefCell; use std::fmt; use std::iter::Enumerate; use std::str::Chars; @@ -707,6 +709,7 @@ impl MaybeNew for ViewportConstraints { let default_values = device.default_computed_values(); + let mut conditions = RuleCacheConditions::default(); let context = Context { is_root_element: false, builder: StyleBuilder::for_derived_style(device, default_values, None, None), @@ -715,6 +718,7 @@ impl MaybeNew for ViewportConstraints { in_media_query: false, quirks_mode: quirks_mode, for_smil_animation: false, + rule_cache_conditions: RefCell::new(&mut conditions), }; // DEVICE-ADAPT ยง 9.3 Resolving 'extend-to-zoom' diff --git a/components/style/stylist.rs b/components/style/stylist.rs index 5027889a453..d5ae300bb88 100644 --- a/components/style/stylist.rs +++ b/components/style/stylist.rs @@ -771,6 +771,8 @@ impl Stylist { font_metrics, cascade_flags, self.quirks_mode, + /* rule_cache = */ None, + &mut Default::default(), ) } @@ -987,6 +989,8 @@ impl Stylist { font_metrics, cascade_flags, self.quirks_mode, + /* rule_cache = */ None, + &mut Default::default(), )) } else { None @@ -1012,6 +1016,8 @@ impl Stylist { font_metrics, cascade_flags, self.quirks_mode, + /* rule_cache = */ None, + &mut Default::default(), ) } @@ -1625,6 +1631,8 @@ impl Stylist { &metrics, CascadeFlags::empty(), self.quirks_mode, + /* rule_cache = */ None, + &mut Default::default(), ) } diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index a6c828b14b8..14a5eab86d3 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -12,9 +12,11 @@ use media_queries::Device; #[cfg(feature = "gecko")] use properties; use properties::{ComputedValues, StyleBuilder}; +use rule_cache::RuleCacheConditions; #[cfg(feature = "servo")] use servo_url::ServoUrl; use std::{f32, fmt}; +use std::cell::RefCell; #[cfg(feature = "servo")] use std::sync::Arc; use style_traits::ToCss; @@ -116,6 +118,11 @@ pub struct Context<'a> { /// This is used to allow certain properties to generate out-of-range /// values, which SMIL allows. pub for_smil_animation: bool, + + /// The conditions to cache a rule node on the rule cache. + /// + /// FIXME(emilio): Drop the refcell. + pub rule_cache_conditions: RefCell<&'a mut RuleCacheConditions>, } impl<'a> Context<'a> { diff --git a/components/style/values/specified/length.rs b/components/style/values/specified/length.rs index 33bad5d90cc..be051c6f9c4 100644 --- a/components/style/values/specified/length.rs +++ b/components/style/values/specified/length.rs @@ -131,6 +131,12 @@ impl FontRelativeLength { match *self { FontRelativeLength::Em(length) => { + if !matches!(base_size, FontBaseSize::InheritedStyle) { + context.rule_cache_conditions.borrow_mut() + .set_font_size_dependency( + reference_font_size.into() + ); + } (reference_font_size, length) }, FontRelativeLength::Ex(length) => { diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index ad1209dd287..3c8b4d37ab9 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -9,6 +9,7 @@ use malloc_size_of::MallocSizeOfOps; use selectors::Element; use selectors::matching::{MatchingContext, MatchingMode, matches_selector}; use servo_arc::{Arc, ArcBorrow, RawOffsetArc}; +use std::cell::RefCell; use std::env; use std::fmt::Write; use std::iter; @@ -116,6 +117,7 @@ use style::properties::PROHIBIT_DISPLAY_CONTENTS; use style::properties::animated_properties::{AnimatableLonghand, AnimationValue}; use style::properties::animated_properties::compare_property_priority; use style::properties::parse_one_declaration_into; +use style::rule_cache::RuleCacheConditions; use style::rule_tree::{CascadeLevel, StyleSource}; use style::selector_parser::PseudoElementCascadeType; use style::shared_lock::{SharedRwLockReadGuard, StylesheetGuards, ToCssWithGuard, Locked}; @@ -3186,6 +3188,7 @@ fn create_context<'a>( parent_style: Option<&'a ComputedValues>, pseudo: Option<&'a PseudoElement>, for_smil_animation: bool, + rule_cache_conditions: &'a mut RuleCacheConditions, ) -> Context<'a> { Context { is_root_element: false, @@ -3200,6 +3203,7 @@ fn create_context<'a>( in_media_query: false, quirks_mode: per_doc_data.stylist.quirks_mode(), for_smil_animation, + rule_cache_conditions: RefCell::new(rule_cache_conditions), } } @@ -3269,6 +3273,7 @@ pub extern "C" fn Servo_GetComputedKeyframeValues(keyframes: RawGeckoKeyframeLis let parent_style = parent_data.as_ref().map(|d| d.styles.primary()).map(|x| &**x); let pseudo = style.pseudo(); + let mut conditions = Default::default(); let mut context = create_context( &data, &metrics, @@ -3276,6 +3281,7 @@ pub extern "C" fn Servo_GetComputedKeyframeValues(keyframes: RawGeckoKeyframeLis parent_style, pseudo.as_ref(), /* for_smil_animation = */ false, + &mut conditions, ); let global_style_data = &*GLOBAL_STYLE_DATA; @@ -3356,13 +3362,15 @@ pub extern "C" fn Servo_GetAnimationValues(declarations: RawServoDeclarationBloc let parent_style = parent_data.as_ref().map(|d| d.styles.primary()).map(|x| &**x); let pseudo = style.pseudo(); + let mut conditions = Default::default(); let mut context = create_context( &data, &metrics, &style, parent_style, pseudo.as_ref(), - /* for_smil_animation = */ true + /* for_smil_animation = */ true, + &mut conditions, ); let default_values = data.default_computed_values(); @@ -3392,13 +3400,15 @@ pub extern "C" fn Servo_AnimationValue_Compute(element: RawGeckoElementBorrowed, let parent_style = parent_data.as_ref().map(|d| d.styles.primary()).map(|x| &**x); let pseudo = style.pseudo(); + let mut conditions = Default::default(); let mut context = create_context( &data, &metrics, style, parent_style, pseudo.as_ref(), - /* for_smil_animation = */ false + /* for_smil_animation = */ false, + &mut conditions, ); let default_values = data.default_computed_values();