mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-22 10:27:03 +00:00
Bug 407889. Reduce dynamic memory allocations by putting nsDisplayListBuilder's per-presshell state in an nsAutoTArray. r+sr=mats
This commit is contained in:
parent
e8fc029ca5
commit
95e3dcb532
@ -132,9 +132,10 @@ static void UnmarkFrameForDisplay(nsIFrame* aFrame) {
|
||||
}
|
||||
|
||||
nsDisplayListBuilder::~nsDisplayListBuilder() {
|
||||
for (PRUint32 i = 0; i < mFramesMarkedForDisplay.Length(); ++i) {
|
||||
UnmarkFrameForDisplay(mFramesMarkedForDisplay[i]);
|
||||
}
|
||||
NS_ASSERTION(mFramesMarkedForDisplay.Length() == 0,
|
||||
"All frames should have been unmarked");
|
||||
NS_ASSERTION(mPresShellStates.Length() == 0,
|
||||
"All presshells should have been exited");
|
||||
|
||||
PL_FreeArenaPool(&mPool);
|
||||
PL_FinishArenaPool(&mPool);
|
||||
@ -142,57 +143,58 @@ nsDisplayListBuilder::~nsDisplayListBuilder() {
|
||||
|
||||
nsICaret *
|
||||
nsDisplayListBuilder::GetCaret() {
|
||||
NS_ASSERTION(mCaretStates.Length() > 0, "Not enough presshells");
|
||||
|
||||
nsIFrame* frame = GetCaretFrame();
|
||||
if (!frame) {
|
||||
return nsnull;
|
||||
}
|
||||
nsIPresShell* shell = frame->PresContext()->PresShell();
|
||||
nsCOMPtr<nsICaret> caret;
|
||||
shell->GetCaret(getter_AddRefs(caret));
|
||||
|
||||
CurrentPresShellState()->mPresShell->GetCaret(getter_AddRefs(caret));
|
||||
return caret;
|
||||
}
|
||||
|
||||
void
|
||||
nsDisplayListBuilder::EnterPresShell(nsIFrame* aReferenceFrame,
|
||||
const nsRect& aDirtyRect) {
|
||||
PresShellState* state = mPresShellStates.AppendElement();
|
||||
if (!state)
|
||||
return;
|
||||
state->mPresShell = aReferenceFrame->PresContext()->PresShell();
|
||||
state->mCaretFrame = nsnull;
|
||||
state->mFirstFrameMarkedForDisplay = mFramesMarkedForDisplay.Length();
|
||||
|
||||
if (!mBuildCaret)
|
||||
return;
|
||||
|
||||
nsIPresShell* shell = aReferenceFrame->PresContext()->PresShell();
|
||||
nsCOMPtr<nsICaret> caret;
|
||||
shell->GetCaret(getter_AddRefs(caret));
|
||||
nsIFrame* frame = caret->GetCaretFrame();
|
||||
state->mPresShell->GetCaret(getter_AddRefs(caret));
|
||||
state->mCaretFrame = caret->GetCaretFrame();
|
||||
|
||||
if (frame) {
|
||||
if (state->mCaretFrame) {
|
||||
// Check if the dirty rect intersects with the caret's dirty rect.
|
||||
nsRect caretRect =
|
||||
caret->GetCaretRect() + frame->GetOffsetTo(aReferenceFrame);
|
||||
caret->GetCaretRect() + state->mCaretFrame->GetOffsetTo(aReferenceFrame);
|
||||
if (caretRect.Intersects(aDirtyRect)) {
|
||||
// Okay, our rects intersect, let's mark the frame and all of its ancestors.
|
||||
mFramesMarkedForDisplay.AppendElement(frame);
|
||||
MarkFrameForDisplay(frame, nsnull);
|
||||
mFramesMarkedForDisplay.AppendElement(state->mCaretFrame);
|
||||
MarkFrameForDisplay(state->mCaretFrame, nsnull);
|
||||
}
|
||||
}
|
||||
|
||||
mCaretStates.AppendElement(frame);
|
||||
}
|
||||
|
||||
void
|
||||
nsDisplayListBuilder::LeavePresShell(nsIFrame* aReferenceFrame,
|
||||
const nsRect& aDirtyRect)
|
||||
{
|
||||
if (!mBuildCaret)
|
||||
if (CurrentPresShellState()->mPresShell != aReferenceFrame->PresContext()->PresShell()) {
|
||||
// Must have not allocated a state for this presshell, presumably due
|
||||
// to OOM.
|
||||
return;
|
||||
}
|
||||
|
||||
// Pop the state off.
|
||||
NS_ASSERTION(mCaretStates.Length() > 0, "Leaving too many PresShell");
|
||||
NS_ASSERTION(GetCaret() || GetCaretFrame() == nsnull,
|
||||
"GetCaret and LeavePresShell diagree");
|
||||
|
||||
mCaretStates.SetLength(mCaretStates.Length() - 1);
|
||||
// Unmark and pop off the frames marked for display in this pres shell.
|
||||
PRUint32 firstFrameForShell = CurrentPresShellState()->mFirstFrameMarkedForDisplay;
|
||||
for (PRUint32 i = firstFrameForShell;
|
||||
i < mFramesMarkedForDisplay.Length(); ++i) {
|
||||
UnmarkFrameForDisplay(mFramesMarkedForDisplay[i]);
|
||||
}
|
||||
mFramesMarkedForDisplay.SetLength(firstFrameForShell);
|
||||
mPresShellStates.SetLength(mPresShellStates.Length() - 1);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -226,11 +226,7 @@ public:
|
||||
* If the caret is currently invisible, this will be null.
|
||||
*/
|
||||
nsIFrame* GetCaretFrame() {
|
||||
if (mBuildCaret) {
|
||||
NS_ASSERTION(mCaretStates.Length() > 0, "Not enough presshells");
|
||||
return mCaretStates[mCaretStates.Length() - 1];
|
||||
}
|
||||
return nsnull;
|
||||
return CurrentPresShellState()->mCaretFrame;
|
||||
}
|
||||
/**
|
||||
* Get the caret associated with the current presshell.
|
||||
@ -290,18 +286,29 @@ private:
|
||||
// it. Don't let us be heap-allocated!
|
||||
void* operator new(size_t sz) CPP_THROW_NEW;
|
||||
|
||||
nsIFrame* mReferenceFrame;
|
||||
nsIFrame* mMovingFrame;
|
||||
nsIFrame* mIgnoreScrollFrame;
|
||||
PLArenaPool mPool;
|
||||
nsCOMPtr<nsISelection> mBoundingSelection;
|
||||
nsTArray<nsIFrame*> mCaretStates;
|
||||
nsTArray<nsIFrame*> mFramesMarkedForDisplay;
|
||||
PRPackedBool mBuildCaret;
|
||||
PRPackedBool mEventDelivery;
|
||||
PRPackedBool mIsBackgroundOnly;
|
||||
PRPackedBool mIsAtRootOfPseudoStackingContext;
|
||||
PRPackedBool mPaintAllFrames;
|
||||
struct PresShellState {
|
||||
nsIPresShell* mPresShell;
|
||||
nsIFrame* mCaretFrame;
|
||||
PRUint32 mFirstFrameMarkedForDisplay;
|
||||
};
|
||||
PresShellState* CurrentPresShellState() {
|
||||
NS_ASSERTION(mPresShellStates.Length() > 0,
|
||||
"Someone forgot to enter a presshell");
|
||||
return &mPresShellStates[mPresShellStates.Length() - 1];
|
||||
}
|
||||
|
||||
nsIFrame* mReferenceFrame;
|
||||
nsIFrame* mMovingFrame;
|
||||
nsIFrame* mIgnoreScrollFrame;
|
||||
PLArenaPool mPool;
|
||||
nsCOMPtr<nsISelection> mBoundingSelection;
|
||||
nsAutoTArray<PresShellState,8> mPresShellStates;
|
||||
nsAutoTArray<nsIFrame*,100> mFramesMarkedForDisplay;
|
||||
PRPackedBool mBuildCaret;
|
||||
PRPackedBool mEventDelivery;
|
||||
PRPackedBool mIsBackgroundOnly;
|
||||
PRPackedBool mIsAtRootOfPseudoStackingContext;
|
||||
PRPackedBool mPaintAllFrames;
|
||||
};
|
||||
|
||||
class nsDisplayItem;
|
||||
|
Loading…
x
Reference in New Issue
Block a user