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

Speed up stylist rebuilds #16659

Merged
merged 5 commits into from Apr 30, 2017
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Factor out the various things stylist does per-selector into helpers.

This makes things more readable, and easier to profile (since the Gecko
profiler doesn't have any intra-function granularity, so I tend to make
helpers non-inline when drilling down into what's expensive).

It allows us to iterate the selector list once, which could help cache locality
for rules with many selectors.

MozReview-Commit-ID: GdFtgrbYCIu
  • Loading branch information
bholley committed Apr 29, 2017
commit 080ff126b57248898422b1118f3776863b047aef
@@ -313,38 +313,13 @@ impl Stylist {
CssRule::Style(ref locked) => {
let style_rule = locked.read_with(&guard);
self.num_declarations += style_rule.block.read_with(&guard).len();

for selector in &style_rule.selectors.0 {
self.num_selectors += 1;
let map = if let Some(ref pseudo) = selector.pseudo_element {
self.pseudos_map
.entry(pseudo.clone())
.or_insert_with(PerPseudoElementSelectorMap::new)
.borrow_for_origin(&stylesheet.origin)
} else {
self.element_map.borrow_for_origin(&stylesheet.origin)
};

map.insert(Rule::new(guard,
selector.inner.clone(),
locked.clone(),
self.rules_source_order,
selector.specificity));
}
self.rules_source_order += 1;

for selector in &style_rule.selectors.0 {
self.add_rule_to_map(guard, selector, locked, stylesheet);
self.dependencies.note_selector(selector);

if needs_revalidation(selector) {
// For revalidation, we can skip everything left of
// the first ancestor combinator.
let revalidation_sel =
selector.inner.slice_to_first_ancestor_combinator();

self.selectors_for_cache_revalidation.push(revalidation_sel);
}
self.note_for_revalidation(selector);
}
self.rules_source_order += 1;
}
CssRule::Import(ref import) => {
let import = import.read_with(guard);
@@ -374,6 +349,38 @@ impl Stylist {
});
}

#[inline]
fn add_rule_to_map(&mut self,
guard: &SharedRwLockReadGuard,
selector: &Selector<SelectorImpl>,
rule: &Arc<Locked<StyleRule>>,
stylesheet: &Stylesheet)
{
let map = if let Some(ref pseudo) = selector.pseudo_element {
self.pseudos_map
.entry(pseudo.clone())
.or_insert_with(PerPseudoElementSelectorMap::new)
.borrow_for_origin(&stylesheet.origin)
} else {
self.element_map.borrow_for_origin(&stylesheet.origin)
};

map.insert(Rule::new(guard,
selector.inner.clone(),
rule.clone(),
self.rules_source_order,
selector.specificity));
}

#[inline]
fn note_for_revalidation(&mut self, selector: &Selector<SelectorImpl>) {
if needs_revalidation(selector) {
// For revalidation, we can skip everything left of the first ancestor
// combinator.
let revalidation_sel = selector.inner.slice_to_first_ancestor_combinator();
self.selectors_for_cache_revalidation.push(revalidation_sel);
}
}

/// Computes the style for a given "precomputed" pseudo-element, taking the
/// universal rules and applying them.
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.