Bug 1370719 - Shrink ElementData by moving pseudo count to type. r=bholley draft
authorJ. Ryan Stinnett <jryans@gmail.com>
Tue, 20 Jun 2017 14:02:45 -0500
changeset 597766 e4230a2f5385f0e3b304deb1eae0292a4a7e3546
parent 597765 6f136f65ea1bdcb126f960d4e335af4b9548bfc3
child 634314 b617017f8e8b379b357ce1a315899f881c698400
push id65023
push userbmo:jryans@gmail.com
push dateTue, 20 Jun 2017 22:59:41 +0000
reviewersbholley
bugs1370719
milestone56.0a1
Bug 1370719 - Shrink ElementData by moving pseudo count to type. r=bholley `ElementValues` holds an optional list of values for each eager pseudo-element. However, the type was declared as a slice instead of a fixed size array, so an extra 8 bytes were being allocated to hold the size, even though it never changes. Moving the constant size into the type reduces `ElementValues` and `ElementData` by 8 bytes. MozReview-Commit-ID: GaO6DKFxUMo
servo/components/style/data.rs
servo/tests/unit/stylo/size_of.rs
--- a/servo/components/style/data.rs
+++ b/servo/components/style/data.rs
@@ -95,18 +95,34 @@ impl RestyleData {
     /// Returns whether this element has been part of a restyle.
     pub fn contains_restyle_data(&self) -> bool {
         self.is_restyle() || !self.hint.is_empty() || !self.damage.is_empty()
     }
 }
 
 /// A list of computed values for eagerly-cascaded pseudo-elements.
 /// Lazily-allocated.
-#[derive(Clone, Debug)]
-pub struct EagerPseudoValues(pub Option<Box<[Option<Arc<ComputedValues>>]>>);
+#[derive(Debug)]
+pub struct EagerPseudoValues(pub Option<Box<[Option<Arc<ComputedValues>>; EAGER_PSEUDO_COUNT]>>);
+
+// Manually implement `Clone` here because the derived impl of `Clone` for
+// array types assumes the value inside is `Copy`.
+impl Clone for EagerPseudoValues {
+    fn clone(&self) -> Self {
+        if self.0.is_none() {
+            return EagerPseudoValues(None)
+        }
+        let self_values = self.0.as_ref().unwrap();
+        let mut values: [Option<Arc<ComputedValues>>; EAGER_PSEUDO_COUNT] = Default::default();
+        for i in 0..EAGER_PSEUDO_COUNT {
+            values[i] = self_values[i].clone();
+        }
+        EagerPseudoValues(Some(Box::new(values)))
+    }
+}
 
 impl EagerPseudoValues {
     /// Returns whether there are any pseudo values.
     pub fn is_empty(&self) -> bool {
         self.0.is_none()
     }
 
     /// Returns a reference to the values for a given eager pseudo, if it exists.
@@ -124,17 +140,17 @@ impl EagerPseudoValues {
     /// Returns true if the EagerPseudoStyles has the values for |pseudo|.
     pub fn has(&self, pseudo: &PseudoElement) -> bool {
         self.get(pseudo).is_some()
     }
 
     /// Sets the values for the eager pseudo.
     pub fn set(&mut self, pseudo: &PseudoElement, value: Arc<ComputedValues>) {
         if self.0.is_none() {
-            self.0 = Some(vec![None; EAGER_PSEUDO_COUNT].into_boxed_slice());
+            self.0 = Some(Box::new(Default::default()));
         }
         self.0.as_mut().unwrap()[pseudo.eager_index()] = Some(value);
     }
 
     /// Inserts a pseudo-element. The pseudo-element must not already exist.
     pub fn insert(&mut self, pseudo: &PseudoElement, value: Arc<ComputedValues>) {
         debug_assert!(!self.has(pseudo));
         self.set(pseudo, value);
--- a/servo/tests/unit/stylo/size_of.rs
+++ b/servo/tests/unit/stylo/size_of.rs
@@ -27,19 +27,19 @@ fn size_of_selectors_dummy_types() {
 // The size of this is critical to performance on the bloom-basic microbenchmark.
 // When iterating over a large Rule array, we want to be able to fast-reject
 // selectors (with the inline hashes) with as few cache misses as possible.
 size_of_test!(test_size_of_rule, style::stylist::Rule, 32);
 
 size_of_test!(test_size_of_option_arc_cv, Option<Arc<ComputedValues>>, 8);
 size_of_test!(test_size_of_option_rule_node, Option<StrongRuleNode>, 8);
 
-size_of_test!(test_size_of_element_values, ElementValues, 24);
+size_of_test!(test_size_of_element_values, ElementValues, 16);
 size_of_test!(test_size_of_restyle_data, RestyleData, 8);
-size_of_test!(test_size_of_element_data, ElementData, 32);
+size_of_test!(test_size_of_element_data, ElementData, 24);
 
 size_of_test!(test_size_of_property_declaration, style::properties::PropertyDeclaration, 32);
 
 size_of_test!(test_size_of_application_declaration_block, ApplicableDeclarationBlock, 24);
 
 // FIXME(bholley): This can shrink with a little bit of work.
 // See https://github.com/servo/servo/issues/17280
 size_of_test!(test_size_of_rule_node, RuleNode, 80);