⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 221139 in webkit


Ignore:
Timestamp:
Aug 24, 2017, 9:37:53 AM (9 years ago)
Author:
Darin Adler
Message:
REGRESSION (r220052): ASSERTION FAILED: !frame().isMainFrame()
!needsStyleRecalcOrLayout() in WebCore::FrameView::updateLayoutAndStyleIfNeededRecursive()

​https://bugs.webkit.org/show_bug.cgi?id=175270

Reviewed by Simon Fraser.

Source/WebCore:

  • dom/Document.cpp:

(WebCore::Document::Document): Initialize m_styleRecalcTimer with a lamdba so it can work
with a function that returns a bool and ignore the return value.
(WebCore::Document::updateStyleIfNeeded): Added a boolean return value indicating if the
function did any work or not.

  • dom/Document.h: Updated for above change.
  • page/FrameView.cpp:

(WebCore::appendRenderedChildren): Added helper that will later replace the
FrameView::renderedChildFrameViews function and is used below.
(WebCore::FrameView::updateLayoutAndStyleIfNeededRecursive): Instead of always doing two
passes of style and layout update do up to four passes, but stop as soon as a pass does
no work. This is slightly more efficient in cases where no layout and style update is
needed, and works correctly when a third pass is needed, which is what happens in the
test that was failing. We can eventually improve this further, but this resolves the
immediate problem we are seeing in the test.

LayoutTests:

  • platform/mac-wk2/TestExpectations: Re-enable the disabled test.
Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r221134 r221139  
     12017-08-22  Darin Adler  <darin@apple.com>
     2
     3        REGRESSION (r220052): ASSERTION FAILED: !frame().isMainFrame() || !needsStyleRecalcOrLayout()  in WebCore::FrameView::updateLayoutAndStyleIfNeededRecursive()
     4        https://bugs.webkit.org/show_bug.cgi?id=175270
     5
     6        Reviewed by Simon Fraser.
     7
     8        * platform/mac-wk2/TestExpectations: Re-enable the disabled test.
     9
    1102017-08-24  Ms2ger  <Ms2ger@igalia.com>
    211
  • trunk/LayoutTests/platform/mac-wk2/TestExpectations

    r221115 r221139  
    753753webkit.org/b/173946 [ Debug ] media/modern-media-controls/fullscreen-support/fullscreen-support-press.html [ Pass Failure ]
    754754
    755 webkit.org/b/175270 [ Debug ] plugins/crash-restoring-plugin-page-from-page-cache.html [ Skip ]
    756 
    757755# CSS Regions are being phased out.
    758756tiled-drawing/scrolling/non-fast-region/wheel-handler-in-region.html [ Skip ]
  • trunk/Source/WebCore/ChangeLog

    r221135 r221139  
     12017-08-22  Darin Adler  <darin@apple.com>
     2
     3        REGRESSION (r220052): ASSERTION FAILED: !frame().isMainFrame() || !needsStyleRecalcOrLayout()  in WebCore::FrameView::updateLayoutAndStyleIfNeededRecursive()
     4        https://bugs.webkit.org/show_bug.cgi?id=175270
     5
     6        Reviewed by Simon Fraser.
     7
     8        * dom/Document.cpp:
     9        (WebCore::Document::Document): Initialize m_styleRecalcTimer with a lamdba so it can work
     10        with a function that returns a bool and ignore the return value.
     11        (WebCore::Document::updateStyleIfNeeded): Added a boolean return value indicating if the
     12        function did any work or not.
     13        * dom/Document.h: Updated for above change.
     14
     15        * page/FrameView.cpp:
     16        (WebCore::appendRenderedChildren): Added helper that will later replace the
     17        FrameView::renderedChildFrameViews function and is used below.
     18        (WebCore::FrameView::updateLayoutAndStyleIfNeededRecursive): Instead of always doing two
     19        passes of style and layout update do up to four passes, but stop as soon as a pass does
     20        no work. This is slightly more efficient in cases where no layout and style update is
     21        needed, and works correctly when a third pass is needed, which is what happens in the
     22        test that was failing. We can eventually improve this further, but this resolves the
     23        immediate problem we are seeing in the test.
     24
    1252017-08-24  Don Olmstead  <don.olmstead@sony.com>
    226
  • trunk/Source/WebCore/dom/Document.cpp

    r221014 r221139  
    461461    , m_visitedLinkState(std::make_unique<VisitedLinkState>(*this))
    462462    , m_markers(std::make_unique<DocumentMarkerController>(*this))
    463     , m_styleRecalcTimer(*this, &Document::updateStyleIfNeeded)
     463    , m_styleRecalcTimer([this] { updateStyleIfNeeded(); })
    464464    , m_updateFocusAppearanceTimer(*this, &Document::updateFocusAppearanceTimerFired)
    465465    , m_documentCreationTime(MonotonicTime::now())
    … …  
    18881888}
    18891889
    1890 void Document::updateStyleIfNeeded()
     1890bool Document::updateStyleIfNeeded()
    18911891{
    18921892    ASSERT(isMainThread());
    … …  
    18941894
    18951895    if (!view() || view()->isInRenderTreeLayout())
    1896         return;
     1896        return false;
    18971897
    18981898    styleScope().flushPendingUpdate();
    18991899
    19001900    if (!needsStyleRecalc())
    1901         return;
     1901        return false;
    19021902
    19031903    resolveStyle();
     1904    return true;
    19041905}
    19051906
  • trunk/Source/WebCore/dom/Document.h

    r221014 r221139  
    545545    enum class ResolveStyleType { Normal, Rebuild };
    546546    void resolveStyle(ResolveStyleType = ResolveStyleType::Normal);
    547     WEBCORE_EXPORT void updateStyleIfNeeded();
     547    WEBCORE_EXPORT bool updateStyleIfNeeded();
    548548    bool needsStyleRecalc() const;
    549549    unsigned lastStyleUpdateSizeForTesting() const { return m_lastStyleUpdateSizeForTesting; }
  • trunk/Source/WebCore/page/FrameView.cpp

    r220812 r221139  
    45764576}
    45774577
     4578static void appendRenderedChildren(FrameView& view, Deque<Ref<FrameView>, 16>& deque)
     4579{
     4580    for (Frame* frame = view.frame().tree().firstRenderedChild(); frame; frame = frame->tree().nextRenderedSibling()) {
     4581        if (frame->view())
     4582            deque.append(*frame->view());
     4583    }
     4584}
     4585
     4586// FIXME: Change the one remaining caller of this to use appendRenderedChildren above instead,
     4587// and then remove FrameViewList and renderedChildFrameViews.
    45784588FrameView::FrameViewList FrameView::renderedChildFrameViews() const
    45794589{
    … …  
    45894599void FrameView::updateLayoutAndStyleIfNeededRecursive()
    45904600{
    4591     // We have to crawl our entire tree looking for any FrameViews that need
    4592     // layout and make sure they are up to date.
    4593     // Mac actually tests for intersection with the dirty region and tries not to
    4594     // update layout for frames that are outside the dirty region.  Not only does this seem
    4595     // pointless (since those frames will have set a zero timer to layout anyway), but
    4596     // it is also incorrect, since if two frames overlap, the first could be excluded from the dirty
    4597     // region but then become included later by the second frame adding rects to the dirty region
    4598     // when it lays out.
     4601    // The number "4" here is empirically determined as the number of passes needed to
     4602    // make sure we don't need more style recalculation or layout; we have not seen a
     4603    // case where we need more than 3 passes, so 4 is a bit more than needed in any
     4604    // normal case. But it's not clear that anything prevents an indefinite number of
     4605    // passes from being needed. So it would be better to instead have a firm guarantee
     4606    // of the number of times this needs to be done, or come up with a way to do this
     4607    // in one pass without a loop.
     4608    const unsigned maxUpdatePasses = 4;
    45994609
    46004610    AnimationUpdateBlock animationUpdateBlock(&frame().animation());
    46014611
    4602     frame().document()->updateStyleIfNeeded();
    4603 
    4604     if (needsLayout())
    4605         layout();
    4606 
    4607     // Grab a copy of the child views, as the list may be mutated by the following updateLayoutAndStyleIfNeededRecursive
    4608     // calls, as they can potentially re-enter a layout of the parent frame view.
    4609     for (auto& frameView : renderedChildFrameViews())
    4610         frameView->updateLayoutAndStyleIfNeededRecursive();
    4611 
    4612     // A child frame may have dirtied us during its layout.
    4613     frame().document()->updateStyleIfNeeded();
    4614     if (needsLayout())
    4615         layout();
    4616 
     4612    auto updateOnce = [this] {
     4613        auto updateOneFrame = [] (FrameView& view) {
     4614            bool didWork = view.frame().document()->updateStyleIfNeeded();
     4615            if (view.needsLayout()) {
     4616                view.layout();
     4617                didWork = true;
     4618            }
     4619            return didWork;
     4620        };
     4621
     4622        bool didWork = false;
     4623
     4624        // Use a copy of the child frame list because it can change while updating.
     4625        Deque<Ref<FrameView>, 16> views;
     4626        views.append(*this);
     4627        while (!views.isEmpty()) {
     4628            auto view = views.takeFirst();
     4629            if (updateOneFrame(view.get()))
     4630                didWork = true;
     4631            appendRenderedChildren(view.get(), views);
     4632        }
     4633
     4634        return didWork;
     4635    };
     4636
     4637    for (unsigned i = 0; i < maxUpdatePasses; ++i) {
     4638        if (!updateOnce())
     4639            break;
     4640    }
     4641
     4642    // FIXME: Unclear why it's appropriate to skip this assertion for non-main frames.
     4643    // The need for this may be obsolete and a leftover from when this fucntion was
     4644    // implemented by recursively calling itself.
    46174645    ASSERT(!frame().isMainFrame() || !needsStyleRecalcOrLayout());
    46184646}
Note: See TracChangeset for help on using the changeset viewer.