style: Share CascadeData instances across ShadowRoots

This should be both a memory and speed win for pages using a lot of
Shadow DOM.

In order to make the cache properly work we need to start keying media query
results on the actual StyleSheetContents, as that's what we share on Gecko, but
that should all be fine.

Differential Revision: https://phabricator.services.mozilla.com/D107266
This commit is contained in:
Oriol Brufau 2023-05-16 09:51:46 +02:00
parent 11153c63fa
commit 060d74ba3b
11 changed files with 175 additions and 178 deletions

View file

@ -61,6 +61,19 @@ impl ImportSheet {
ImportSheet::Pending(_) => None,
}
}
/// Returns the media list for this import rule.
pub fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList> {
self.as_sheet().and_then(|s| s.media(guard))
}
/// Returns the rule list for this import rule.
pub fn rules<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> &'a [CssRule] {
match self.as_sheet() {
Some(s) => s.rules(guard),
None => &[],
}
}
}
#[cfg(feature = "gecko")]
@ -85,69 +98,21 @@ impl DeepCloneWithLock for ImportSheet {
}
}
#[cfg(feature = "gecko")]
impl StylesheetInDocument for ImportSheet {
fn origin(&self, _guard: &SharedRwLockReadGuard) -> Origin {
match *self {
ImportSheet::Sheet(ref s) => s.contents().origin,
ImportSheet::Pending(ref p) => p.origin,
}
}
fn quirks_mode(&self, _guard: &SharedRwLockReadGuard) -> QuirksMode {
match *self {
ImportSheet::Sheet(ref s) => s.contents().quirks_mode,
ImportSheet::Pending(ref p) => p.quirks_mode,
}
}
fn enabled(&self) -> bool {
match *self {
ImportSheet::Sheet(ref s) => s.enabled(),
ImportSheet::Pending(_) => true,
}
}
fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList> {
match *self {
ImportSheet::Sheet(ref s) => s.media(guard),
ImportSheet::Pending(_) => None,
}
}
fn rules<'a, 'b: 'a>(&'a self, guard: &'b SharedRwLockReadGuard) -> &'a [CssRule] {
match *self {
ImportSheet::Sheet(ref s) => s.contents().rules(guard),
ImportSheet::Pending(_) => &[],
}
}
}
/// A sheet that is held from an import rule.
#[cfg(feature = "servo")]
#[derive(Debug)]
pub struct ImportSheet(pub ::servo_arc::Arc<crate::stylesheets::Stylesheet>);
#[cfg(feature = "servo")]
impl StylesheetInDocument for ImportSheet {
fn origin(&self, guard: &SharedRwLockReadGuard) -> Origin {
self.0.origin(guard)
}
fn quirks_mode(&self, guard: &SharedRwLockReadGuard) -> QuirksMode {
self.0.quirks_mode(guard)
}
fn enabled(&self) -> bool {
self.0.enabled()
}
fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList> {
impl ImportSheet {
/// Returns the media list for this import rule.
pub fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList> {
self.0.media(guard)
}
fn rules<'a, 'b: 'a>(&'a self, guard: &'b SharedRwLockReadGuard) -> &'a [CssRule] {
self.0.rules(guard)
/// Returns the rules for this import rule.
pub fn rules<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> &'a [CssRule] {
self.0.rules()
}
}

View file

@ -7,7 +7,6 @@
use crate::context::QuirksMode;
use crate::media_queries::Device;
use crate::shared_lock::SharedRwLockReadGuard;
use crate::stylesheets::StylesheetInDocument;
use crate::stylesheets::{CssRule, DocumentRule, ImportRule, MediaRule, SupportsRule};
use smallvec::SmallVec;
use std::slice;
@ -227,10 +226,13 @@ impl NestedRuleIterationCondition for EffectiveRules {
fn process_import(
guard: &SharedRwLockReadGuard,
device: &Device,
_quirks_mode: QuirksMode,
quirks_mode: QuirksMode,
rule: &ImportRule,
) -> bool {
rule.stylesheet.is_effective_for_device(device, guard)
match rule.stylesheet.media(guard) {
Some(m) => m.evaluate(device, quirks_mode),
None => true,
}
}
fn process_media(

View file

@ -4,7 +4,6 @@
use crate::context::QuirksMode;
use crate::error_reporting::{ContextualParseError, ParseErrorReporter};
use crate::invalidation::media_queries::{MediaListKey, ToMediaListKey};
use crate::media_queries::{Device, MediaList};
use crate::parser::ParserContext;
use crate::shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked};
@ -102,10 +101,10 @@ impl StylesheetContents {
Self {
rules: CssRules::new(rules, &shared_lock),
origin: origin,
origin,
url_data: RwLock::new(url_data),
namespaces: namespaces,
quirks_mode: quirks_mode,
namespaces,
quirks_mode,
source_map_url: RwLock::new(source_map_url),
source_url: RwLock::new(source_url),
}
@ -218,12 +217,6 @@ macro_rules! rule_filter {
/// A trait to represent a given stylesheet in a document.
pub trait StylesheetInDocument: ::std::fmt::Debug {
/// Get the stylesheet origin.
fn origin(&self, guard: &SharedRwLockReadGuard) -> Origin;
/// Get the stylesheet quirks mode.
fn quirks_mode(&self, guard: &SharedRwLockReadGuard) -> QuirksMode;
/// Get whether this stylesheet is enabled.
fn enabled(&self) -> bool;
@ -231,7 +224,12 @@ pub trait StylesheetInDocument: ::std::fmt::Debug {
fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList>;
/// Returns a reference to the list of rules in this stylesheet.
fn rules<'a, 'b: 'a>(&'a self, guard: &'b SharedRwLockReadGuard) -> &'a [CssRule];
fn rules<'a, 'b: 'a>(&'a self, guard: &'b SharedRwLockReadGuard) -> &'a [CssRule] {
self.contents().rules(guard)
}
/// Returns a reference to the contents of the stylesheet.
fn contents(&self) -> &StylesheetContents;
/// Return an iterator using the condition `C`.
#[inline]
@ -243,18 +241,19 @@ pub trait StylesheetInDocument: ::std::fmt::Debug {
where
C: NestedRuleIterationCondition,
{
let contents = self.contents();
RulesIterator::new(
device,
self.quirks_mode(guard),
contents.quirks_mode,
guard,
self.rules(guard).iter(),
contents.rules(guard).iter(),
)
}
/// Returns whether the style-sheet applies for the current device.
fn is_effective_for_device(&self, device: &Device, guard: &SharedRwLockReadGuard) -> bool {
match self.media(guard) {
Some(medialist) => medialist.evaluate(device, self.quirks_mode(guard)),
Some(medialist) => medialist.evaluate(device, self.contents().quirks_mode),
None => true,
}
}
@ -285,14 +284,6 @@ pub trait StylesheetInDocument: ::std::fmt::Debug {
}
impl StylesheetInDocument for Stylesheet {
fn origin(&self, _guard: &SharedRwLockReadGuard) -> Origin {
self.contents.origin
}
fn quirks_mode(&self, _guard: &SharedRwLockReadGuard) -> QuirksMode {
self.contents.quirks_mode
}
fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList> {
Some(self.media.read_with(guard))
}
@ -302,8 +293,8 @@ impl StylesheetInDocument for Stylesheet {
}
#[inline]
fn rules<'a, 'b: 'a>(&'a self, guard: &'b SharedRwLockReadGuard) -> &'a [CssRule] {
self.contents.rules(guard)
fn contents(&self) -> &StylesheetContents {
&self.contents
}
}
@ -321,21 +312,7 @@ impl PartialEq for DocumentStyleSheet {
}
}
impl ToMediaListKey for DocumentStyleSheet {
fn to_media_list_key(&self) -> MediaListKey {
self.0.to_media_list_key()
}
}
impl StylesheetInDocument for DocumentStyleSheet {
fn origin(&self, guard: &SharedRwLockReadGuard) -> Origin {
self.0.origin(guard)
}
fn quirks_mode(&self, guard: &SharedRwLockReadGuard) -> QuirksMode {
self.0.quirks_mode(guard)
}
fn media<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> Option<&'a MediaList> {
self.0.media(guard)
}
@ -345,8 +322,8 @@ impl StylesheetInDocument for DocumentStyleSheet {
}
#[inline]
fn rules<'a, 'b: 'a>(&'a self, guard: &'b SharedRwLockReadGuard) -> &'a [CssRule] {
self.0.rules(guard)
fn contents(&self) -> &StylesheetContents {
self.0.contents()
}
}