aboutsummaryrefslogtreecommitdiffstats
path: root/components/style/sharing
diff options
context:
space:
mode:
authorEmilio Cobos Álvarez <emilio@crisal.io>2017-05-29 23:12:44 +0200
committerEmilio Cobos Álvarez <emilio@crisal.io>2017-05-29 23:12:44 +0200
commit10bd5636dcf665bccfb65956eca3db5bdaaba0b4 (patch)
tree051f6ee210064e499f4cadf94aef174778f183d2 /components/style/sharing
parent03952a0c27311e956748234389657ef637b22e2c (diff)
downloadservo-10bd5636dcf665bccfb65956eca3db5bdaaba0b4.tar.gz
servo-10bd5636dcf665bccfb65956eca3db5bdaaba0b4.zip
style: Allow sharing style for elements with presentational hints.
Diffstat (limited to 'components/style/sharing')
-rw-r--r--components/style/sharing/checks.rs13
-rw-r--r--components/style/sharing/mod.rs52
2 files changed, 46 insertions, 19 deletions
diff --git a/components/style/sharing/checks.rs b/components/style/sharing/checks.rs
index 6fad78fcb7e..d773afc2bd4 100644
--- a/components/style/sharing/checks.rs
+++ b/components/style/sharing/checks.rs
@@ -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.
diff --git a/components/style/sharing/mod.rs b/components/style/sharing/mod.rs
index c850ee24605..c6fe9a078a8 100644
--- a/components/style/sharing/mod.rs
+++ b/components/style/sharing/mod.rs
@@ -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)
}