Skip to content

Commit 1d80119

Browse files
committed
Bug 1980234 - Cache DependencyInvalidationKind within Dependency for faster lookup of NormalInvalidationKind. r=dshin
Differential Revision: https://phabricator.services.mozilla.com/D259468
1 parent 4dfd341 commit 1d80119

File tree

4 files changed

+70
-66
lines changed

4 files changed

+70
-66
lines changed

style/invalidation/element/invalidation_map.rs

Lines changed: 64 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,8 @@ pub struct Dependency {
7171
#[ignore_malloc_size_of = "Arc"]
7272
pub next: Option<ThinArc<(), Dependency>>,
7373

74-
/// What kind of relative selector invalidation this generates.
75-
/// None if this dependency is not within a relative selector.
76-
relative_kind: Option<RelativeDependencyInvalidationKind>,
74+
/// What kind of selector invalidation this generates.
75+
kind: DependencyInvalidationKind,
7776
}
7877

7978
impl SelectorMapEntry for Dependency {
@@ -125,12 +124,64 @@ pub enum RelativeDependencyInvalidationKind {
125124
/// Invalidation kind merging normal and relative dependencies.
126125
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, MallocSizeOf)]
127126
pub enum DependencyInvalidationKind {
127+
/// This dependency is for full selector invalidation.
128+
/// It is assuumed that there will be no next dependency to look for.
129+
FullSelector,
128130
/// This dependency is a normal dependency.
129131
Normal(NormalDependencyInvalidationKind),
130132
/// This dependency is a relative dependency.
131133
Relative(RelativeDependencyInvalidationKind),
132134
}
133135

136+
/// Return the type of normal invalidation given a selector & an offset.
137+
fn get_normal_invalidation_kind(selector: &Selector<SelectorImpl>, selector_offset: usize) -> DependencyInvalidationKind {
138+
if selector_offset == 0 || selector.len() <= selector_offset{
139+
return DependencyInvalidationKind::Normal(NormalDependencyInvalidationKind::Element);
140+
}
141+
let combinator = Some(selector
142+
.combinator_at_match_order(selector_offset - 1)
143+
);
144+
DependencyInvalidationKind::Normal(
145+
match combinator {
146+
None => NormalDependencyInvalidationKind::Element,
147+
Some(Combinator::Child) | Some(Combinator::Descendant) => {
148+
NormalDependencyInvalidationKind::Descendants
149+
},
150+
Some(Combinator::LaterSibling) | Some(Combinator::NextSibling) => {
151+
NormalDependencyInvalidationKind::Siblings
152+
},
153+
Some(Combinator::PseudoElement) => {
154+
NormalDependencyInvalidationKind::ElementAndDescendants
155+
},
156+
Some(Combinator::SlotAssignment) => NormalDependencyInvalidationKind::SlottedElements,
157+
Some(Combinator::Part) => NormalDependencyInvalidationKind::Parts,
158+
}
159+
)
160+
}
161+
162+
/// Return the relative invalidation kind given a match hint
163+
fn get_relative_kind(match_hint: RelativeSelectorMatchHint) -> RelativeDependencyInvalidationKind{
164+
match match_hint {
165+
RelativeSelectorMatchHint::InChild => RelativeDependencyInvalidationKind::Parent,
166+
RelativeSelectorMatchHint::InSubtree => {
167+
RelativeDependencyInvalidationKind::Ancestors
168+
},
169+
RelativeSelectorMatchHint::InNextSibling => {
170+
RelativeDependencyInvalidationKind::PrevSibling
171+
},
172+
RelativeSelectorMatchHint::InSibling => {
173+
RelativeDependencyInvalidationKind::EarlierSibling
174+
},
175+
RelativeSelectorMatchHint::InNextSiblingSubtree => {
176+
RelativeDependencyInvalidationKind::AncestorPrevSibling
177+
},
178+
RelativeSelectorMatchHint::InSiblingSubtree => {
179+
RelativeDependencyInvalidationKind::AncestorEarlierSibling
180+
},
181+
}
182+
}
183+
184+
134185
impl Dependency {
135186
/// Creates a dummy dependency to invalidate the whole selector.
136187
///
@@ -145,56 +196,22 @@ impl Dependency {
145196
selector_offset: selector.len() + 1,
146197
selector,
147198
next: None,
148-
relative_kind: None,
199+
kind: DependencyInvalidationKind::FullSelector,
149200
}
150201
}
151202

152-
/// Returns the combinator to the right of the partial selector this
153-
/// dependency represents.
154-
///
155-
/// TODO(emilio): Consider storing inline if it helps cache locality?
156-
fn combinator(&self) -> Option<Combinator> {
157-
if self.selector_offset == 0 {
158-
return None;
159-
}
160-
161-
Some(
162-
self.selector
163-
.combinator_at_match_order(self.selector_offset - 1),
164-
)
165-
}
166-
167203
/// The kind of normal invalidation that this would generate. The dependency
168204
/// in question must be a normal dependency.
169205
pub fn normal_invalidation_kind(&self) -> NormalDependencyInvalidationKind {
170-
debug_assert!(
171-
self.relative_kind.is_none(),
172-
"Querying normal invalidation kind on relative dependency."
173-
);
174-
match self.combinator() {
175-
None => NormalDependencyInvalidationKind::Element,
176-
Some(Combinator::Child) | Some(Combinator::Descendant) => {
177-
NormalDependencyInvalidationKind::Descendants
178-
},
179-
Some(Combinator::LaterSibling) | Some(Combinator::NextSibling) => {
180-
NormalDependencyInvalidationKind::Siblings
181-
},
182-
// TODO(emilio): We could look at the selector itself to see if it's
183-
// an eager pseudo, and return only Descendants here if not.
184-
Some(Combinator::PseudoElement) => {
185-
NormalDependencyInvalidationKind::ElementAndDescendants
186-
},
187-
Some(Combinator::SlotAssignment) => NormalDependencyInvalidationKind::SlottedElements,
188-
Some(Combinator::Part) => NormalDependencyInvalidationKind::Parts,
206+
if let DependencyInvalidationKind::Normal(kind) = self.kind {
207+
return kind;
189208
}
209+
unreachable!("Querying normal invalidation kind on non-normal dependency.");
190210
}
191211

192212
/// The kind of invalidation that this would generate.
193213
pub fn invalidation_kind(&self) -> DependencyInvalidationKind {
194-
if let Some(kind) = self.relative_kind {
195-
return DependencyInvalidationKind::Relative(kind);
196-
}
197-
DependencyInvalidationKind::Normal(self.normal_invalidation_kind())
214+
self.kind
198215
}
199216

200217
/// Is the combinator to the right of this dependency's compound selector
@@ -218,10 +235,10 @@ impl Dependency {
218235
/// connected through next sibling, e.g. `.a:has(> .b)`.
219236
pub fn dependency_is_relative_with_single_next_sibling(&self) -> bool {
220237
match self.invalidation_kind() {
221-
DependencyInvalidationKind::Normal(_) => false,
222238
DependencyInvalidationKind::Relative(kind) => {
223239
kind == RelativeDependencyInvalidationKind::PrevSibling
224240
},
241+
_ => false,
225242
}
226243
}
227244
}
@@ -763,7 +780,7 @@ fn next_dependency(
763780
selector: selector.clone(),
764781
selector_offset,
765782
next: dependencies_from(previous, next_outer_dependency, next_scope_dependencies),
766-
relative_kind: None,
783+
kind: get_normal_invalidation_kind(selector, selector_offset),
767784
};
768785

769786
Some(
@@ -799,7 +816,7 @@ impl<'a, 'b, 'c> Collector for SelectorDependencyCollector<'a, 'b, 'c> {
799816
selector: self.selector.clone(),
800817
selector_offset: offset,
801818
next: next,
802-
relative_kind: None,
819+
kind: get_normal_invalidation_kind(self.selector, offset),
803820
}
804821
}
805822

@@ -1304,7 +1321,7 @@ impl<'a, 'b> Collector for RelativeSelectorDependencyCollector<'a, 'b> {
13041321
);
13051322
debug_assert!(
13061323
next.as_ref()
1307-
.is_some_and(|d| d.slice()[0].relative_kind.is_none()),
1324+
.is_some_and(|d| !matches!(d.slice()[0].kind, DependencyInvalidationKind::Relative(_))),
13081325
"Duplicate relative dependency?"
13091326
);
13101327
debug_assert!(
@@ -1315,24 +1332,7 @@ impl<'a, 'b> Collector for RelativeSelectorDependencyCollector<'a, 'b> {
13151332
Dependency {
13161333
selector: self.selector.selector.clone(),
13171334
selector_offset: self.compound_state.offset,
1318-
relative_kind: Some(match self.combinator_count.get_match_hint() {
1319-
RelativeSelectorMatchHint::InChild => RelativeDependencyInvalidationKind::Parent,
1320-
RelativeSelectorMatchHint::InSubtree => {
1321-
RelativeDependencyInvalidationKind::Ancestors
1322-
},
1323-
RelativeSelectorMatchHint::InNextSibling => {
1324-
RelativeDependencyInvalidationKind::PrevSibling
1325-
},
1326-
RelativeSelectorMatchHint::InSibling => {
1327-
RelativeDependencyInvalidationKind::EarlierSibling
1328-
},
1329-
RelativeSelectorMatchHint::InNextSiblingSubtree => {
1330-
RelativeDependencyInvalidationKind::AncestorPrevSibling
1331-
},
1332-
RelativeSelectorMatchHint::InSiblingSubtree => {
1333-
RelativeDependencyInvalidationKind::AncestorEarlierSibling
1334-
},
1335-
}),
1335+
kind: DependencyInvalidationKind::Relative(get_relative_kind(self.combinator_count.get_match_hint())),
13361336
next: next,
13371337
}
13381338
}

style/invalidation/element/invalidator.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,7 @@ where
924924
let n = &deps.as_ref().slice()[0];
925925
let invalidation_kind = n.invalidation_kind();
926926
match invalidation_kind {
927+
DependencyInvalidationKind::FullSelector => unreachable!(),
927928
DependencyInvalidationKind::Normal(_) => n,
928929
DependencyInvalidationKind::Relative(kind) => {
929930
self.processor.found_relative_selector_invalidation(

style/invalidation/element/relative_selector.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,7 @@ where
466466
host: Option<OpaqueElement>,
467467
) {
468468
match dependency.invalidation_kind() {
469+
DependencyInvalidationKind::FullSelector => unreachable!(),
469470
DependencyInvalidationKind::Normal(..) => {
470471
self.dependencies
471472
.entry(element)
@@ -498,6 +499,7 @@ where
498499
let mut result = ToInvalidate::default();
499500
for invalidation in self.invalidations {
500501
match invalidation.dependency.invalidation_kind() {
502+
DependencyInvalidationKind::FullSelector => unreachable!(),
501503
DependencyInvalidationKind::Normal(_) => {
502504
unreachable!("Inner selector in invalidation?")
503505
},
@@ -1073,7 +1075,7 @@ where
10731075
loop {
10741076
debug_assert!(
10751077
matches!(d.invalidation_kind(), DependencyInvalidationKind::Normal(_)),
1076-
"Unexpected outer relative dependency"
1078+
"Unexpected dependency kind"
10771079
);
10781080
if !dependency_may_be_relevant(d, &element, false) {
10791081
break false;
@@ -1199,6 +1201,7 @@ where
11991201
sibling_invalidations: &mut InvalidationVector<'a>,
12001202
) {
12011203
match dependency.invalidation_kind() {
1204+
DependencyInvalidationKind::FullSelector => unreachable!(),
12021205
DependencyInvalidationKind::Normal(_) => (),
12031206
DependencyInvalidationKind::Relative(kind) => {
12041207
self.found_relative_selector_invalidation(element, kind, dependency);

style/invalidation/element/state_and_attributes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ where
527527
dependency.invalidation_kind(),
528528
DependencyInvalidationKind::Normal(_)
529529
),
530-
"Found relative selector dependency"
530+
"Found unexpected dependency invalidation kind"
531531
);
532532
debug!(
533533
"TreeStyleInvalidator::scan_dependency({:?}, {:?})",

0 commit comments

Comments
 (0)