moebius#138: Optimize operations on root of deeply-nested frame tree

https://github.com/MoonchildProductions/moebius/pull/138
This commit is contained in:
janekptacijarabaci 2018-04-24 21:39:13 +02:00 committed by Roy Tam
commit 85692a1198
23 changed files with 651 additions and 40 deletions

View file

@ -154,7 +154,7 @@ RestyleManagerBase::ChangeHintToString(nsChangeHint aHint)
"NeutralChange", "InvalidateRenderingObservers",
"ReflowChangesSizeOrPosition", "UpdateComputedBSize",
"UpdateUsesOpacity", "UpdateBackgroundPosition",
"AddOrRemoveTransform"
"AddOrRemoveTransform", "CSSOverflowChange",
};
static_assert(nsChangeHint_AllHints == (1 << ArrayLength(names)) - 1,
"Name list doesn't match change hints.");
@ -1070,6 +1070,67 @@ RestyleManagerBase::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
FramePropertyTable* propTable = presContext->PropertyTable();
nsCSSFrameConstructor* frameConstructor = presContext->FrameConstructor();
// Handle nsChangeHint_CSSOverflowChange, by either updating the
// scrollbars on the viewport, or upgrading the change hint to frame-reconstruct.
for (nsStyleChangeData& data : aChangeList) {
if (data.mHint & nsChangeHint_CSSOverflowChange) {
data.mHint &= ~nsChangeHint_CSSOverflowChange;
bool doReconstruct = true; // assume the worst
// Only bother with this if we're html/body, since:
// (a) It'd be *expensive* to reframe these particular nodes. They're
// at the root, so reframing would mean rebuilding the world.
// (b) It's often *unnecessary* to reframe for "overflow" changes on
// these particular nodes. In general, the only reason we reframe
// for "overflow" changes is so we can construct (or destroy) a
// scrollframe & scrollbars -- and the html/body nodes often don't
// need their own scrollframe/scrollbars because they coopt the ones
// on the viewport (which always exist). So depending on whether
// that's happening, we can skip the reframe for these nodes.
if (data.mContent->IsAnyOfHTMLElements(nsGkAtoms::body,
nsGkAtoms::html)) {
// If the restyled element provided/provides the scrollbar styles for
// the viewport before and/or after this restyle, AND it's not coopting
// that responsibility from some other element (which would need
// reconstruction to make its own scrollframe now), THEN: we don't need
// to reconstruct - we can just reflow, because no scrollframe is being
// added/removed.
nsIContent* prevOverrideNode =
presContext->GetViewportScrollbarStylesOverrideNode();
nsIContent* newOverrideNode =
presContext->UpdateViewportScrollbarStylesOverride();
if (data.mContent == prevOverrideNode ||
data.mContent == newOverrideNode) {
// If we get here, the restyled element provided the scrollbar styles
// for viewport before this restyle, OR it will provide them after.
if (!prevOverrideNode || !newOverrideNode ||
prevOverrideNode == newOverrideNode) {
// If we get here, the restyled element is NOT replacing (or being
// replaced by) some other element as the viewport's
// scrollbar-styles provider. (If it were, we'd potentially need to
// reframe to create a dedicated scrollframe for whichever element
// is being booted from providing viewport scrollbar styles.)
//
// Under these conditions, we're OK to assume that this "overflow"
// change only impacts the root viewport's scrollframe, which
// already exists, so we can simply reflow instead of reframing.
// When requesting this reflow, we send the exact same change hints
// that "width" and "height" would send (since conceptually,
// adding/removing scrollbars is like changing the available
// space).
data.mHint |= (nsChangeHint_ReflowHintsForISizeChange |
nsChangeHint_ReflowHintsForBSizeChange);
doReconstruct = false;
}
}
}
if (doReconstruct) {
data.mHint |= nsChangeHint_ReconstructFrame;
}
}
}
// Make sure to not rebuild quote or counter lists while we're
// processing restyles
frameConstructor->BeginUpdate();