Bug 92196 - ASSERTION FAILED: !needsLayout() : virtual void WebCore::RenderView::paint(WebCore::PaintInfo &, const LayoutPoint &)
Summary: ASSERTION FAILED: !needsLayout() : virtual void WebCore::RenderView::paint(We...
Status: RESOLVED WORKSFORME
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebCore JavaScript (show other bugs)
Version: 528+ (Nightly build)
Hardware: Mac (Intel) Other
: P2 Normal
Assignee: Nobody
URL: http://www.browsertests.com/test.php?...
Keywords:
Depends on:
Blocks:
 
Reported: 2012-07-24 19:29 PDT by Dimitris Apostolou
Modified: 2015-11-05 02:54 PST (History)
3 users (show)

See Also:


Attachments
reduced test case (14.90 KB, text/html)
2012-09-21 12:12 PDT, zalan
no flags Details
reduced test case 2. (now without text) (558 bytes, text/html)
2012-10-01 04:30 PDT, zalan
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Dimitris Apostolou 2012-07-24 19:29:46 PDT
r123549

Reproducibility: once

Steps:
1. Go to http://www.browsertests.com/test.php?sMode=browserbuster&sCode=66&sTemplate=browserbuster&URL=http://www.kyoto-np.co.jp/&uiSequance=&bReversed=
2. Click on right arrow on top left corner of webpage to load to next site (will be MSN Japan).
3. After MSN Japan loads, hit Safari "Back" button.

What happened:
ASSERTION FAILED: !needsLayout()
/Users/rex/WebKit/Source/WebCore/rendering/RenderView.cpp(257) : virtual void WebCore::RenderView::paint(WebCore::PaintInfo &, const LayoutPoint &)
1   0x106b21c19 WebCore::RenderView::paint(WebCore::PaintInfo&, WebCore::FractionalLayoutPoint const&)
2   0x1069b9116 WebCore::RenderLayer::paintLayerContents(WebCore::RenderLayer*, WebCore::GraphicsContext*, WebCore::FractionalLayoutRect const&, unsigned int, WebCore::RenderObject*, WebCore::RenderRegion*, WTF::HashMap<WebCore::OverlapTestRequestClient*, WebCore::IntRect, WTF::PtrHash<WebCore::OverlapTestRequestClient*>, WTF::HashTraits<WebCore::OverlapTestRequestClient*>, WTF::HashTraits<WebCore::IntRect> >*, unsigned int)
3   0x1069d5bca WebCore::RenderLayerBacking::paintIntoLayer(WebCore::RenderLayer*, WebCore::GraphicsContext*, WebCore::IntRect const&, unsigned int, WebCore::GraphicsLayerPaintingPhase, WebCore::RenderObject*)
4   0x1069d5e84 WebCore::RenderLayerBacking::paintContents(WebCore::GraphicsLayer const*, WebCore::GraphicsContext&, WebCore::GraphicsLayerPaintingPhase, WebCore::IntRect const&)
5   0x105ec2420 WebCore::GraphicsLayer::paintGraphicsLayerContents(WebCore::GraphicsContext&, WebCore::IntRect const&)
6   0x105eca8a0 WebCore::GraphicsLayerCA::platformCALayerPaintContents(WebCore::GraphicsContext&, WebCore::IntRect const&)
7   0x105eca8e7 non-virtual thunk to WebCore::GraphicsLayerCA::platformCALayerPaintContents(WebCore::GraphicsContext&, WebCore::IntRect const&)
8   0x106f77cb7 __drawLayerContents_block_invoke_0
9   0x103dd824b WKCALayerEnumerateRectsBeingDrawnWithBlock
10  0x106f7754c drawLayerContents(CGContext*, CALayer*, WebCore::PlatformCALayer*)
11  0x106f92446 -[WebTiledLayer drawInContext:]
12  0x7fff95305675 tiled_layer_render(_CAImageProvider*, unsigned int, unsigned int, unsigned int, unsigned int, void*)
13  0x7fff95243a21 CAImageProviderThread(unsigned int*, bool)
14  0x7fff9522ed51 CA::timer_callback(__CFRunLoopTimer*, void*)
15  0x7fff933984b4 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__
16  0x7fff93397fcd __CFRunLoopDoTimer
17  0x7fff9337d7b9 __CFRunLoopRun
18  0x7fff9337cdd2 CFRunLoopRunSpecific
19  0x7fff96784774 RunCurrentEventLoopInMode
20  0x7fff96784512 ReceiveNextEventCommon
21  0x7fff967843a3 BlockUntilNextEventMatchingListInMode
22  0x7fff90c2dfa3 _DPSNextEvent
23  0x7fff90c2d862 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:]
24  0x7fff90c24c03 -[NSApplication run]
25  0x106b73cfc WebCore::RunLoop::run()
26  0x103d552e8 WebKit::WebProcessMain(WebKit::CommandLine const&)
27  0x103c68ad8 WebKitMain(WebKit::CommandLine const&)
28  0x103c689f4 WebKitMain
29  0x103a22da2 main
30  0x7fff907647e1 start
31  0x8

Expected result:
No assert failure.
Comment 2 zalan 2012-09-21 12:12:33 PDT
Created attachment 165171 [details]
reduced test case

canvas + div + long text in an iframe.
Comment 3 zalan 2012-10-01 04:30:58 PDT
Created attachment 166448 [details]
reduced test case 2. (now without text)
Comment 4 zalan 2012-10-01 05:24:26 PDT
It looks like when WebTiledLayer (inherited from CATiledLayer) is used to render the content, painting operation is not guaranteed to happen on a clean tree. 

what normally happens with a CALayer based surface rendering
1, js initiates layout change and layout is scheduled 
2, layout is executed
3, painting is initiated by calling TiledCoreAnimationDrawingArea::flushLayers()
4, flush calls WebTiledLayer::setNeedsDisplayInRect() (and it also calls layoutifneeded to make sure of a clean tree)
5, in setNeedDisplayInRect, CATiledLayer schedules a callback to ::display to render the content -presumably with a 0 timer to make sure no other timer can be fired between this and rendering -like a js timer to change content) 
6, ::display is called and it directly calls into ::drawInContext ->rendering
7, js initiates layout change...   

and how it is different from a CATiledLayer based surface rendering (now that the content height is over 2000px)
1, js initiates layout change and layout is scheduled 
2, layout is executed
3, painting is initiated by calling TiledCoreAnimationDrawingArea::flushLayers()
4, flush calls WebTiledLayer::setNeedsDisplayInRect() + layoutifneeded
5, in setNeedDisplayInRect, CATiledLayer schedules a callback to ::display
6, ::display is called but it does not call into ::drawInContent synchronously, instead it looks like it schedules a callback to it.
7, js initiates layout change and layout is scheduled 
8, ::drawInContext is called on a dirty tree -> assert.

so apparently js can get a timeslot between flush and the actual rendering and that breaks the rule of rendering always on a clean tree. 
According to the CATiledLayer documentation, due to the potentially large(r) size of rendering surface, there could be multiple calls made to render the content. I assume this 'multiple call' manner leads to the asynchronous way of initiating ::drawInContent. We should either not let any other timer fired inbetween(CA code?) or make sure right before the rendering that the content is still clean(yet another layout). (or drop the CATiledLayer completely)
Not sure if all above holds true as I've got no access to Core Animation sources, so someone with access should check this out.
Comment 5 zalan 2012-10-01 05:32:08 PDT
>Not sure if all above holds true as I've got no access to Core Animation sources, so someone with access should check this out.
Simon, git blame came back with your name on WebTiledLayer.mm. Could you check this out?
Comment 6 Simon Fraser (smfr) 2012-10-01 12:59:55 PDT
WebTiledLayer may go away, in which case this shouldn't happen any more.
Comment 7 zalan 2012-10-02 00:52:37 PDT
(In reply to comment #6)
> WebTiledLayer may go away, in which case this shouldn't happen any more.
Thanks, sounds great!
Comment 8 Renata Hodovan 2015-11-05 02:54:06 PST
All the provided test cases run without any failure now. Closing bug.