Created attachment 457556 [details]
See testcase, which crashes current trunk build, after you've resized the browser window.
0 xul.dll IsPercentageAware layout/generic/nsLineLayout.cpp:671
1 mozcrt19.dll arena_malloc_small obj-firefox/memory/jemalloc/crtsrc/jemalloc.c:3734
2 mozcrt19.dll malloc obj-firefox/memory/jemalloc/crtsrc/jemalloc.c:5811
3 xul.dll nsTArray_base::EnsureCapacity obj-firefox/xpcom/build/nsTArray.cpp:76
4 xul.dll xul.dll@0xbcb30f
5 xul.dll nsContinuingTextFrame::Init
6 xul.dll xul.dll@0x86e8f
7 xul.dll PL_DHashTableOperate obj-firefox/xpcom/build/pldhash.c:625
8 xul.dll mozilla::FramePropertyTable::Remove layout/base/FramePropertyTable.cpp:148
9 xul.dll mozilla::FrameProperties::Remove obj-firefox/dist/include/FramePropertyTable.h:230
10 xul.dll nsContainerFrame::StealOverflowFrames layout/generic/nsContainerFrame.h:623
11 xul.dll nsLineLayout::BeginSpan layout/generic/nsLineLayout.cpp:435
12 xul.dll nsFirstLetterFrame::Reflow layout/generic/nsFirstLetterFrame.cpp:234
Oh, this is exciting. The immediate cause of the crash is that we pass a null frame pointer to IsPercentageAware. And that happens because the nsFirstLetterFrame has no textframe kid but nsFirstLetterFrame::Reflow assumes |kid| is non-null.
Looking at the frame tree, it looks like we have a block frame for the <td> which has a Letter frame containing the first 'm' on the first line. That Letter frame has a continuation (containing " m"), and that has another continuation (containing " m"). This last also has an overflow list containing the single textframe with "m\u0639" in it, and a next-continuation which is a Letter frame with no kid which has _another_ next-continuation which is a Letter frame with no kid.
We're reflowing this last letter frame.
So it looks like we somehow failed to reflow the Letter frame that should have pulled stuff off the overflow list and destroyed that last empty continuation, right?
There were 122 reported crash incidents for IsPercentageAware in the past
two week period. I think we should wallpaper (with an assert) the case
where kid == NULL until we think we have fixed this.
Created attachment 507762 [details] [diff] [review]
I don't think this is needed though, because I have found the real bug....
Created attachment 507764 [details] [diff] [review]
After reflowing a first-letter child frame we have
NS_FRAME_IS_COMPLETE(aReflowStatus) and thus we delete all the kid's
This makes a bunch of |this| next-in-flows empty and nsLineLayout::ReflowFrame
only deletes the next-in-flows in the !NS_INLINE_IS_BREAK_BEFORE case
the else-clause just pushes the frame and leaves the empty first-letter
Let me know if you want the wallpaper as well. I don't think it should
Isn't the nsLineLayout code a bogus optimization? I think it should always delete the next-in-flows of the child even if NS_INLINE_IS_BREAK_BEFORE.
Created attachment 510662 [details] [diff] [review]
The crashtest triggers a couple of:
###!!! ASSERTION: Computed overflow area must contain frame bounds: 'aNewSize.width == 0 || aNewSize.height == 0 || aOverflowAreas.Overflow(otype).Contains(nsRect(nsPoint(0,0), aNewSize))', file layout/generic/nsFrame.cpp, line 6144
I'll file that separately. (TryServer results pending...)
I collected some statistics (loading Alexa top 500 sites).
~7% of nsLineLayout::ReflowFrame calls ends up in the else-block,
of those ~1.7% has a next-in-flow. In other words, only 0.01% of
nsLineLayout::ReflowFrame calls are affected by the "optimization".
Fwiw, I did a quick hack marking frames where we delete next-in-flows
(in the else-block) and then counting them in
About 96% did call CreateContinuingFrame.
Created attachment 510663 [details] [diff] [review]
Load the right test file...
+ parent->DeleteNextInFlowChild(mPresContext, kidNextInFlow,
Shouldn't we just be passing "true" for aDeletingEmptyFrames?
If I pass PR_TRUE then nsLayoutUtils::AssertTreeOnlyEmptyNextInFlows says
###!!! ASSERTION: frame tree not empty, but caller reported complete status: 'start == end || IsInLetterFrame(aSubtreeRoot)', file layout/base/nsLayoutUtils.cpp, line 3964
when loading layout/generic/crashtests/586806-1.html
Created attachment 512154 [details]
reduced testcase for the assertion in comment 11
This is a reduced testcase based on layout/generic/crashtests/586806-1.htm
Created attachment 512155 [details]
frame dump + stack for the reduced testcase
Created attachment 546633 [details]
frame dump #2
Here's a little more detail on what happens leading up the assertion
Where reflowing an inline, 0x7fffd7c353e0 (lime). It calls
ReflowInlineFrame on its text frame child 0x7fffd7c35450 (yellow)
and the resulting status is INLINE_IS_BREAK_BEFORE, here:
so we break out of the loop and don't reflow any more child frames.
Returning to nsLineLayout::ReflowFrame we now have a reflow status
this is INLINE_IS_BREAK_BEFORE and FRAME_IS_COMPLETE.
The previous patch removed the next-in-flow (blue) for the inline (lime)
which caused the assertion, since text frame (red) maps content.
I think removing the next-in-flow in this case is wrong -- when the
reflow status is INLINE_IS_BREAK_BEFORE whether it's also COMPLETE
or INCOMPLETE is irrelevant since we haven't even tried to reflow
all the child frames yet.
I think the real bug is in nsFirstLetterFrame::Reflow (see comment 6)
which caused these first-letter frame continuations to be empty in the
Created attachment 546634 [details] [diff] [review]
fix v3 (wdiff)
Don't mess with next-in-flows when the status is INLINE_IS_BREAK_BEFORE.
Comment on attachment 546634 [details] [diff] [review]
fix v3 (wdiff)
Review of attachment 546634 [details] [diff] [review]: