Closed
Bug 525608
Opened 15 years ago
Closed 15 years ago
[FIX]Speed up pseudo-style probing
Categories
(Core :: CSS Parsing and Computation, defect)
Tracking
()
RESOLVED
FIXED
People
(Reporter: bzbarsky, Assigned: bzbarsky)
References
(Blocks 1 open bug)
Details
Attachments
(10 files, 4 obsolete files)
7.46 KB,
patch
|
dbaron
:
review+
|
Details | Diff | Splinter Review |
23.28 KB,
patch
|
dbaron
:
review+
|
Details | Diff | Splinter Review |
19.27 KB,
patch
|
dbaron
:
review+
|
Details | Diff | Splinter Review |
35.24 KB,
patch
|
dbaron
:
review+
|
Details | Diff | Splinter Review |
20.37 KB,
patch
|
Details | Diff | Splinter Review | |
89.55 KB,
patch
|
Details | Diff | Splinter Review | |
4.13 KB,
patch
|
Details | Diff | Splinter Review | |
36.78 KB,
patch
|
Details | Diff | Splinter Review | |
35.46 KB,
patch
|
Details | Diff | Splinter Review | |
2.58 KB,
patch
|
dbaron
:
review+
|
Details | Diff | Splinter Review |
Basic idea is to be smarter about storing our pseudo-style selectors in the rule cascade, instead of just using a flat list. See the mozilla.dev.tech.layout thread about "Optimizing pseudo-style probing".
Assignee | ||
Comment 1•15 years ago
|
||
I'm not a huge fan of the actual names in this enum, so if you have better suggestions, please let me know!
Attachment #409468 -
Flags: review?(dbaron)
Assignee | ||
Comment 2•15 years ago
|
||
Attachment #409469 -
Flags: review?(dbaron)
Assignee | ||
Comment 3•15 years ago
|
||
Attachment #409470 -
Flags: review?(dbaron)
Assignee | ||
Comment 4•15 years ago
|
||
Two things worth checking here:
1) I removed the null-checks of the return value of PresContext() in the style
set. I think that's ok, but if not please let me know?
2) Should EnumerateAllRules get the tag/id/etc from aData itself, now that it
can?
Attachment #409471 -
Flags: review?(dbaron)
Assignee | ||
Comment 5•15 years ago
|
||
Attachment #409472 -
Flags: review?(dbaron)
Assignee | ||
Comment 6•15 years ago
|
||
Attachment #409473 -
Flags: review?(dbaron)
Assignee | ||
Comment 7•15 years ago
|
||
I'm not sure what the best approach is to the pseudo stats here.... I'm also not sure whether it's in fact worth putting the tree pseudos in a separate hashtable instead of just riding along on the rulehash. It does remove at least one IsPseudoElement() check from the tree pseudo codepath, but that's peanuts.
Attachment #409475 -
Flags: review?(dbaron)
Assignee | ||
Comment 8•15 years ago
|
||
One other note. We could make the -moz-list* pseudos into anonymous boxes instead of pseudo-elements if we're ok with applying the font-size quirk to *|*::-moz-list-bullet in quirks mode, not just to li::-moz-list-bullet. That might make list items a tiny bit faster (no need for the RuleProcessorData data for the bullet). Or not, if the hashtable op is enough more expensive than the array index...
Assignee | ||
Updated•15 years ago
|
Summary: Speed up pseudo-style probing → [FIX]Speed up pseudo-style probing
Attachment #409468 -
Flags: review?(dbaron) → review+
Comment on attachment 409468 [details] [diff] [review]
Part 1. Introduce an enum for pseudo-elements
r=dbaron, though I'm interested to see what uses some of those enum values turn out to have in the later patches
(I wonder if you should change from to passing null for the content node when resolving the frameset border styles, but I think it's ok as-is.)
(In reply to comment #9)
> (I wonder if you should change from to passing null for the content node when
> resolving the frameset border styles, but I think it's ok as-is.)
I guess that's moot after patch 3, though. :-)
Assignee | ||
Comment 11•15 years ago
|
||
> what uses some of those enum values turn out to have in the later patches
The main uses are telling apart pseudo-element vs anon box vs tree pseudo (if nothing else for patch 3), and for the first of these looking up the pseudo atom quickly (mostly for impedance matching with existing code) and looking up the relevant rulehash in patch 4.
Comment on attachment 409469 [details] [diff] [review]
Part 2. CSS parser changes
In ParsePseudoSelector and ParseSelector, could you either rename
aPseudoType to be aPseudoElementType or rename
aPseudoElement/aPseudoElementArgs to aPseudo/aPseudoArgs. I think I'd
prefer the former. (Anonymous boxes really are just a variation of
pseudo-elements.)
>+ NS_ASSERTION(!isPseudoClass ||
>+ pseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement,
>+ "Why is this atom both a pseudo-class and a pseudo-element?");
You might also want to assert that isPseudoClass + isPseudoElement +
isAnonBox <= 1.
> // -- nsCSSSelector -------------------------------
>-
> nsCSSSelector::nsCSSSelector(void)
I'd prefer keeping the blank line.
r=dbaron
Attachment #409469 -
Flags: review?(dbaron) → review+
Comment on attachment 409470 [details] [diff] [review]
Part 3. Make consumers ask for different pseudo styles differently
nsStyleStruct.h:
+// See nsStyleContext::GetPseudoEnum
+#define NS_STYLE_CONTEXT_TYPE_SHIFT 28
Could you explicitly define the mask even if you don't use the constant?
nsStyleSet.cpp:
+#ifdef DEBUG
+ else {
+ NS_ASSERTION(result->GetPseudoType() == aPseudoType, "Unexpected type");
+ }
+#endif
No need for the #ifdefs. (And you could check GetPseudoTag too if you
want.)
Are the changes to nsComputedDOMStyle::GetStyleContextForContent
changing compatibility? Should we instead return an non-element style
inside the element? Or does it matter?
(Also, while I'm there, shouldn't the recursive call inside
GetStyleContextForContentNoFlush call GetStyleContextForContentNoFlush
rather than just GetStyleContextForContent?
It occurs to me that we might want to make :-moz-non-element be a
different type in the enum (at some time in the future).
r=dbaron
Attachment #409470 -
Flags: review?(dbaron) → review+
Assignee | ||
Comment 14•15 years ago
|
||
> Could you explicitly define the mask even if you don't use the constant?
So just NS_STYLE_CONTEXT_TYPE_MASK defined to 0xf000000?
> Are the changes to nsComputedDOMStyle::GetStyleContextForContent
> changing compatibility?
Yes. I'm absolutely open for changing the behavior here in various ways. The current code (before this change) just always returns a style context pointing to the root rulenode for cases when an unknown (not anon box, not tree pseudo, not pseudo-element) pseudo is used; which is effectively a non-element style context inside the element, as you propose. After my change, a call that uses a pseudo that's not a pseudo-element will throw. We can change it to do the non-element thing, for sure. Would you prefer that? I don't have a strong opinion here; I suspect in practice no one ever uses the pseudo version of getComputedStyle, esp. not with random non-pseudo-element pseudos.
> shouldn't the recursive call inside GetStyleContextForContentNoFlush call
> GetStyleContextForContentNoFlush
Yes, it should. I'll roll that change in.
> It occurs to me that we might want to make :-moz-non-element be a
> different type in the enum (at some time in the future)
Sure. I'd be fine with that.
(In reply to comment #14)
> > Could you explicitly define the mask even if you don't use the constant?
>
> So just NS_STYLE_CONTEXT_TYPE_MASK defined to 0xf000000?
Yes.
> > Are the changes to nsComputedDOMStyle::GetStyleContextForContent
> > changing compatibility?
>
> Yes. I'm absolutely open for changing the behavior here in various ways. The
> current code (before this change) just always returns a style context pointing
> to the root rulenode for cases when an unknown (not anon box, not tree pseudo,
> not pseudo-element) pseudo is used; which is effectively a non-element style
> context inside the element, as you propose. After my change, a call that uses
> a pseudo that's not a pseudo-element will throw. We can change it to do the
> non-element thing, for sure. Would you prefer that? I don't have a strong
> opinion here; I suspect in practice no one ever uses the pseudo version of
> getComputedStyle, esp. not with random non-pseudo-element pseudos.
On the other hand, maybe throwing is better, because we're changing the code from actually computing the style correctly for some future pseudo-element to actually not being able to compute it.
Assignee | ||
Comment 16•15 years ago
|
||
We didn't really compute it correctly before, since the future pseudo-element never had any rules applying to it (since they got dropped by the parser)...
Assignee | ||
Comment 17•15 years ago
|
||
> rename aPseudoType to be aPseudoElementType
Done; similar for the locals. Addressed the other two comments too.
Attachment #409469 -
Attachment is obsolete: true
Assignee | ||
Comment 18•15 years ago
|
||
Addressed the issues from comment 13, except for deciding whether to make the behavior change. Do we want that?
I guess throwing makes sense.
Assignee | ||
Comment 20•15 years ago
|
||
Attachment #409470 -
Attachment is obsolete: true
Comment on attachment 409471 [details] [diff] [review]
Part 4. The actual change to how pseudo-elements work
I think it would make more sense to store mQuirksMode on the
RuleCascadeData rather than on each RuleHash.
+ RuleHash* ruleHash = cascade->mPseudoElementRuleHashes[pseudoType];
Maybe make this RuleHash*& or RuleHash** and then just assign right back
to it?
You need to rev the nsIStyleRuleProcessor IID.
Also, in nsIStyleRuleProcessor.h, the comment for
RulesMatching(PseudoRuleProcessorData*) should perhaps say anonymous box
rather than just "pseudo"? (Hmmm... maybe you put that in a later
patch?)
In nsStyleSet.cpp, you should put ResolvePseudoElementStyle before
ResolvePseudoStyle, like it is everywhere else.
r=dbaron with that
Attachment #409471 -
Flags: review?(dbaron) → review+
(In reply to comment #21)
> Also, in nsIStyleRuleProcessor.h, the comment for
> RulesMatching(PseudoRuleProcessorData*) should perhaps say anonymous box
> rather than just "pseudo"? (Hmmm... maybe you put that in a later
> patch?)
Given the later patches, ignore this. (Though maybe there should be a patch on top to change it to be more clearly for only what's left, which I think is just the tree pseudos?)
Comment on attachment 409472 [details] [diff] [review]
Part 5. Make anonymous boxes not do selector matching at all and instead just do a single hashtable lookup
r=dbaron
Attachment #409472 -
Flags: review?(dbaron) → review+
Comment on attachment 409473 [details] [diff] [review]
Part 6. Now that anon boxes don't use RuleProcessorData, it always has an mContent
r=dbaron
Attachment #409473 -
Flags: review?(dbaron) → review+
One other question about patch 4: should we really be using ContentEnumFunc directly? Doesn't that do an entirely wasted SelectorMatches call on the pseudo-element selector?
Comment on attachment 409475 [details] [diff] [review]
Part 7. Move tree pseudos out of the rulehash
> PLDHashTable mAttributeSelectors;
> PLDHashTable mAnonBoxRules;
>
>+#ifdef MOZ_XUL
>+ PLDHashTable mXULTreeRules;
>+#endif
Drop the blank line before the #ifdef?
And yes, this patch has the comment changes in nsIStyleRuleProcessor.h
(and the IID rev, but watch the 80th column in the comment above it)
that I asked for for patch 4.
r=dbaron
And one other comment about AddRule: there might be value in having the
most common case at the start of the if-else chain rather than at the
end. (Maybe another patch on top?)
Attachment #409475 -
Flags: review?(dbaron) → review+
Assignee | ||
Comment 27•15 years ago
|
||
> store mQuirksMode on the RuleCascadeData
> Maybe make this RuleHash*&
Excellent ideas.
> put ResolvePseudoElementStyle before ResolvePseudoStyle
Does that still matter since that last becomes ResolveXULTreePseudoStyle in the last patch on this bug? I can move that last down to make the C++ order match the header order if desired, but would prefer to do that in the last diff to reduce merge pain if you don't have strong views about having the order correct in the intermediate states.
> Though maybe there should be a patch on top to change it to be more clearly
> for only what's left, which I think is just the tree pseudos?
I believe part 7 does this.
> Doesn't that do an entirely wasted SelectorMatches call on the
> pseudo-element selector?
No. The key is that in the pseudo-element case we do:
aRuleInfo->mSelector = aRuleInfo->mSelector->mNext;
before calling PrependRule on the rulehash for that pseudo-element. So the rules in each pseudo-element rulehash only contain the selectors up to the pseudo-element. Then we match the nsIContent the pseudo-element is for against those rules, which is exactly what we want.
Part 2 is what makes sure the mNext is non-null here; that part is pretty key.
(In reply to comment #27)
> Does that still matter since that last becomes ResolveXULTreePseudoStyle in the
> last patch on this bug? I can move that last down to make the C++ order match
> the header order if desired, but would prefer to do that in the last diff to
> reduce merge pain if you don't have strong views about having the order correct
> in the intermediate states.
Doing it another patch on top is probably best.
> > Though maybe there should be a patch on top to change it to be more clearly
> > for only what's left, which I think is just the tree pseudos?
>
> I believe part 7 does this.
Yep... hence my followup comments.
> > Doesn't that do an entirely wasted SelectorMatches call on the
> > pseudo-element selector?
>
> No. The key is that in the pseudo-element case we do:
>
> aRuleInfo->mSelector = aRuleInfo->mSelector->mNext;
>
> before calling PrependRule on the rulehash for that pseudo-element. So the
> rules in each pseudo-element rulehash only contain the selectors up to the
> pseudo-element. Then we match the nsIContent the pseudo-element is for against
> those rules, which is exactly what we want.
ah, ok
> Part 2 is what makes sure the mNext is non-null here; that part is pretty key.
Is it? Or could you then just null-check here?
Assignee | ||
Comment 29•15 years ago
|
||
I could, sort of; some of my initial work on this bug did just that. It leads to more complicated code, and in particular to being unable to just reuse ContentEnumFunc. Since the case of a "naked" pseudo-element is rather rare (with the possible exception of ::selection), the space optimization of not creating the mNext for that rare case doesn't seem worthwhile if it makes the code more complicated (and possibly slower) here.
ok
Assignee | ||
Comment 31•15 years ago
|
||
Add |const PRBool mQuirksMode| on RuleCascadeData, use |RuleHash*&|.
Assignee | ||
Comment 32•15 years ago
|
||
Attachment #409471 -
Attachment is obsolete: true
Assignee | ||
Comment 33•15 years ago
|
||
Removes the blank line; fixes the wrapping; moves ResolveXULTreePseudoStyle to the right place in the .cpp.
Assignee | ||
Comment 34•15 years ago
|
||
Attachment #415179 -
Attachment is obsolete: true
Assignee | ||
Comment 35•15 years ago
|
||
Attachment #415181 -
Flags: review?(dbaron)
Comment on attachment 415181 [details] [diff] [review]
Part 8. Reorder AddRule
r=dbaron
Attachment #415181 -
Flags: review?(dbaron) → review+
Assignee | ||
Comment 37•15 years ago
|
||
Pushed:
http://hg.mozilla.org/mozilla-central/rev/696a4ad5d011
http://hg.mozilla.org/mozilla-central/rev/909cbe6e8979
http://hg.mozilla.org/mozilla-central/rev/5c675fda7ba6
http://hg.mozilla.org/mozilla-central/rev/05b655b218dd
http://hg.mozilla.org/mozilla-central/rev/aa21350b7c67
http://hg.mozilla.org/mozilla-central/rev/95a7468a8a8e
http://hg.mozilla.org/mozilla-central/rev/c6665a0ce75d
http://hg.mozilla.org/mozilla-central/rev/9c8bd114fd20
with a slight change to part 2 to not use pseudoElementType if pseudoElement is null.
Status: NEW → RESOLVED
Closed: 15 years ago
Resolution: --- → FIXED
(In reply to comment #37)
> with a slight change to part 2 to not use pseudoElementType if pseudoElement is
> null.
Though I wonder if it would have made more sense to initialize pseudoElementType instead (to NotPseudoElement, I presume).
Assignee | ||
Comment 39•15 years ago
|
||
Hmm. Yeah, ok. That would make sense too. I'll change to that.
Assignee | ||
Comment 40•15 years ago
|
||
Pushed http://hg.mozilla.org/mozilla-central/rev/5d2775cdebc8 with that change.
You need to log in
before you can comment on or make changes to this bug.
Description
•