mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
Skip rule node which contains only inherited properties for rule cache.
This commit is contained in:
parent
782e3fe4e4
commit
3593392788
6 changed files with 75 additions and 7 deletions
|
@ -485,6 +485,7 @@ fn compute_style_for_animation_step(context: &SharedStyleContext,
|
||||||
properties::apply_declarations(context.stylist.device(),
|
properties::apply_declarations(context.stylist.device(),
|
||||||
/* pseudo = */ None,
|
/* pseudo = */ None,
|
||||||
previous_style.rules(),
|
previous_style.rules(),
|
||||||
|
&context.guards,
|
||||||
iter,
|
iter,
|
||||||
Some(previous_style),
|
Some(previous_style),
|
||||||
Some(previous_style),
|
Some(previous_style),
|
||||||
|
|
|
@ -283,6 +283,12 @@ impl PropertyDeclarationBlock {
|
||||||
self.longhands.contains(id)
|
self.longhands.contains(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns whether this block contains any reset longhand.
|
||||||
|
#[inline]
|
||||||
|
pub fn contains_any_reset(&self) -> bool {
|
||||||
|
self.longhands.contains_any_reset()
|
||||||
|
}
|
||||||
|
|
||||||
/// Get a declaration for a given property.
|
/// Get a declaration for a given property.
|
||||||
///
|
///
|
||||||
/// NOTE: This is linear time.
|
/// NOTE: This is linear time.
|
||||||
|
|
|
@ -309,6 +309,16 @@ impl LonghandIdSet {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns whether this set contains any longhand that `other` also contains.
|
||||||
|
pub fn contains_any(&self, other: &Self) -> bool {
|
||||||
|
for (self_cell, other_cell) in self.storage.iter().zip(other.storage.iter()) {
|
||||||
|
if (*self_cell & *other_cell) != 0 {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
/// Create an empty set
|
/// Create an empty set
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new() -> LonghandIdSet {
|
pub fn new() -> LonghandIdSet {
|
||||||
|
@ -322,6 +332,13 @@ impl LonghandIdSet {
|
||||||
(self.storage[bit / 32] & (1 << (bit % 32))) != 0
|
(self.storage[bit / 32] & (1 << (bit % 32))) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return whether this set contains any reset longhand.
|
||||||
|
#[inline]
|
||||||
|
pub fn contains_any_reset(&self) -> bool {
|
||||||
|
${static_longhand_id_set("RESET", lambda p: not p.style_struct.inherited)}
|
||||||
|
self.contains_any(&RESET)
|
||||||
|
}
|
||||||
|
|
||||||
/// Add the given property to the set
|
/// Add the given property to the set
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn insert(&mut self, id: LonghandId) {
|
pub fn insert(&mut self, id: LonghandId) {
|
||||||
|
@ -3165,6 +3182,7 @@ pub fn cascade(
|
||||||
device,
|
device,
|
||||||
pseudo,
|
pseudo,
|
||||||
rule_node,
|
rule_node,
|
||||||
|
guards,
|
||||||
iter_declarations,
|
iter_declarations,
|
||||||
parent_style,
|
parent_style,
|
||||||
parent_style_ignoring_first_line,
|
parent_style_ignoring_first_line,
|
||||||
|
@ -3184,6 +3202,7 @@ pub fn apply_declarations<'a, F, I>(
|
||||||
device: &Device,
|
device: &Device,
|
||||||
pseudo: Option<<&PseudoElement>,
|
pseudo: Option<<&PseudoElement>,
|
||||||
rules: &StrongRuleNode,
|
rules: &StrongRuleNode,
|
||||||
|
guards: &StylesheetGuards,
|
||||||
iter_declarations: F,
|
iter_declarations: F,
|
||||||
parent_style: Option<<&ComputedValues>,
|
parent_style: Option<<&ComputedValues>,
|
||||||
parent_style_ignoring_first_line: Option<<&ComputedValues>,
|
parent_style_ignoring_first_line: Option<<&ComputedValues>,
|
||||||
|
@ -3486,7 +3505,7 @@ where
|
||||||
% endif
|
% endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(style) = rule_cache.and_then(|c| c.find(&context.builder)) {
|
if let Some(style) = rule_cache.and_then(|c| c.find(guards, &context.builder)) {
|
||||||
context.builder.copy_reset_from(style);
|
context.builder.copy_reset_from(style);
|
||||||
apply_reset = false;
|
apply_reset = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,9 +8,10 @@
|
||||||
use fnv::FnvHashMap;
|
use fnv::FnvHashMap;
|
||||||
use logical_geometry::WritingMode;
|
use logical_geometry::WritingMode;
|
||||||
use properties::{ComputedValues, StyleBuilder};
|
use properties::{ComputedValues, StyleBuilder};
|
||||||
use rule_tree::StrongRuleNode;
|
use rule_tree::{StrongRuleNode, StyleSource};
|
||||||
use selector_parser::PseudoElement;
|
use selector_parser::PseudoElement;
|
||||||
use servo_arc::Arc;
|
use servo_arc::Arc;
|
||||||
|
use shared_lock::StylesheetGuards;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use values::computed::NonNegativeLength;
|
use values::computed::NonNegativeLength;
|
||||||
|
|
||||||
|
@ -81,12 +82,44 @@ impl RuleCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Walk the rule tree and return a rule node for using as the key
|
||||||
|
/// for rule cache.
|
||||||
|
///
|
||||||
|
/// It currently skips a rule node when it is neither from a style
|
||||||
|
/// rule, nor containing any declaration of reset property. We don't
|
||||||
|
/// skip style rule so that we don't need to walk a long way in the
|
||||||
|
/// worst case. Skipping declarations rule nodes should be enough
|
||||||
|
/// to address common cases that rule cache would fail to share
|
||||||
|
/// when using the rule node directly, like preshint, style attrs,
|
||||||
|
/// and animations.
|
||||||
|
fn get_rule_node_for_cache<'r>(
|
||||||
|
guards: &StylesheetGuards,
|
||||||
|
mut rule_node: Option<&'r StrongRuleNode>
|
||||||
|
) -> Option<&'r StrongRuleNode> {
|
||||||
|
while let Some(node) = rule_node {
|
||||||
|
match *node.style_source() {
|
||||||
|
StyleSource::Declarations(ref decls) => {
|
||||||
|
let cascade_level = node.cascade_level();
|
||||||
|
let decls = decls.read_with(cascade_level.guard(guards));
|
||||||
|
if decls.contains_any_reset() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
StyleSource::None => {}
|
||||||
|
StyleSource::Style(_) => break,
|
||||||
|
}
|
||||||
|
rule_node = node.parent();
|
||||||
|
}
|
||||||
|
rule_node
|
||||||
|
}
|
||||||
|
|
||||||
/// Finds a node in the properties matched cache.
|
/// Finds a node in the properties matched cache.
|
||||||
///
|
///
|
||||||
/// This needs to receive a `StyleBuilder` with the `early` properties
|
/// This needs to receive a `StyleBuilder` with the `early` properties
|
||||||
/// already applied.
|
/// already applied.
|
||||||
pub fn find(
|
pub fn find(
|
||||||
&self,
|
&self,
|
||||||
|
guards: &StylesheetGuards,
|
||||||
builder_with_early_props: &StyleBuilder,
|
builder_with_early_props: &StyleBuilder,
|
||||||
) -> Option<&ComputedValues> {
|
) -> Option<&ComputedValues> {
|
||||||
if builder_with_early_props.is_style_if_visited() {
|
if builder_with_early_props.is_style_if_visited() {
|
||||||
|
@ -102,7 +135,8 @@ impl RuleCache {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let rules = builder_with_early_props.rules.as_ref()?;
|
let rules = builder_with_early_props.rules.as_ref();
|
||||||
|
let rules = Self::get_rule_node_for_cache(guards, rules)?;
|
||||||
let cached_values = self.map.get(rules)?;
|
let cached_values = self.map.get(rules)?;
|
||||||
|
|
||||||
for &(ref conditions, ref values) in cached_values.iter() {
|
for &(ref conditions, ref values) in cached_values.iter() {
|
||||||
|
@ -119,6 +153,7 @@ impl RuleCache {
|
||||||
/// Returns whether the style was inserted into the cache.
|
/// Returns whether the style was inserted into the cache.
|
||||||
pub fn insert_if_possible(
|
pub fn insert_if_possible(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
guards: &StylesheetGuards,
|
||||||
style: &Arc<ComputedValues>,
|
style: &Arc<ComputedValues>,
|
||||||
pseudo: Option<&PseudoElement>,
|
pseudo: Option<&PseudoElement>,
|
||||||
conditions: &RuleCacheConditions,
|
conditions: &RuleCacheConditions,
|
||||||
|
@ -138,8 +173,9 @@ impl RuleCache {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
let rules = match style.rules {
|
let rules = style.rules.as_ref();
|
||||||
Some(ref r) => r.clone(),
|
let rules = match Self::get_rule_node_for_cache(guards, rules) {
|
||||||
|
Some(r) => r.clone(),
|
||||||
None => return false,
|
None => return false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -864,7 +864,8 @@ impl StrongRuleNode {
|
||||||
WeakRuleNode::from_ptr(self.ptr())
|
WeakRuleNode::from_ptr(self.ptr())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parent(&self) -> Option<&StrongRuleNode> {
|
/// Get the parent rule node of this rule node.
|
||||||
|
pub fn parent(&self) -> Option<&StrongRuleNode> {
|
||||||
self.get().parent.as_ref()
|
self.get().parent.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -597,7 +597,12 @@ where
|
||||||
self.context
|
self.context
|
||||||
.thread_local
|
.thread_local
|
||||||
.rule_cache
|
.rule_cache
|
||||||
.insert_if_possible(&values, pseudo, &conditions);
|
.insert_if_possible(
|
||||||
|
&self.context.shared.guards,
|
||||||
|
&values,
|
||||||
|
pseudo,
|
||||||
|
&conditions
|
||||||
|
);
|
||||||
|
|
||||||
values
|
values
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue