Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Skip rule node which contains only inherited properties for rule cache #19696

Merged
merged 1 commit into from Jan 5, 2018
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -485,6 +485,7 @@ fn compute_style_for_animation_step(context: &SharedStyleContext,
properties::apply_declarations(context.stylist.device(),
/* pseudo = */ None,
previous_style.rules(),
&context.guards,
iter,
Some(previous_style),
Some(previous_style),
@@ -283,6 +283,12 @@ impl PropertyDeclarationBlock {
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.
///
/// NOTE: This is linear time.
@@ -309,6 +309,16 @@ impl LonghandIdSet {
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
#[inline]
pub fn new() -> LonghandIdSet {
@@ -322,6 +332,13 @@ impl LonghandIdSet {
(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
#[inline]
pub fn insert(&mut self, id: LonghandId) {
@@ -3165,6 +3182,7 @@ pub fn cascade(
device,
pseudo,
rule_node,
guards,
iter_declarations,
parent_style,
parent_style_ignoring_first_line,
@@ -3184,6 +3202,7 @@ pub fn apply_declarations<'a, F, I>(
device: &Device,
pseudo: Option<<&PseudoElement>,
rules: &StrongRuleNode,
guards: &StylesheetGuards,
iter_declarations: F,
parent_style: Option<<&ComputedValues>,
parent_style_ignoring_first_line: Option<<&ComputedValues>,
@@ -3486,7 +3505,7 @@ where
% 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);
apply_reset = false;
}
@@ -8,9 +8,10 @@
use fnv::FnvHashMap;
use logical_geometry::WritingMode;
use properties::{ComputedValues, StyleBuilder};
use rule_tree::StrongRuleNode;
use rule_tree::{StrongRuleNode, StyleSource};
use selector_parser::PseudoElement;
use servo_arc::Arc;
use shared_lock::StylesheetGuards;
use smallvec::SmallVec;
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.
///
/// This needs to receive a `StyleBuilder` with the `early` properties
/// already applied.
pub fn find(
&self,
guards: &StylesheetGuards,
builder_with_early_props: &StyleBuilder,
) -> Option<&ComputedValues> {
if builder_with_early_props.is_style_if_visited() {
@@ -102,7 +135,8 @@ impl RuleCache {
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)?;

for &(ref conditions, ref values) in cached_values.iter() {
@@ -119,6 +153,7 @@ impl RuleCache {
/// Returns whether the style was inserted into the cache.
pub fn insert_if_possible(
&mut self,
guards: &StylesheetGuards,
style: &Arc<ComputedValues>,
pseudo: Option<&PseudoElement>,
conditions: &RuleCacheConditions,
@@ -138,8 +173,9 @@ impl RuleCache {
return false;
}

let rules = match style.rules {
Some(ref r) => r.clone(),
let rules = style.rules.as_ref();
let rules = match Self::get_rule_node_for_cache(guards, rules) {
Some(r) => r.clone(),
None => return false,
};

@@ -864,7 +864,8 @@ impl StrongRuleNode {
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()
}

@@ -597,7 +597,12 @@ where
self.context
.thread_local
.rule_cache
.insert_if_possible(&values, pseudo, &conditions);
.insert_if_possible(
&self.context.shared.guards,
&values,
pseudo,
&conditions
);

values
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.