style: Allow sharing style for elements with presentational hints.

This commit is contained in:
Emilio Cobos Álvarez 2017-05-29 23:12:44 +02:00
parent 03952a0c27
commit 10bd5636dc
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
2 changed files with 46 additions and 19 deletions

View file

@ -12,7 +12,6 @@ use element_state::*;
use selectors::bloom::BloomFilter;
use selectors::matching::StyleRelations;
use sharing::{StyleSharingCandidate, StyleSharingTarget};
use sink::ForgetfulSink;
use stylearc::Arc;
/// Determines, based on the results of selector matching, whether it's worth to
@ -23,8 +22,7 @@ pub fn relations_are_shareable(relations: &StyleRelations) -> bool {
use selectors::matching::*;
!relations.intersects(AFFECTED_BY_ID_SELECTOR |
AFFECTED_BY_PSEUDO_ELEMENTS |
AFFECTED_BY_STYLE_ATTRIBUTE |
AFFECTED_BY_PRESENTATIONAL_HINTS)
AFFECTED_BY_STYLE_ATTRIBUTE)
}
/// Whether, given two elements, they have pointer-equal computed values.
@ -51,12 +49,13 @@ pub fn same_computed_values<E>(first: Option<E>, second: Option<E>) -> bool
/// We consider not worth to share style with an element that has presentational
/// hints, both because implementing the code that compares that the hints are
/// equal is somewhat annoying, and also because it'd be expensive enough.
pub fn has_presentational_hints<E>(element: E) -> bool
pub fn have_same_presentational_hints<E>(
target: &mut StyleSharingTarget<E>,
candidate: &mut StyleSharingCandidate<E>
) -> bool
where E: TElement,
{
let mut hints = ForgetfulSink::new();
element.synthesize_presentational_hints_for_legacy_attributes(&mut hints);
!hints.is_empty()
target.pres_hints() == candidate.pres_hints()
}
/// Whether a given element has the same class attribute than a given candidate.

View file

@ -15,10 +15,9 @@ use matching::{ChildCascadeRequirement, MatchMethods};
use properties::ComputedValues;
use selectors::bloom::BloomFilter;
use selectors::matching::{ElementSelectorFlags, StyleRelations};
use sink::ForgetfulSink;
use smallvec::SmallVec;
use std::ops::Deref;
use stylist::Stylist;
use stylist::{ApplicableDeclarationBlock, Stylist};
mod checks;
@ -45,6 +44,9 @@ pub struct CachedStyleSharingData {
/// a similar fashion as what Boris is doing for the ID attribute.
class_list: Option<SmallVec<[Atom; 5]>>,
/// The list of presentational attributes of the element.
pres_hints: Option<SmallVec<[ApplicableDeclarationBlock; 5]>>,
/// The cached result of matching this entry against the revalidation
/// selectors.
revalidation_match_results: Option<BitVec>,
@ -56,6 +58,7 @@ impl CachedStyleSharingData {
pub fn new() -> Self {
Self {
class_list: None,
pres_hints: None,
revalidation_match_results: None,
}
}
@ -64,10 +67,24 @@ impl CachedStyleSharingData {
pub fn take(&mut self) -> Self {
Self {
class_list: self.class_list.take(),
pres_hints: self.pres_hints.take(),
revalidation_match_results: self.revalidation_match_results.take(),
}
}
/// Get or compute the list of presentational attributes associated with
/// this element.
pub fn pres_hints<E>(&mut self, element: E) -> &[ApplicableDeclarationBlock]
where E: TElement,
{
if self.pres_hints.is_none() {
let mut pres_hints = SmallVec::new();
element.synthesize_presentational_hints_for_legacy_attributes(&mut pres_hints);
self.pres_hints = Some(pres_hints);
}
&*self.pres_hints.as_ref().unwrap()
}
/// Get or compute the class-list associated with this element.
pub fn class_list<E>(&mut self, element: E) -> &[Atom]
where E: TElement,
@ -121,6 +138,11 @@ impl<E: TElement> StyleSharingCandidate<E> {
self.cache.class_list(*self.element)
}
/// Get the pres hints of this candidate.
fn pres_hints(&mut self) -> &[ApplicableDeclarationBlock] {
self.cache.pres_hints(*self.element)
}
/// Get the classlist of this candidate.
fn revalidation_match_results(
&mut self,
@ -167,6 +189,11 @@ impl<E: TElement> StyleSharingTarget<E> {
self.cache.class_list(self.element)
}
/// Get the pres hints of this candidate.
fn pres_hints(&mut self) -> &[ApplicableDeclarationBlock] {
self.cache.pres_hints(self.element)
}
fn revalidation_match_results(
&mut self,
stylist: &Stylist,
@ -307,7 +334,9 @@ impl<E: TElement> StyleSharingCandidateCache<E> {
element: &E,
style: &ComputedValues,
relations: StyleRelations,
cache: CachedStyleSharingData) {
mut cache: CachedStyleSharingData) {
use selectors::matching::AFFECTED_BY_PRESENTATIONAL_HINTS;
let parent = match element.parent_element() {
Some(element) => element,
None => {
@ -328,14 +357,6 @@ impl<E: TElement> StyleSharingCandidateCache<E> {
return;
}
// Make sure we noted any presentational hints in the StyleRelations.
if cfg!(debug_assertions) {
let mut hints = ForgetfulSink::new();
element.synthesize_presentational_hints_for_legacy_attributes(&mut hints);
debug_assert!(hints.is_empty(),
"Style relations should not be shareable!");
}
let box_style = style.get_box();
if box_style.specifies_transitions() {
debug!("Failing to insert to the cache: transitions");
@ -347,6 +368,13 @@ impl<E: TElement> StyleSharingCandidateCache<E> {
return;
}
// Take advantage of the information we've learned during
// selector-matching.
if !relations.intersects(AFFECTED_BY_PRESENTATIONAL_HINTS) {
debug_assert!(cache.pres_hints.as_ref().map_or(true, |v| v.is_empty()));
cache.pres_hints = Some(SmallVec::new());
}
debug!("Inserting into cache: {:?} with parent {:?}", element, parent);
self.cache.insert(StyleSharingCandidate {
@ -532,7 +560,7 @@ impl<E: TElement> StyleSharingCandidateCache<E> {
miss!(Class)
}
if checks::has_presentational_hints(target.element) {
if !checks::have_same_presentational_hints(target, candidate) {
miss!(PresHints)
}