servo: Merge #12962 - Cached element class names in style sharing cache with lazy computation (from ashrko619:cache-element-classnames); r=notriddle
authorAshwin R <ashwinravichandran24@gmail.com>
Mon, 22 Aug 2016 01:22:04 -0500
changeset 339534 c15133b225c5903b93dbe3682465deb5fe259ce6
parent 339533 72acbb5883be863f468e4b37f076f1725d9cd933
child 339535 281631312857179b36e220bf482b341838d030b5
push id31307
push usergszorc@mozilla.com
push dateSat, 04 Feb 2017 00:59:06 +0000
treeherdermozilla-central@94079d43835f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnotriddle
servo: Merge #12962 - Cached element class names in style sharing cache with lazy computation (from ashrko619:cache-element-classnames); r=notriddle <!-- Please describe your changes on the following line: --> Fixes #12912 Added a field to StyleSharingCandidate to lazily compute and cache the class names. --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [x] These changes fix #12912 (github issue number if applicable). <!-- Either: --> - [ ] There are tests for these changes OR - [x] These changes do not require tests. <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> Source-Repo: https://github.com/servo/servo Source-Revision: 87cc453ba7824191f120eb9af3bf358ca5bc3d8a
servo/components/style/matching.rs
--- a/servo/components/style/matching.rs
+++ b/servo/components/style/matching.rs
@@ -181,16 +181,18 @@ impl ApplicableDeclarationsCache {
 #[derive(Debug)]
 struct StyleSharingCandidate {
     /// The node, guaranteed to be an element.
     node: UnsafeNode,
     /// The cached computed style, here for convenience.
     style: Arc<ComputedValues>,
     /// The cached common style affecting attribute info.
     common_style_affecting_attributes: Option<CommonStyleAffectingAttributes>,
+    /// the cached class names.
+    class_attributes: Option<Vec<Atom>>,
 }
 
 impl PartialEq<StyleSharingCandidate> for StyleSharingCandidate {
     fn eq(&self, other: &Self) -> bool {
         self.node == other.node &&
             arc_ptr_eq(&self.style, &other.style) &&
             self.common_style_affecting_attributes == other.common_style_affecting_attributes
     }
@@ -260,17 +262,17 @@ fn element_matches_candidate<E: TElement
     if element.get_id().is_some() {
         miss!(IdAttr)
     }
 
     if element.style_attribute().is_some() {
         miss!(StyleAttr)
     }
 
-    if !have_same_class(element, candidate_element) {
+    if !have_same_class(element, candidate, candidate_element) {
         miss!(Class)
     }
 
     if !have_same_common_style_affecting_attributes(element,
                                                     candidate,
                                                     candidate_element) {
         miss!(CommonStyleAffectingAttributes)
     }
@@ -368,25 +370,30 @@ pub fn common_style_affecting_attributes
 
 /// Attributes that, if present, disable style sharing. All legacy HTML attributes must be in
 /// either this list or `common_style_affecting_attributes`. See the comment in
 /// `synthesize_presentational_hints_for_legacy_attributes`.
 pub fn rare_style_affecting_attributes() -> [Atom; 3] {
     [ atom!("bgcolor"), atom!("border"), atom!("colspan") ]
 }
 
-fn have_same_class<E: TElement>(element: &E, candidate: &E) -> bool {
+fn have_same_class<E: TElement>(element: &E,
+                                candidate: &mut StyleSharingCandidate,
+                                candidate_element: &E) -> bool {
     // XXX Efficiency here, I'm only validating ideas.
-    let mut first = vec![];
-    let mut second = vec![];
+    let mut element_class_attributes = vec![];
+    element.each_class(|c| element_class_attributes.push(c.clone()));
 
-    element.each_class(|c| first.push(c.clone()));
-    candidate.each_class(|c| second.push(c.clone()));
+    if candidate.class_attributes.is_none() {
+        let mut attrs = vec![];
+        candidate_element.each_class(|c| attrs.push(c.clone()));
+        candidate.class_attributes = Some(attrs)
+    }
 
-    first == second
+    element_class_attributes == candidate.class_attributes.clone().unwrap()
 }
 
 // TODO: These re-match the candidate every time, which is suboptimal.
 #[inline]
 fn match_same_not_common_style_affecting_attributes_rules<E: TElement>(element: &E,
                                                                        candidate: &E,
                                                                        ctx: &SharedStyleContext) -> bool {
     ctx.stylist.match_same_not_common_style_affecting_attributes_rules(element, candidate)
@@ -449,16 +456,17 @@ impl StyleSharingCandidateCache {
 
         debug!("Inserting into cache: {:?} with parent {:?}",
                element.as_node().to_unsafe(), parent.as_node().to_unsafe());
 
         self.cache.insert(StyleSharingCandidate {
             node: node.to_unsafe(),
             style: style.clone(),
             common_style_affecting_attributes: None,
+            class_attributes: None,
         }, ());
     }
 
     pub fn touch(&mut self, index: usize) {
         self.cache.touch(index);
     }
 
     pub fn clear(&mut self) {