Bug 1355343: Cache snapshot lookups. r=bholley

This is likely to be important at least for the initial element.

For the rest of them this is likely useless because we create them in a
throwaway fashion.

MozReview-Commit-ID: EFz9WUdB8S0
Signed-off-by: Emilio Cobos Álvarez <emilio@crisal.io>
This commit is contained in:
Emilio Cobos Álvarez 2017-05-07 02:36:19 +02:00
parent 46bf5d61f0
commit c732b0c600
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C

View file

@ -22,6 +22,7 @@ use selectors::parser::{SelectorInner, SelectorMethods};
use selectors::visitor::SelectorVisitor; use selectors::visitor::SelectorVisitor;
use smallvec::SmallVec; use smallvec::SmallVec;
use std::borrow::Borrow; use std::borrow::Borrow;
use std::cell::Cell;
use std::clone::Clone; use std::clone::Clone;
use stylist::SelectorMap; use stylist::SelectorMap;
@ -194,6 +195,7 @@ struct ElementWrapper<'a, E>
where E: TElement, where E: TElement,
{ {
element: E, element: E,
cached_snapshot: Cell<Option<&'a Snapshot>>,
snapshot_map: &'a SnapshotMap, snapshot_map: &'a SnapshotMap,
} }
@ -202,20 +204,28 @@ impl<'a, E> ElementWrapper<'a, E>
{ {
/// Trivially constructs an `ElementWrapper`. /// Trivially constructs an `ElementWrapper`.
fn new(el: E, snapshot_map: &'a SnapshotMap) -> Self { fn new(el: E, snapshot_map: &'a SnapshotMap) -> Self {
ElementWrapper { element: el, snapshot_map: snapshot_map } ElementWrapper {
element: el,
cached_snapshot: Cell::new(None),
snapshot_map: snapshot_map,
}
} }
/// Gets the snapshot associated with this element, if any. /// Gets the snapshot associated with this element, if any.
///
/// TODO(emilio): If the hash table lookup happens to appear in profiles, we
/// can cache the snapshot in a RefCell<&'a Snapshot>.
fn snapshot(&self) -> Option<&'a Snapshot> { fn snapshot(&self) -> Option<&'a Snapshot> {
if !self.element.has_snapshot() { if !self.element.has_snapshot() {
return None return None;
}
if let Some(s) = self.cached_snapshot.get() {
return Some(s);
} }
let snapshot = self.snapshot_map.get(&self.element); let snapshot = self.snapshot_map.get(&self.element);
debug_assert!(snapshot.is_some(), "has_snapshot lied!"); debug_assert!(snapshot.is_some(), "has_snapshot lied!");
self.cached_snapshot.set(snapshot);
snapshot snapshot
} }
} }