mirror of
https://github.com/servo/servo.git
synced 2025-08-05 21:50:18 +01:00
Fix the handling of the Bloom filter in the style sharing cache.
This commit is contained in:
parent
a36edb9970
commit
98f95a32da
5 changed files with 61 additions and 27 deletions
|
@ -158,6 +158,14 @@ impl<E: TElement> StyleBloom<E> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the element that represents the chain of things inserted
|
||||||
|
/// into the filter right now. That chain is the given element
|
||||||
|
/// (if any) and its ancestors.
|
||||||
|
#[inline]
|
||||||
|
pub fn current_parent(&self) -> Option<E> {
|
||||||
|
self.elements.last().map(|el| **el)
|
||||||
|
}
|
||||||
|
|
||||||
/// Insert the parents of an element in the bloom filter, trying to recover
|
/// Insert the parents of an element in the bloom filter, trying to recover
|
||||||
/// the filter if the last element inserted doesn't match.
|
/// the filter if the last element inserted doesn't match.
|
||||||
///
|
///
|
||||||
|
@ -185,7 +193,7 @@ impl<E: TElement> StyleBloom<E> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.elements.last().map(|el| **el) == Some(parent_element) {
|
if self.current_parent() == Some(parent_element) {
|
||||||
// Ta da, cache hit, we're all done.
|
// Ta da, cache hit, we're all done.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
//! quickly whether it's worth to share style, and whether two different
|
//! quickly whether it's worth to share style, and whether two different
|
||||||
//! elements can indeed share the same style.
|
//! elements can indeed share the same style.
|
||||||
|
|
||||||
|
use bloom::StyleBloom;
|
||||||
use context::{SelectorFlagsMap, SharedStyleContext};
|
use context::{SelectorFlagsMap, SharedStyleContext};
|
||||||
use dom::TElement;
|
use dom::TElement;
|
||||||
use element_state::*;
|
use element_state::*;
|
||||||
use selectors::bloom::BloomFilter;
|
|
||||||
use selectors::matching::StyleRelations;
|
use selectors::matching::StyleRelations;
|
||||||
use sharing::{StyleSharingCandidate, StyleSharingTarget};
|
use sharing::{StyleSharingCandidate, StyleSharingTarget};
|
||||||
use stylearc::Arc;
|
use stylearc::Arc;
|
||||||
|
@ -102,7 +102,7 @@ pub fn have_same_state_ignoring_visitedness<E>(element: E,
|
||||||
pub fn revalidate<E>(target: &mut StyleSharingTarget<E>,
|
pub fn revalidate<E>(target: &mut StyleSharingTarget<E>,
|
||||||
candidate: &mut StyleSharingCandidate<E>,
|
candidate: &mut StyleSharingCandidate<E>,
|
||||||
shared_context: &SharedStyleContext,
|
shared_context: &SharedStyleContext,
|
||||||
bloom: &BloomFilter,
|
bloom: &StyleBloom<E>,
|
||||||
selector_flags_map: &mut SelectorFlagsMap<E>)
|
selector_flags_map: &mut SelectorFlagsMap<E>)
|
||||||
-> bool
|
-> bool
|
||||||
where E: TElement,
|
where E: TElement,
|
||||||
|
|
|
@ -7,13 +7,13 @@
|
||||||
|
|
||||||
use Atom;
|
use Atom;
|
||||||
use bit_vec::BitVec;
|
use bit_vec::BitVec;
|
||||||
|
use bloom::StyleBloom;
|
||||||
use cache::{LRUCache, LRUCacheMutIterator};
|
use cache::{LRUCache, LRUCacheMutIterator};
|
||||||
use context::{SelectorFlagsMap, SharedStyleContext, StyleContext};
|
use context::{SelectorFlagsMap, SharedStyleContext, StyleContext};
|
||||||
use data::{ComputedStyle, ElementData, ElementStyles};
|
use data::{ComputedStyle, ElementData, ElementStyles};
|
||||||
use dom::{TElement, SendElement};
|
use dom::{TElement, SendElement};
|
||||||
use matching::{ChildCascadeRequirement, MatchMethods};
|
use matching::{ChildCascadeRequirement, MatchMethods};
|
||||||
use properties::ComputedValues;
|
use properties::ComputedValues;
|
||||||
use selectors::bloom::BloomFilter;
|
|
||||||
use selectors::matching::{ElementSelectorFlags, VisitedHandlingMode, StyleRelations};
|
use selectors::matching::{ElementSelectorFlags, VisitedHandlingMode, StyleRelations};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
@ -95,19 +95,40 @@ impl ValidationData {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computes the revalidation results if needed, and returns it.
|
/// Computes the revalidation results if needed, and returns it.
|
||||||
|
/// Inline so we know at compile time what bloom_known_valid is.
|
||||||
|
#[inline]
|
||||||
fn revalidation_match_results<E, F>(
|
fn revalidation_match_results<E, F>(
|
||||||
&mut self,
|
&mut self,
|
||||||
element: E,
|
element: E,
|
||||||
stylist: &Stylist,
|
stylist: &Stylist,
|
||||||
bloom: &BloomFilter,
|
bloom: &StyleBloom<E>,
|
||||||
|
bloom_known_valid: bool,
|
||||||
flags_setter: &mut F
|
flags_setter: &mut F
|
||||||
) -> &BitVec
|
) -> &BitVec
|
||||||
where E: TElement,
|
where E: TElement,
|
||||||
F: FnMut(&E, ElementSelectorFlags),
|
F: FnMut(&E, ElementSelectorFlags),
|
||||||
{
|
{
|
||||||
if self.revalidation_match_results.is_none() {
|
if self.revalidation_match_results.is_none() {
|
||||||
|
// The bloom filter may already be set up for our element.
|
||||||
|
// If it is, use it. If not, we must be in a candidate
|
||||||
|
// (i.e. something in the cache), and the element is one
|
||||||
|
// of our cousins, not a sibling. In that case, we'll
|
||||||
|
// just do revalidation selector matching without a bloom
|
||||||
|
// filter, to avoid thrashing the filter.
|
||||||
|
let bloom_to_use = if bloom_known_valid {
|
||||||
|
debug_assert_eq!(bloom.current_parent(),
|
||||||
|
element.parent_element());
|
||||||
|
Some(bloom.filter())
|
||||||
|
} else {
|
||||||
|
if bloom.current_parent() == element.parent_element() {
|
||||||
|
Some(bloom.filter())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
};
|
||||||
self.revalidation_match_results =
|
self.revalidation_match_results =
|
||||||
Some(stylist.match_revalidation_selectors(&element, bloom,
|
Some(stylist.match_revalidation_selectors(&element,
|
||||||
|
bloom_to_use,
|
||||||
flags_setter));
|
flags_setter));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,16 +170,18 @@ impl<E: TElement> StyleSharingCandidate<E> {
|
||||||
self.validation_data.pres_hints(*self.element)
|
self.validation_data.pres_hints(*self.element)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the classlist of this candidate.
|
/// Compute the bit vector of revalidation selector match results
|
||||||
|
/// for this candidate.
|
||||||
fn revalidation_match_results(
|
fn revalidation_match_results(
|
||||||
&mut self,
|
&mut self,
|
||||||
stylist: &Stylist,
|
stylist: &Stylist,
|
||||||
bloom: &BloomFilter,
|
bloom: &StyleBloom<E>,
|
||||||
) -> &BitVec {
|
) -> &BitVec {
|
||||||
self.validation_data.revalidation_match_results(
|
self.validation_data.revalidation_match_results(
|
||||||
*self.element,
|
*self.element,
|
||||||
stylist,
|
stylist,
|
||||||
bloom,
|
bloom,
|
||||||
|
/* bloom_known_valid = */ false,
|
||||||
&mut |_, _| {})
|
&mut |_, _| {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -204,7 +227,7 @@ impl<E: TElement> StyleSharingTarget<E> {
|
||||||
fn revalidation_match_results(
|
fn revalidation_match_results(
|
||||||
&mut self,
|
&mut self,
|
||||||
stylist: &Stylist,
|
stylist: &Stylist,
|
||||||
bloom: &BloomFilter,
|
bloom: &StyleBloom<E>,
|
||||||
selector_flags_map: &mut SelectorFlagsMap<E>
|
selector_flags_map: &mut SelectorFlagsMap<E>
|
||||||
) -> &BitVec {
|
) -> &BitVec {
|
||||||
// It's important to set the selector flags. Otherwise, if we succeed in
|
// It's important to set the selector flags. Otherwise, if we succeed in
|
||||||
|
@ -231,6 +254,7 @@ impl<E: TElement> StyleSharingTarget<E> {
|
||||||
self.element,
|
self.element,
|
||||||
stylist,
|
stylist,
|
||||||
bloom,
|
bloom,
|
||||||
|
/* bloom_known_valid = */ true,
|
||||||
&mut set_selector_flags)
|
&mut set_selector_flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,7 +267,10 @@ impl<E: TElement> StyleSharingTarget<E> {
|
||||||
{
|
{
|
||||||
let shared_context = &context.shared;
|
let shared_context = &context.shared;
|
||||||
let selector_flags_map = &mut context.thread_local.selector_flags;
|
let selector_flags_map = &mut context.thread_local.selector_flags;
|
||||||
let bloom_filter = context.thread_local.bloom_filter.filter();
|
let bloom_filter = &context.thread_local.bloom_filter;
|
||||||
|
|
||||||
|
debug_assert_eq!(bloom_filter.current_parent(),
|
||||||
|
self.element.parent_element());
|
||||||
|
|
||||||
let result = context.thread_local
|
let result = context.thread_local
|
||||||
.style_sharing_candidate_cache
|
.style_sharing_candidate_cache
|
||||||
|
@ -400,7 +427,7 @@ impl<E: TElement> StyleSharingCandidateCache<E> {
|
||||||
&mut self,
|
&mut self,
|
||||||
shared_context: &SharedStyleContext,
|
shared_context: &SharedStyleContext,
|
||||||
selector_flags_map: &mut SelectorFlagsMap<E>,
|
selector_flags_map: &mut SelectorFlagsMap<E>,
|
||||||
bloom_filter: &BloomFilter,
|
bloom_filter: &StyleBloom<E>,
|
||||||
target: &mut StyleSharingTarget<E>,
|
target: &mut StyleSharingTarget<E>,
|
||||||
data: &mut ElementData
|
data: &mut ElementData
|
||||||
) -> StyleSharingResult {
|
) -> StyleSharingResult {
|
||||||
|
@ -498,7 +525,7 @@ impl<E: TElement> StyleSharingCandidateCache<E> {
|
||||||
fn test_candidate(target: &mut StyleSharingTarget<E>,
|
fn test_candidate(target: &mut StyleSharingTarget<E>,
|
||||||
candidate: &mut StyleSharingCandidate<E>,
|
candidate: &mut StyleSharingCandidate<E>,
|
||||||
shared: &SharedStyleContext,
|
shared: &SharedStyleContext,
|
||||||
bloom: &BloomFilter,
|
bloom: &StyleBloom<E>,
|
||||||
selector_flags_map: &mut SelectorFlagsMap<E>)
|
selector_flags_map: &mut SelectorFlagsMap<E>)
|
||||||
-> Result<ComputedStyle, CacheMiss> {
|
-> Result<ComputedStyle, CacheMiss> {
|
||||||
macro_rules! miss {
|
macro_rules! miss {
|
||||||
|
|
|
@ -1092,7 +1092,7 @@ impl Stylist {
|
||||||
/// revalidation selectors.
|
/// revalidation selectors.
|
||||||
pub fn match_revalidation_selectors<E, F>(&self,
|
pub fn match_revalidation_selectors<E, F>(&self,
|
||||||
element: &E,
|
element: &E,
|
||||||
bloom: &BloomFilter,
|
bloom: Option<&BloomFilter>,
|
||||||
flags_setter: &mut F)
|
flags_setter: &mut F)
|
||||||
-> BitVec
|
-> BitVec
|
||||||
where E: TElement,
|
where E: TElement,
|
||||||
|
@ -1101,7 +1101,7 @@ impl Stylist {
|
||||||
// NB: `MatchingMode` doesn't really matter, given we don't share style
|
// NB: `MatchingMode` doesn't really matter, given we don't share style
|
||||||
// between pseudos.
|
// between pseudos.
|
||||||
let mut matching_context =
|
let mut matching_context =
|
||||||
MatchingContext::new(MatchingMode::Normal, Some(bloom));
|
MatchingContext::new(MatchingMode::Normal, bloom);
|
||||||
|
|
||||||
// Note that, by the time we're revalidating, we're guaranteed that the
|
// Note that, by the time we're revalidating, we're guaranteed that the
|
||||||
// candidate and the entry have the same id, classes, and local name.
|
// candidate and the entry have the same id, classes, and local name.
|
||||||
|
|
|
@ -799,19 +799,6 @@ fn compute_style<E, D>(_traversal: &D,
|
||||||
context.thread_local.statistics.elements_styled += 1;
|
context.thread_local.statistics.elements_styled += 1;
|
||||||
let kind = data.restyle_kind();
|
let kind = data.restyle_kind();
|
||||||
|
|
||||||
// First, try the style sharing cache. If we get a match we can skip the rest
|
|
||||||
// of the work.
|
|
||||||
if let MatchAndCascade = kind {
|
|
||||||
let target = StyleSharingTarget::new(element);
|
|
||||||
let sharing_result = target.share_style_if_possible(context, data);
|
|
||||||
|
|
||||||
if let StyleWasShared(index, had_damage) = sharing_result {
|
|
||||||
context.thread_local.statistics.styles_shared += 1;
|
|
||||||
context.thread_local.style_sharing_candidate_cache.touch(index);
|
|
||||||
return had_damage;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match kind {
|
match kind {
|
||||||
MatchAndCascade => {
|
MatchAndCascade => {
|
||||||
// Ensure the bloom filter is up to date.
|
// Ensure the bloom filter is up to date.
|
||||||
|
@ -820,6 +807,18 @@ fn compute_style<E, D>(_traversal: &D,
|
||||||
traversal_data.current_dom_depth);
|
traversal_data.current_dom_depth);
|
||||||
|
|
||||||
context.thread_local.bloom_filter.assert_complete(element);
|
context.thread_local.bloom_filter.assert_complete(element);
|
||||||
|
|
||||||
|
// Now that our bloom filter is set up, try the style sharing
|
||||||
|
// cache. If we get a match we can skip the rest of the work.
|
||||||
|
let target = StyleSharingTarget::new(element);
|
||||||
|
let sharing_result = target.share_style_if_possible(context, data);
|
||||||
|
|
||||||
|
if let StyleWasShared(index, had_damage) = sharing_result {
|
||||||
|
context.thread_local.statistics.styles_shared += 1;
|
||||||
|
context.thread_local.style_sharing_candidate_cache.touch(index);
|
||||||
|
return had_damage;
|
||||||
|
}
|
||||||
|
|
||||||
context.thread_local.statistics.elements_matched += 1;
|
context.thread_local.statistics.elements_matched += 1;
|
||||||
|
|
||||||
// Perform the matching and cascading.
|
// Perform the matching and cascading.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue