Lazily compute common style affecting attribute info.

This commit is contained in:
Emilio Cobos Álvarez 2016-08-11 16:44:21 -07:00
parent 51b6568273
commit a46f0c3b24
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
2 changed files with 26 additions and 16 deletions

View file

@ -7,7 +7,7 @@
use rand; use rand;
use rand::Rng; use rand::Rng;
use std::hash::{Hash, Hasher, SipHasher}; use std::hash::{Hash, Hasher, SipHasher};
use std::slice::Iter; use std::slice::{Iter, IterMut};
pub struct LRUCache<K, V> { pub struct LRUCache<K, V> {
entries: Vec<(K, V)>, entries: Vec<(K, V)>,
@ -17,7 +17,7 @@ pub struct LRUCache<K, V> {
impl<K: PartialEq, V: Clone> LRUCache<K, V> { impl<K: PartialEq, V: Clone> LRUCache<K, V> {
pub fn new(size: usize) -> LRUCache<K, V> { pub fn new(size: usize) -> LRUCache<K, V> {
LRUCache { LRUCache {
entries: vec!(), entries: vec![],
cache_size: size, cache_size: size,
} }
} }
@ -36,6 +36,10 @@ impl<K: PartialEq, V: Clone> LRUCache<K, V> {
self.entries.iter() self.entries.iter()
} }
pub fn iter_mut(&mut self) -> IterMut<(K, V)> {
self.entries.iter_mut()
}
pub fn insert(&mut self, key: K, val: V) { pub fn insert(&mut self, key: K, val: V) {
if self.entries.len() == self.cache_size { if self.entries.len() == self.cache_size {
self.entries.remove(0); self.entries.remove(0);

View file

@ -24,7 +24,7 @@ use sink::ForgetfulSink;
use smallvec::SmallVec; use smallvec::SmallVec;
use std::collections::HashMap; use std::collections::HashMap;
use std::hash::{BuildHasherDefault, Hash, Hasher}; use std::hash::{BuildHasherDefault, Hash, Hasher};
use std::slice::Iter; use std::slice::IterMut;
use std::sync::Arc; use std::sync::Arc;
use string_cache::Atom; use string_cache::Atom;
use traversal::RestyleResult; use traversal::RestyleResult;
@ -188,7 +188,7 @@ struct StyleSharingCandidate {
/// The cached computed style, here for convenience. /// The cached computed style, here for convenience.
style: Arc<ComputedValues>, style: Arc<ComputedValues>,
/// The cached common style affecting attribute info. /// The cached common style affecting attribute info.
common_style_affecting_attributes: CommonStyleAffectingAttributes, common_style_affecting_attributes: Option<CommonStyleAffectingAttributes>,
} }
impl PartialEq<StyleSharingCandidate> for StyleSharingCandidate { impl PartialEq<StyleSharingCandidate> for StyleSharingCandidate {
@ -230,7 +230,7 @@ pub enum CacheMiss {
} }
fn element_matches_candidate<E: TElement>(element: &E, fn element_matches_candidate<E: TElement>(element: &E,
candidate: &StyleSharingCandidate, candidate: &mut StyleSharingCandidate,
candidate_element: &E, candidate_element: &E,
shared_context: &SharedStyleContext) shared_context: &SharedStyleContext)
-> Result<Arc<ComputedValues>, CacheMiss> { -> Result<Arc<ComputedValues>, CacheMiss> {
@ -272,7 +272,9 @@ fn element_matches_candidate<E: TElement>(element: &E,
miss!(Class) miss!(Class)
} }
if !have_same_common_style_affecting_attributes(element, candidate) { if !have_same_common_style_affecting_attributes(element,
candidate,
candidate_element) {
miss!(CommonStyleAffectingAttributes) miss!(CommonStyleAffectingAttributes)
} }
@ -296,11 +298,14 @@ fn element_matches_candidate<E: TElement>(element: &E,
} }
fn have_same_common_style_affecting_attributes<E: TElement>(element: &E, fn have_same_common_style_affecting_attributes<E: TElement>(element: &E,
candidate: &StyleSharingCandidate) -> bool { candidate: &mut StyleSharingCandidate,
// XXX probably could do something smarter. Also, the cache should candidate_element: &E) -> bool {
// precompute this for the parent. Just experimenting now though. if candidate.common_style_affecting_attributes.is_none() {
candidate.common_style_affecting_attributes =
Some(create_common_style_affecting_attributes_from_element(candidate_element))
}
create_common_style_affecting_attributes_from_element(element) == create_common_style_affecting_attributes_from_element(element) ==
candidate.common_style_affecting_attributes candidate.common_style_affecting_attributes.unwrap()
} }
fn have_same_presentational_hints<E: TElement>(element: &E, candidate: &E) -> bool { fn have_same_presentational_hints<E: TElement>(element: &E, candidate: &E) -> bool {
@ -406,8 +411,8 @@ impl StyleSharingCandidateCache {
} }
} }
fn iter(&self) -> Iter<(StyleSharingCandidate, ())> { fn iter_mut(&mut self) -> IterMut<(StyleSharingCandidate, ())> {
self.cache.iter() self.cache.iter_mut()
} }
pub fn insert_if_possible<E: TElement>(&mut self, pub fn insert_if_possible<E: TElement>(&mut self,
@ -451,8 +456,7 @@ impl StyleSharingCandidateCache {
self.cache.insert(StyleSharingCandidate { self.cache.insert(StyleSharingCandidate {
node: node.to_unsafe(), node: node.to_unsafe(),
style: style.clone(), style: style.clone(),
common_style_affecting_attributes: common_style_affecting_attributes: None,
create_common_style_affecting_attributes_from_element(element),
}, ()); }, ());
} }
@ -620,7 +624,7 @@ trait PrivateElementMatchMethods: TElement {
fn share_style_with_candidate_if_possible(&self, fn share_style_with_candidate_if_possible(&self,
parent_node: Self::ConcreteNode, parent_node: Self::ConcreteNode,
shared_context: &SharedStyleContext, shared_context: &SharedStyleContext,
candidate: &StyleSharingCandidate) candidate: &mut StyleSharingCandidate)
-> Result<Arc<ComputedValues>, CacheMiss> { -> Result<Arc<ComputedValues>, CacheMiss> {
debug_assert!(parent_node.is_element()); debug_assert!(parent_node.is_element());
@ -697,7 +701,7 @@ pub trait ElementMatchMethods : TElement {
_ => return StyleSharingResult::CannotShare, _ => return StyleSharingResult::CannotShare,
}; };
for (i, &(ref candidate, ())) in style_sharing_candidate_cache.iter().enumerate() { for (i, &mut (ref mut candidate, ())) in style_sharing_candidate_cache.iter_mut().enumerate() {
let sharing_result = self.share_style_with_candidate_if_possible(parent, let sharing_result = self.share_style_with_candidate_if_possible(parent,
shared_context, shared_context,
candidate); candidate);
@ -734,6 +738,8 @@ pub trait ElementMatchMethods : TElement {
return StyleSharingResult::StyleWasShared(i, damage, restyle_result) return StyleSharingResult::StyleWasShared(i, damage, restyle_result)
} }
Err(miss) => { Err(miss) => {
debug!("Cache miss: {:?}", miss);
// Cache miss, let's see what kind of failure to decide // Cache miss, let's see what kind of failure to decide
// whether we keep trying or not. // whether we keep trying or not.
match miss { match miss {