From 8016c434b01afde931f8de909c8b9f839f8b6dd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Tue, 6 Jun 2023 23:54:09 +0200 Subject: [PATCH] style: Reuse inherited custom properties if they didn't change after resolution This should be cheap and gives us a lot of memory savings for the page on the bug, by deduplicating the inherited properties between parent and children. WebKit implements a similar optimization. Differential Revision: https://phabricator.services.mozilla.com/D140826 --- components/style/custom_properties.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/components/style/custom_properties.rs b/components/style/custom_properties.rs index 0b5bcf8842c..7be700ec350 100644 --- a/components/style/custom_properties.rs +++ b/components/style/custom_properties.rs @@ -723,6 +723,22 @@ impl<'a> CustomPropertiesBuilder<'a> { true } + fn inherited_properties_match(&self, map: &CustomPropertiesMap) -> bool { + let inherited = match self.inherited { + Some(inherited) => inherited, + None => return false, + }; + if inherited.len() != map.len() { + return false; + } + for name in self.seen.iter() { + if inherited.get(*name) != map.get(*name) { + return false; + } + } + true + } + /// Returns the final map of applicable custom properties. /// /// If there was any specified property, we've created a new map and now we @@ -734,9 +750,19 @@ impl<'a> CustomPropertiesBuilder<'a> { Some(m) => m, None => return self.inherited.cloned(), }; + if self.may_have_cycles { substitute_all(&mut map, &self.seen, self.device); } + + // Some pages apply a lot of redundant custom properties, see e.g. + // bug 1758974 comment 5. Try to detect the case where the values + // haven't really changed, and save some memory by reusing the inherited + // map in that case. + if self.inherited_properties_match(&map) { + return self.inherited.cloned(); + } + map.shrink_to_fit(); Some(Arc::new(map)) }