Changeset 174761 in webkit


Ignore:
Timestamp:
Oct 15, 2014 11:50:30 PM (9 years ago)
Author:
abucur@adobe.com
Message:

ASSERTION FAILED in WebCore::RenderFlowThread::getRegionRangeForBox
https://bugs.webkit.org/show_bug.cgi?id=135563

Reviewed by David Hyatt.

Source/WebCore:

The new multi-column code doesn't work correctly when the document contains nested fragmentation
contexts. The problem is the current flow thread concept that can store only one RenderFlowThread
at a time and use it during layout.

The stored flow thread is always correct for regions because named flow threads are absolutley positioned
so every child renderer is contained inside them (with the expcetion of fixed positioned elements which are
treated separately).

For multi-column elements this is no longer the case. An absolutely positioned element inside a static
multi-column element will be contained by a block outside the fragmentation context. It can even be
contained by a different multi-column element in the case of nested flow threads.

The patch below explores a solution that's not based on a current flow thread stored globally. The proposed
patch makes every block to store a pointer to its fragmentation context and a flag that states if this pointer
needs to be updated or not. If the renderer is not a block it will get its flow thread from the containing
block. Once the containing flow thread is requested for the block, the pointer is computed and cached until
invalidated:

  • when a subtree is removed from a flow thread
  • when the position property of an element inside a flow thread changes

The process is recursive and it doesn't affect elements that are not nested inside a flow thread. If a block
changes position from relative to static, any element that was contained by it can only be contained by an
ancestor of the block. This ancestor will still be outside of any flow thread. This ensures that non-fragmentation
code is not affected from a performance perspective.

The patch affects the results of the performance tests:

  • the regions layout tests have a decreased performance raging from 2% to 5-6%
  • the regions selection tests have an increased performance raging from 1-2% to 10%
  • the multicolumn layout tests (now pending review in b137687) have an increased performance

raging from 1.8% to 5%

Tests: fast/multicol/multicol-all-positioned-crash.html

fast/multicol/multicol-transform-containing-block.html

  • rendering/FlowThreadController.cpp:

(WebCore::FlowThreadController::FlowThreadController):

  • rendering/FlowThreadController.h:

(WebCore::FlowThreadController::currentRenderFlowThread): Deleted.
(WebCore::FlowThreadController::setCurrentRenderFlowThread): Deleted.

  • rendering/LayoutState.h:

(WebCore::LayoutState::currentRenderFlowThread):
(WebCore::LayoutState::setCurrentRenderFlowThread):

  • rendering/RenderBlock.cpp:

(WebCore::RenderBlockRareData::RenderBlockRareData):
(WebCore::RenderBlock::styleWillChange):
(WebCore::RenderBlock::styleDidChange):
(WebCore::RenderBlock::collapseAnonymousBoxChild):
(WebCore::RenderBlock::cachedFlowThreadContainingBlock):
(WebCore::RenderBlock::cachedFlowThreadContainingBlockNeedsUpdate):
(WebCore::RenderBlock::setCachedFlowThreadContainingBlockNeedsUpdate):
(WebCore::RenderBlock::updateCachedFlowThreadContainingBlock):
(WebCore::RenderBlock::locateFlowThreadContainingBlock):

  • rendering/RenderBlock.h:
  • rendering/RenderBlockFlow.cpp:

(WebCore::RenderBlockFlow::styleWillChange):

  • rendering/RenderBox.cpp:

(WebCore::RenderBox::borderBoxRectInRegion):

  • rendering/RenderFlowThread.cpp:

(WebCore::RenderFlowThread::layout):
(WebCore::RenderFlowThread::updateAllLayerToRegionMappings):
(WebCore::RenderFlowThread::repaintRectangleInRegions):
(WebCore::CurrentRenderFlowThreadMaintainer::CurrentRenderFlowThreadMaintainer): Deleted.
(WebCore::CurrentRenderFlowThreadMaintainer::~CurrentRenderFlowThreadMaintainer): Deleted.
(WebCore::CurrentRenderFlowThreadDisabler::CurrentRenderFlowThreadDisabler): Deleted.
(WebCore::CurrentRenderFlowThreadDisabler::~CurrentRenderFlowThreadDisabler): Deleted.

  • rendering/RenderFlowThread.h:
  • rendering/RenderLayer.cpp:

(WebCore::RenderLayer::paintLayer):
(WebCore::RenderLayer::hitTestLayer):
(WebCore::RenderLayer::mapLayerClipRectsToFragmentationLayer):
(WebCore::RenderLayer::calculateClipRects):

  • rendering/RenderObject.cpp:

(WebCore::RenderObject::showRegionsInformation):
(WebCore::RenderObject::insertedIntoTree):
(WebCore::RenderObject::removeFromRenderFlowThread):
(WebCore::RenderObject::removeFromRenderFlowThreadIncludingDescendants):
(WebCore::RenderObject::invalidateFlowThreadContainingBlockIncludingDescendants):
(WebCore::RenderObject::currentRenderNamedFlowFragment):
(WebCore::RenderObject::locateFlowThreadContainingBlock):
(WebCore::RenderObject::locateFlowThreadContainingBlockNoCache): Deleted.
(WebCore::RenderObject::removeFromRenderFlowThreadRecursive): Deleted.

  • rendering/RenderObject.h:

(WebCore::RenderObject::flowThreadContainingBlock):

  • rendering/RenderRegion.cpp:

(WebCore::RenderRegion::computeOverflowFromFlowThread):

  • rendering/RenderView.cpp:

(WebCore::RenderView::pushLayoutStateForCurrentFlowThread):
(WebCore::RenderView::popLayoutStateForCurrentFlowThread):

  • rendering/RenderView.h:

LayoutTests:

A test verifying that positioned elements inside multi-column containers don't
cause assertions or crashes.

  • fast/multicol/multicol-all-positioned-crash-expected.txt: Added.
  • fast/multicol/multicol-all-positioned-crash.html: Added.
  • fast/multicol/multicol-transform-containing-block-expected.txt: Added.
  • fast/multicol/multicol-transform-containing-block.html: Added.
Location:
trunk
Files:
4 added
17 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r174755 r174761  
     12014-10-15  Andrei Bucur  <abucur@adobe.com>
     2
     3        ASSERTION  FAILED in WebCore::RenderFlowThread::getRegionRangeForBox
     4        https://bugs.webkit.org/show_bug.cgi?id=135563
     5
     6        Reviewed by David Hyatt.
     7
     8        A test verifying that positioned elements inside multi-column containers don't
     9        cause assertions or crashes.
     10
     11        * fast/multicol/multicol-all-positioned-crash-expected.txt: Added.
     12        * fast/multicol/multicol-all-positioned-crash.html: Added.
     13        * fast/multicol/multicol-transform-containing-block-expected.txt: Added.
     14        * fast/multicol/multicol-transform-containing-block.html: Added.
     15
    1162014-10-15  Commit Queue  <commit-queue@webkit.org>
    217
  • trunk/Source/WebCore/ChangeLog

    r174759 r174761  
     12014-10-15  Andrei Bucur  <abucur@adobe.com>
     2
     3        ASSERTION  FAILED in WebCore::RenderFlowThread::getRegionRangeForBox
     4        https://bugs.webkit.org/show_bug.cgi?id=135563
     5
     6        Reviewed by David Hyatt.
     7
     8        The new multi-column code doesn't work correctly when the document contains nested fragmentation
     9        contexts. The problem is the current flow thread concept that can store only one RenderFlowThread
     10        at a time and use it during layout.
     11
     12        The stored flow thread is always correct for regions because named flow threads are absolutley positioned
     13        so every child renderer is contained inside them (with the expcetion of fixed positioned elements which are
     14        treated separately).
     15
     16        For multi-column elements this is no longer the case. An absolutely positioned element inside a static
     17        multi-column element will be contained by a block outside the fragmentation context. It can even be
     18        contained by a different multi-column element in the case of nested flow threads.
     19
     20        The patch below explores a solution that's not based on a current flow thread stored globally. The proposed
     21        patch makes every block to store a pointer to its fragmentation context and a flag that states if this pointer
     22        needs to be updated or not. If the renderer is not a block it will get its flow thread from the containing
     23        block. Once the containing flow thread is requested for the block, the pointer is computed and cached until
     24        invalidated:
     25        - when a subtree is removed from a flow thread
     26        - when the position property of an element inside a flow thread changes
     27
     28        The process is recursive and it doesn't affect elements that are not nested inside a flow thread. If a block
     29        changes position from relative to static, any element that was contained by it can only be contained by an
     30        ancestor of the block. This ancestor will still be outside of any flow thread. This ensures that non-fragmentation
     31        code is not affected from a performance perspective.
     32
     33        The patch affects the results of the performance tests:
     34        - the regions layout tests have a decreased performance raging from 2% to 5-6%
     35        - the regions selection tests have an increased performance raging from 1-2% to 10%
     36        - the multicolumn layout tests (now pending review in b137687) have an increased performance
     37        raging from 1.8% to 5%
     38
     39        Tests: fast/multicol/multicol-all-positioned-crash.html
     40               fast/multicol/multicol-transform-containing-block.html
     41
     42        * rendering/FlowThreadController.cpp:
     43        (WebCore::FlowThreadController::FlowThreadController):
     44        * rendering/FlowThreadController.h:
     45        (WebCore::FlowThreadController::currentRenderFlowThread): Deleted.
     46        (WebCore::FlowThreadController::setCurrentRenderFlowThread): Deleted.
     47        * rendering/LayoutState.h:
     48        (WebCore::LayoutState::currentRenderFlowThread):
     49        (WebCore::LayoutState::setCurrentRenderFlowThread):
     50        * rendering/RenderBlock.cpp:
     51        (WebCore::RenderBlockRareData::RenderBlockRareData):
     52        (WebCore::RenderBlock::styleWillChange):
     53        (WebCore::RenderBlock::styleDidChange):
     54        (WebCore::RenderBlock::collapseAnonymousBoxChild):
     55        (WebCore::RenderBlock::cachedFlowThreadContainingBlock):
     56        (WebCore::RenderBlock::cachedFlowThreadContainingBlockNeedsUpdate):
     57        (WebCore::RenderBlock::setCachedFlowThreadContainingBlockNeedsUpdate):
     58        (WebCore::RenderBlock::updateCachedFlowThreadContainingBlock):
     59        (WebCore::RenderBlock::locateFlowThreadContainingBlock):
     60        * rendering/RenderBlock.h:
     61        * rendering/RenderBlockFlow.cpp:
     62        (WebCore::RenderBlockFlow::styleWillChange):
     63        * rendering/RenderBox.cpp:
     64        (WebCore::RenderBox::borderBoxRectInRegion):
     65        * rendering/RenderFlowThread.cpp:
     66        (WebCore::RenderFlowThread::layout):
     67        (WebCore::RenderFlowThread::updateAllLayerToRegionMappings):
     68        (WebCore::RenderFlowThread::repaintRectangleInRegions):
     69        (WebCore::CurrentRenderFlowThreadMaintainer::CurrentRenderFlowThreadMaintainer): Deleted.
     70        (WebCore::CurrentRenderFlowThreadMaintainer::~CurrentRenderFlowThreadMaintainer): Deleted.
     71        (WebCore::CurrentRenderFlowThreadDisabler::CurrentRenderFlowThreadDisabler): Deleted.
     72        (WebCore::CurrentRenderFlowThreadDisabler::~CurrentRenderFlowThreadDisabler): Deleted.
     73        * rendering/RenderFlowThread.h:
     74        * rendering/RenderLayer.cpp:
     75        (WebCore::RenderLayer::paintLayer):
     76        (WebCore::RenderLayer::hitTestLayer):
     77        (WebCore::RenderLayer::mapLayerClipRectsToFragmentationLayer):
     78        (WebCore::RenderLayer::calculateClipRects):
     79        * rendering/RenderObject.cpp:
     80        (WebCore::RenderObject::showRegionsInformation):
     81        (WebCore::RenderObject::insertedIntoTree):
     82        (WebCore::RenderObject::removeFromRenderFlowThread):
     83        (WebCore::RenderObject::removeFromRenderFlowThreadIncludingDescendants):
     84        (WebCore::RenderObject::invalidateFlowThreadContainingBlockIncludingDescendants):
     85        (WebCore::RenderObject::currentRenderNamedFlowFragment):
     86        (WebCore::RenderObject::locateFlowThreadContainingBlock):
     87        (WebCore::RenderObject::locateFlowThreadContainingBlockNoCache): Deleted.
     88        (WebCore::RenderObject::removeFromRenderFlowThreadRecursive): Deleted.
     89        * rendering/RenderObject.h:
     90        (WebCore::RenderObject::flowThreadContainingBlock):
     91        * rendering/RenderRegion.cpp:
     92        (WebCore::RenderRegion::computeOverflowFromFlowThread):
     93        * rendering/RenderView.cpp:
     94        (WebCore::RenderView::pushLayoutStateForCurrentFlowThread):
     95        (WebCore::RenderView::popLayoutStateForCurrentFlowThread):
     96        * rendering/RenderView.h:
     97
    1982014-10-15  Chris Dumez  <cdumez@apple.com>
    299
  • trunk/Source/WebCore/rendering/FlowThreadController.cpp

    r173765 r174761  
    4343FlowThreadController::FlowThreadController(RenderView* view)
    4444    : m_view(view)
    45     , m_currentRenderFlowThread(0)
    4645    , m_isRenderNamedFlowThreadOrderDirty(false)
    4746    , m_flowThreadsWithAutoLogicalHeightRegions(0)
  • trunk/Source/WebCore/rendering/FlowThreadController.h

    r166489 r174761  
    4949    ~FlowThreadController();
    5050
    51     RenderFlowThread* currentRenderFlowThread() const { return m_currentRenderFlowThread; }
    52     void setCurrentRenderFlowThread(RenderFlowThread* flowThread) { m_currentRenderFlowThread = flowThread; }
    53 
    5451    bool isRenderNamedFlowThreadOrderDirty() const { return m_isRenderNamedFlowThreadOrderDirty; }
    5552    void setIsRenderNamedFlowThreadOrderDirty(bool dirty)
     
    9794private:
    9895    RenderView* m_view;
    99     RenderFlowThread* m_currentRenderFlowThread;
    10096    bool m_isRenderNamedFlowThreadOrderDirty;
    10197    unsigned m_flowThreadsWithAutoLogicalHeightRegions;
  • trunk/Source/WebCore/rendering/LayoutState.h

    r168380 r174761  
    8484   
    8585    bool needsBlockDirectionLocationSetBeforeLayout() const { return m_lineGrid || (m_isPaginated && m_pageLogicalHeight); }
     86
     87    RenderFlowThread* currentRenderFlowThread() const { return m_currentRenderFlowThread; }
     88    void setCurrentRenderFlowThread(RenderFlowThread* flowThread) { m_currentRenderFlowThread = flowThread; }
     89
    8690private:
    8791    void propagateLineGridInfo(RenderBox*);
     
    123127    LayoutSize m_lineGridPaginationOrigin;
    124128
     129    RenderFlowThread* m_currentRenderFlowThread { nullptr };
     130
    125131#ifndef NDEBUG
    126132    RenderObject* m_renderer;
  • trunk/Source/WebCore/rendering/RenderBlock.cpp

    r174729 r174761  
    6969#include "TextBreakIterator.h"
    7070#include "TransformState.h"
     71
    7172#include <wtf/NeverDestroyed.h>
     73#include <wtf/Optional.h>
    7274#include <wtf/StackStats.h>
    7375#include <wtf/TemporaryChange.h>
     
    9597static TrackedContainerMap* gPositionedContainerMap = 0;
    9698static TrackedContainerMap* gPercentHeightContainerMap = 0;
    97    
     99
    98100typedef HashMap<RenderBlock*, std::unique_ptr<ListHashSet<RenderInline*>>> ContinuationOutlineTableMap;
    99101
     
    122124    WTF_MAKE_NONCOPYABLE(RenderBlockRareData); WTF_MAKE_FAST_ALLOCATED;
    123125public:
    124     RenderBlockRareData() 
     126    RenderBlockRareData()
    125127        : m_paginationStrut(0)
    126128        , m_pageLogicalOffset(0)
    127     {
     129        , m_flowThreadContainingBlock(Nullopt)
     130    {
    128131    }
    129132
    130133    LayoutUnit m_paginationStrut;
    131134    LayoutUnit m_pageLogicalOffset;
     135
     136    Optional<RenderFlowThread*> m_flowThreadContainingBlock;
    132137};
    133138
     
    267272
    268273    setReplaced(newStyle.isDisplayInlineType());
    269    
     274
    270275    if (oldStyle && parent() && diff == StyleDifferenceLayout && oldStyle->position() != newStyle.position()) {
    271276        if (newStyle.position() == StaticPosition)
     
    284289                containingBlock = containingBlock->parent();
    285290            }
    286            
     291
    287292            if (is<RenderBlock>(*containingBlock))
    288293                downcast<RenderBlock>(*containingBlock).removePositionedObjects(this, NewContainingBlock);
     
    309314void RenderBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
    310315{
     316    RenderStyle& newStyle = style();
     317
     318    bool hadTransform = hasTransform();
     319    bool flowThreadContainingBlockInvalidated = false;
     320    if (oldStyle && oldStyle->position() != newStyle.position()) {
     321        invalidateFlowThreadContainingBlockIncludingDescendants();
     322        flowThreadContainingBlockInvalidated = true;
     323    }
     324
    311325    RenderBox::styleDidChange(diff, oldStyle);
    312    
    313     RenderStyle& newStyle = style();
     326
     327    if (hadTransform != hasTransform() && !flowThreadContainingBlockInvalidated)
     328        invalidateFlowThreadContainingBlockIncludingDescendants();
    314329
    315330    if (!isAnonymousBlock()) {
     
    325340    propagateStyleToAnonymousChildren(PropagateToBlockChildrenOnly);
    326341    m_lineHeight = -1;
    327    
     342
    328343    // It's possible for our border/padding to change, but for the overall logical width of the block to
    329344    // end up being the same. We keep track of this change so in layoutBlock, we can know to set relayoutChildren=true.
     
    691706
    692707    RenderFlowThread* childFlowThread = child->flowThreadContainingBlock();
    693     CurrentRenderFlowThreadMaintainer flowThreadMaintainer(childFlowThread);
    694708    if (childFlowThread && childFlowThread->isRenderNamedFlowThread())
    695709        toRenderNamedFlowThread(childFlowThread)->removeFlowChildInfo(child);
     
    32553269}
    32563270
     3271RenderFlowThread* RenderBlock::cachedFlowThreadContainingBlock() const
     3272{
     3273    RenderBlockRareData* rareData = getRareData(this);
     3274
     3275    if (!rareData || !rareData->m_flowThreadContainingBlock)
     3276        return nullptr;
     3277
     3278    return rareData->m_flowThreadContainingBlock.value();
     3279}
     3280
     3281bool RenderBlock::cachedFlowThreadContainingBlockNeedsUpdate() const
     3282{
     3283    RenderBlockRareData* rareData = getRareData(this);
     3284
     3285    if (!rareData || !rareData->m_flowThreadContainingBlock)
     3286        return true;
     3287
     3288    return false;
     3289}
     3290
     3291void RenderBlock::setCachedFlowThreadContainingBlockNeedsUpdate()
     3292{
     3293    RenderBlockRareData& rareData = ensureRareData(this);
     3294    rareData.m_flowThreadContainingBlock = Nullopt;
     3295}
     3296
     3297RenderFlowThread* RenderBlock::updateCachedFlowThreadContainingBlock(RenderFlowThread* flowThread) const
     3298{
     3299    RenderBlockRareData& rareData = ensureRareData(this);
     3300    rareData.m_flowThreadContainingBlock = flowThread;
     3301
     3302    return flowThread;
     3303}
     3304
     3305RenderFlowThread* RenderBlock::locateFlowThreadContainingBlock() const
     3306{
     3307    RenderBlockRareData* rareData = getRareData(this);
     3308    if (!rareData || !rareData->m_flowThreadContainingBlock)
     3309        return updateCachedFlowThreadContainingBlock(RenderBox::locateFlowThreadContainingBlock());
     3310
     3311    ASSERT(rareData->m_flowThreadContainingBlock.value() == RenderBox::locateFlowThreadContainingBlock());
     3312    return rareData->m_flowThreadContainingBlock.value();
     3313}
     3314
    32573315LayoutUnit RenderBlock::paginationStrut() const
    32583316{
  • trunk/Source/WebCore/rendering/RenderBlock.h

    r174504 r174761  
    313313    virtual bool canCollapseAnonymousBlockChild() const { return true; }
    314314
     315    RenderFlowThread* cachedFlowThreadContainingBlock() const;
     316    void setCachedFlowThreadContainingBlockNeedsUpdate();
     317    virtual bool cachedFlowThreadContainingBlockNeedsUpdate() const;
     318
    315319protected:
     320    virtual RenderFlowThread* locateFlowThreadContainingBlock() const override;
    316321    virtual void willBeDestroyed() override;
    317322
     
    450455    virtual LayoutRect rectWithOutlineForRepaint(const RenderLayerModelObject* repaintContainer, LayoutUnit outlineWidth) const override final;
    451456    virtual const RenderStyle& outlineStyleForRepaint() const override final;
    452    
     457
    453458    virtual RenderElement* hoverAncestor() const override final;
    454459    virtual void updateDragState(bool dragOn) override final;
     
    489494    RenderPtr<RenderBlock> clone() const;
    490495    RenderBlock* continuationBefore(RenderObject* beforeChild);
     496
     497    RenderFlowThread* updateCachedFlowThreadContainingBlock(RenderFlowThread*) const;
    491498
    492499private:
  • trunk/Source/WebCore/rendering/RenderBlockFlow.cpp

    r174746 r174761  
    19861986        EPosition oldPosition = oldStyle->position();
    19871987        EPosition newPosition = newStyle.position();
    1988        
     1988
    19891989        if (parent() && diff == StyleDifferenceLayout && oldPosition != newPosition) {
    19901990            if (containsFloats() && !isFloating() && !isOutOfFlowPositioned() && newStyle.hasOutOfFlowPosition())
    19911991                markAllDescendantsWithFloatsForLayout();
    1992 
    1993             // If this block is inside a multicol and is moving from in-flow positioning to out-of-flow positioning,
    1994             // remove its info (such as lines-to-region mapping) from the flowthread because it won't be able to do it later.
    1995             // The flowthread will no longer be in its containing block chain and, as such, flowThreadContainingBlock will return null.
    1996             if (RenderFlowThread* flowThread = flowThreadContainingBlock(SkipFlowThreadCache)) {
    1997                 if (flowThread->isRenderMultiColumnFlowThread() && !isOutOfFlowPositioned() && (newPosition == AbsolutePosition || newPosition == FixedPosition))
    1998                     flowThread->removeFlowChildInfo(this);
    1999             }
    20001992        }
    20011993    }
  • trunk/Source/WebCore/rendering/RenderBox.cpp

    r174722 r174761  
    197197        return borderBoxRect();
    198198    }
    199    
     199
    200200    ASSERT(flowThread->regionInRange(region, startRegion, endRegion));
    201201
     
    208208    LayoutUnit logicalWidth = boxInfo->logicalWidth();
    209209    LayoutUnit logicalLeft = boxInfo->logicalLeft();
    210        
     210
    211211    // Now apply the parent inset since it is cumulative whenever anything in the containing block chain shifts.
    212212    // FIXME: Doesn't work right with perpendicular writing modes.
    213213    const RenderBlock* currentBox = containingBlock();
    214     RenderBoxRegionInfo* currentBoxInfo = currentBox->renderBoxRegionInfo(region);
     214    RenderBoxRegionInfo* currentBoxInfo = isRenderFlowThread() ? nullptr : currentBox->renderBoxRegionInfo(region);
    215215    while (currentBoxInfo && currentBoxInfo->isShifted()) {
    216216        if (currentBox->style().direction() == LTR)
     
    218218        else
    219219            logicalLeft -= (currentBox->logicalWidth() - currentBoxInfo->logicalWidth()) - currentBoxInfo->logicalLeft();
     220
     221        // Once we reach the fragmentation container we should stop.
     222        if (currentBox->isRenderFlowThread())
     223            break;
     224
    220225        currentBox = currentBox->containingBlock();
    221226        region = currentBox->clampToStartAndEndRegions(region);
    222227        currentBoxInfo = currentBox->renderBoxRegionInfo(region);
    223228    }
    224    
     229
    225230    if (cacheFlag == DoNotCacheRenderBoxRegionInfo)
    226231        delete boxInfo;
  • trunk/Source/WebCore/rendering/RenderFlowThread.cpp

    r174714 r174761  
    198198    validateRegions();
    199199
    200     CurrentRenderFlowThreadMaintainer currentFlowThreadSetter(this);
    201200    RenderBlockFlow::layout();
    202201
     
    289288        return false;
    290289
    291     // We can't use currentFlowThread as it is possible to have interleaved flow threads and the wrong one could be used.
    292     // Let each region figure out the proper enclosing flow thread.
    293     CurrentRenderFlowThreadDisabler disabler(&view());
    294 
    295290    // If the RenderFlowThread had a z-index layer update, then we need to update the composited layers too.
    296291    bool needsLayerUpdate = layer()->isDirtyRenderFlowThread() || m_layersToRegionMappingsDirty || !m_layerToRegionMap.get();
     
    389384    LayoutStateDisabler layoutStateDisabler(&view()); // We can't use layout state to repaint, since the regions are somewhere else.
    390385
    391     // We can't use currentFlowThread as it is possible to have interleaved flow threads and the wrong one could be used.
    392     // Let each region figure out the proper enclosing flow thread.
    393     CurrentRenderFlowThreadDisabler disabler(&view());
    394    
    395386    for (auto& region : m_regionList)
    396387        region->repaintFlowThreadContent(repaintRect);
     
    15231514}
    15241515
    1525 CurrentRenderFlowThreadMaintainer::CurrentRenderFlowThreadMaintainer(RenderFlowThread* renderFlowThread)
    1526     : m_renderFlowThread(renderFlowThread)
    1527     , m_previousRenderFlowThread(0)
    1528 {
    1529     if (!m_renderFlowThread)
    1530         return;
    1531     FlowThreadController& controller = m_renderFlowThread->view().flowThreadController();
    1532     m_previousRenderFlowThread = controller.currentRenderFlowThread();
    1533     // Remove the assert so we can use this to change the flow thread context.
    1534     // ASSERT(!m_previousRenderFlowThread || !renderFlowThread->isRenderNamedFlowThread());
    1535     controller.setCurrentRenderFlowThread(m_renderFlowThread);
    1536 }
    1537 
    1538 CurrentRenderFlowThreadMaintainer::~CurrentRenderFlowThreadMaintainer()
    1539 {
    1540     if (!m_renderFlowThread)
    1541         return;
    1542     FlowThreadController& controller = m_renderFlowThread->view().flowThreadController();
    1543     ASSERT(controller.currentRenderFlowThread() == m_renderFlowThread);
    1544     controller.setCurrentRenderFlowThread(m_previousRenderFlowThread);
    1545 }
    1546 
    1547 CurrentRenderFlowThreadDisabler::CurrentRenderFlowThreadDisabler(RenderView* view)
    1548     : m_view(view)
    1549     , m_renderFlowThread(0)
    1550 {
    1551     m_renderFlowThread = m_view->flowThreadController().currentRenderFlowThread();
    1552     if (m_renderFlowThread)
    1553         view->flowThreadController().setCurrentRenderFlowThread(0);
    1554 }
    1555 
    1556 CurrentRenderFlowThreadDisabler::~CurrentRenderFlowThreadDisabler()
    1557 {
    1558     if (m_renderFlowThread)
    1559         m_view->flowThreadController().setCurrentRenderFlowThread(m_renderFlowThread);
    1560 }
    1561 
    15621516
    15631517} // namespace WebCore
  • trunk/Source/WebCore/rendering/RenderFlowThread.h

    r174562 r174761  
    232232    ContainingRegionMap& containingRegionMap();
    233233
     234    virtual bool cachedFlowThreadContainingBlockNeedsUpdate() const override { return false; }
     235
    234236    // FIXME: Eventually as column and region flow threads start nesting, this may end up changing.
    235237    virtual bool shouldCheckColumnBreaks() const { return false; }
     
    244246protected:
    245247    RenderFlowThread(Document&, PassRef<RenderStyle>);
     248
     249    virtual RenderFlowThread* locateFlowThreadContainingBlock() const override { return const_cast<RenderFlowThread*>(this); }
    246250
    247251    virtual const char* renderName() const = 0;
     
    375379RENDER_OBJECT_TYPE_CASTS(RenderFlowThread, isRenderFlowThread())
    376380
    377 class CurrentRenderFlowThreadMaintainer {
    378     WTF_MAKE_NONCOPYABLE(CurrentRenderFlowThreadMaintainer);
    379 public:
    380     CurrentRenderFlowThreadMaintainer(RenderFlowThread*);
    381     ~CurrentRenderFlowThreadMaintainer();
    382 private:
    383     RenderFlowThread* m_renderFlowThread;
    384     RenderFlowThread* m_previousRenderFlowThread;
    385 };
    386 
    387 class CurrentRenderFlowThreadDisabler {
    388     WTF_MAKE_NONCOPYABLE(CurrentRenderFlowThreadDisabler);
    389 public:
    390     CurrentRenderFlowThreadDisabler(RenderView*);
    391     ~CurrentRenderFlowThreadDisabler();
    392 private:
    393     RenderView* m_view;
    394     RenderFlowThread* m_renderFlowThread;
    395 };
    396 
    397381// This structure is used by PODIntervalTree for debugging.
    398382#ifndef NDEBUG
  • trunk/Source/WebCore/rendering/RenderLayer.cpp

    r174729 r174761  
    37723772    // Don't paint the layer if the renderer doesn't belong to this region.
    37733773    // This is true as long as we clamp the range of a box to its containing block range.
    3774 
    3775     // Disable named flow region information for in flow threads such as multi-col.
    3776     std::unique_ptr<CurrentRenderFlowThreadDisabler> flowThreadDisabler;
    3777     if (enclosingPaginationLayer(ExcludeCompositedPaginatedLayers))
    3778         flowThreadDisabler = std::make_unique<CurrentRenderFlowThreadDisabler>(&renderer().view());
    3779 
    37803774    RenderNamedFlowFragment* namedFlowFragment = currentRenderNamedFlowFragment();
    37813775    if (namedFlowFragment) {
     
    48224816        return 0;
    48234817
    4824     // Disable named flow region information for in flow threads such as multi-col.
    4825     std::unique_ptr<CurrentRenderFlowThreadDisabler> flowThreadDisabler;
    4826     if (enclosingPaginationLayer(ExcludeCompositedPaginatedLayers))
    4827         flowThreadDisabler = std::make_unique<CurrentRenderFlowThreadDisabler>(&renderer().view());
    4828 
    48294818    RenderNamedFlowFragment* namedFlowFragment = currentRenderNamedFlowFragment();
    48304819
     
    52335222
    52345223    ASSERT(namedFlowFragment->parent() && namedFlowFragment->parent()->isRenderNamedFlowFragmentContainer());
    5235    
    5236     CurrentRenderFlowThreadDisabler flowThreadDisabler(&renderer().view());
     5224
    52375225    ClipRectsContext targetClipRectsContext(&namedFlowFragment->fragmentContainerLayer(), TemporaryClipRects);
    52385226    namedFlowFragment->fragmentContainerLayer().calculateClipRects(targetClipRectsContext, clipRects);
     
    67116699{
    67126700    LayoutRect regionContentBox = toRenderBox(region->layerOwner()).contentBoxRect();
    6713     CurrentRenderFlowThreadMaintainer flowThreadMaintainer(toRenderFlowThread(&renderer()));
    67146701    CurrentRenderRegionMaintainer regionMaintainer(*region);
    67156702    region->setRegionObjectsRegionStyle();
     
    68186805        hitTestRectInFlowThread.expand(LayoutSize(fabs((double)hitTestOffset.width()), fabs((double)hitTestOffset.height())));
    68196806
    6820         CurrentRenderFlowThreadMaintainer flowThreadMaintainer(flowThread);
    68216807        CurrentRenderRegionMaintainer regionMaintainer(region);
    68226808
  • trunk/Source/WebCore/rendering/RenderObject.cpp

    r174722 r174761  
    523523}
    524524
    525 RenderFlowThread* RenderObject::locateFlowThreadContainingBlockNoCache() const
    526 {
    527     ASSERT(flowThreadState() != NotInsideFlowThread);
    528 
    529     RenderObject* curr = const_cast<RenderObject*>(this);
    530     while (curr) {
    531         if (curr->isRenderFlowThread())
    532             return toRenderFlowThread(curr);
    533         curr = curr->containingBlock();
    534     }
    535     return 0;
    536 }
    537 
    538 RenderFlowThread* RenderObject::locateFlowThreadContainingBlock() const
    539 {
    540     ASSERT(flowThreadState() != NotInsideFlowThread);
    541 
    542     // See if we have the thread cached because we're in the middle of layout.
    543     RenderFlowThread* flowThread = view().flowThreadController().currentRenderFlowThread();
    544     if (flowThread && (flowThreadState() == flowThread->flowThreadState())) {
    545         // Make sure the slow path would return the same result as our cache.
    546         // FIXME: For the moment, only apply this assertion to regions, as multicol
    547         // still has some issues and triggers this assert.
    548         // Created https://bugs.webkit.org/show_bug.cgi?id=132946 for this issue.
    549         ASSERT(!flowThread->isRenderNamedFlowThread() || flowThread == locateFlowThreadContainingBlockNoCache());
    550         return flowThread;
    551     }
    552    
    553     // Not in the middle of layout so have to find the thread the slow way.
    554     return locateFlowThreadContainingBlockNoCache();
    555 }
    556 
    557525RenderBlock* RenderObject::firstLineBlock() const
    558526{
     
    14391407void RenderObject::showRegionsInformation() const
    14401408{
    1441     CurrentRenderFlowThreadDisabler flowThreadDisabler(&view());
    1442 
    14431409    if (RenderFlowThread* flowThread = flowThreadContainingBlock()) {
    14441410        const RenderBox* box = isBox() ? toRenderBox(this) : nullptr;
     
    20492015    if (!isFloating() && parent()->childrenInline())
    20502016        parent()->dirtyLinesFromChangedChild(*this);
    2051    
    2052     // We have to unset the current layout RenderFlowThread here, since insertedIntoTree() can happen in
    2053     // the middle of layout but for objects inside a nested flow thread that is still being populated. This
    2054     // will cause an accurate crawl to happen in order to ensure that the right flow thread is notified.
    2055     RenderFlowThread* previousThread = view().flowThreadController().currentRenderFlowThread();
    2056     view().flowThreadController().setCurrentRenderFlowThread(nullptr);
    2057     if (parent()->isRenderFlowThread())
    2058         toRenderFlowThread(parent())->flowThreadDescendantInserted(this);
    2059     else if (RenderFlowThread* flowThread = parent()->flowThreadContainingBlock())
     2017
     2018    if (RenderFlowThread* flowThread = flowThreadContainingBlock())
    20602019        flowThread->flowThreadDescendantInserted(this);
    2061     view().flowThreadController().setCurrentRenderFlowThread(previousThread);
    20622020}
    20632021
     
    20762034    if (flowThreadState() == NotInsideFlowThread)
    20772035        return;
    2078    
     2036
    20792037    // Sometimes we remove the element from the flow, but it's not destroyed at that time.
    2080     // It's only until later when we actually destroy it and remove all the children from it. 
     2038    // It's only until later when we actually destroy it and remove all the children from it.
    20812039    // Currently, that happens for firstLetter elements and list markers.
    20822040    // Pass in the flow thread so that we don't have to look it up for all the children.
    2083     removeFromRenderFlowThreadRecursive(flowThreadContainingBlock());
    2084 }
    2085 
    2086 void RenderObject::removeFromRenderFlowThreadRecursive(RenderFlowThread* renderFlowThread)
    2087 {
     2041    removeFromRenderFlowThreadIncludingDescendants(true);
     2042}
     2043
     2044void RenderObject::removeFromRenderFlowThreadIncludingDescendants(bool shouldUpdateState)
     2045{
     2046    // Once we reach another flow thread we don't need to update the flow thread state
     2047    // but we have to continue cleanup the flow thread info.
     2048    if (isRenderFlowThread())
     2049        shouldUpdateState = false;
     2050
    20882051    for (RenderObject* child = firstChildSlow(); child; child = child->nextSibling())
    2089         child->removeFromRenderFlowThreadRecursive(renderFlowThread);
    2090 
    2091     RenderFlowThread* localFlowThread = renderFlowThread;
    2092     if (flowThreadState() == InsideInFlowThread)
    2093         localFlowThread = flowThreadContainingBlock(); // We have to ask. We can't just assume we are in the same flow thread.
    2094     if (localFlowThread)
    2095         localFlowThread->removeFlowChildInfo(this);
    2096     setFlowThreadState(NotInsideFlowThread);
     2052        child->removeFromRenderFlowThreadIncludingDescendants(shouldUpdateState);
     2053
     2054    // We have to ask for our containing flow thread as it may be above the removed sub-tree.
     2055    RenderFlowThread* flowThreadContainingBlock = this->flowThreadContainingBlock();
     2056    if (flowThreadContainingBlock)
     2057        flowThreadContainingBlock->removeFlowChildInfo(this);
     2058    if (is<RenderBlock>(*this))
     2059        downcast<RenderBlock>(*this).setCachedFlowThreadContainingBlockNeedsUpdate();
     2060    if (shouldUpdateState)
     2061        setFlowThreadState(NotInsideFlowThread);
     2062}
     2063
     2064void RenderObject::invalidateFlowThreadContainingBlockIncludingDescendants(RenderFlowThread* flowThread)
     2065{
     2066    if (flowThreadState() == NotInsideFlowThread)
     2067        return;
     2068
     2069    if (is<RenderBlock>(*this)) {
     2070        RenderBlock& block = downcast<RenderBlock>(*this);
     2071
     2072        if (block.cachedFlowThreadContainingBlockNeedsUpdate())
     2073            return;
     2074
     2075        flowThread = block.cachedFlowThreadContainingBlock();
     2076        block.setCachedFlowThreadContainingBlockNeedsUpdate();
     2077    }
     2078
     2079    if (flowThread)
     2080        flowThread->removeFlowChildInfo(this);
     2081
     2082    for (RenderObject* child = firstChildSlow(); child; child = child->nextSibling())
     2083        child->invalidateFlowThreadContainingBlockIncludingDescendants(flowThread);
    20972084}
    20982085
     
    25982585RenderNamedFlowFragment* RenderObject::currentRenderNamedFlowFragment() const
    25992586{
    2600     if (flowThreadState() == NotInsideFlowThread)
     2587    RenderFlowThread* flowThread = flowThreadContainingBlock();
     2588    if (!flowThread || !flowThread->isRenderNamedFlowThread())
    26012589        return nullptr;
    2602 
    2603     RenderFlowThread* flowThread = view().flowThreadController().currentRenderFlowThread();
    2604     if (!flowThread)
    2605         return nullptr;
    2606 
    2607     ASSERT(flowThread == flowThreadContainingBlock());
    26082590
    26092591    // FIXME: Once regions are fully integrated with the compositing system we should uncomment this assert.
     
    26122594    // ASSERT(flowThread->currentRegion() && flowThread->currentRegion()->isRenderNamedFlowFragment());
    26132595
    2614     RenderNamedFlowFragment* namedFlowFragment = toRenderNamedFlowFragment(flowThread->currentRegion());
    2615     return namedFlowFragment;
     2596    return toRenderNamedFlowFragment(flowThread->currentRegion());
     2597}
     2598
     2599RenderFlowThread* RenderObject::locateFlowThreadContainingBlock() const
     2600{
     2601    RenderBlock* containingBlock = this->containingBlock();
     2602    return containingBlock ? containingBlock->flowThreadContainingBlock() : nullptr;
    26162603}
    26172604
  • trunk/Source/WebCore/rendering/RenderObject.h

    r174722 r174761  
    213213    bool fixedPositionedWithNamedFlowContainingBlock() const;
    214214
    215     enum ShouldUseFlowThreadCache {
    216         UseFlowThreadCache,
    217         SkipFlowThreadCache
    218     };
    219 
    220215    // Function to return our enclosing flow thread if we are contained inside one. This
    221216    // function follows the containing block chain.
    222     RenderFlowThread* flowThreadContainingBlock(ShouldUseFlowThreadCache useCache = UseFlowThreadCache) const
     217    RenderFlowThread* flowThreadContainingBlock() const
    223218    {
    224219        if (flowThreadState() == NotInsideFlowThread)
    225             return 0;
    226         return (useCache == SkipFlowThreadCache) ? locateFlowThreadContainingBlockNoCache() : locateFlowThreadContainingBlock();
     220            return nullptr;
     221
     222        return locateFlowThreadContainingBlock();
    227223    }
    228224
     
    893889    void setNeedsSimplifiedNormalFlowLayoutBit(bool b) { m_bitfields.setNeedsSimplifiedNormalFlowLayout(b); }
    894890
     891    virtual RenderFlowThread* locateFlowThreadContainingBlock() const;
     892    void invalidateFlowThreadContainingBlockIncludingDescendants(RenderFlowThread* = nullptr);
     893
    895894private:
    896     RenderFlowThread* locateFlowThreadContainingBlock() const;
    897     RenderFlowThread* locateFlowThreadContainingBlockNoCache() const;
    898    
    899895    void removeFromRenderFlowThread();
    900     void removeFromRenderFlowThreadRecursive(RenderFlowThread*);
     896    void removeFromRenderFlowThreadIncludingDescendants(bool);
    901897
    902898    Color selectionColor(int colorProperty) const;
  • trunk/Source/WebCore/rendering/RenderRegion.cpp

    r174714 r174761  
    219219{
    220220    ASSERT(isValid());
    221    
    222     LayoutRect layoutRect;
    223     {
    224         // When getting the overflow from the flow thread we need to temporarly reset the current flow thread because
    225         // we're changing flows.
    226         CurrentRenderFlowThreadMaintainer flowThreadMaintainer(m_flowThread);
    227         layoutRect = layoutOverflowRectForBox(m_flowThread);
    228     }
    229 
     221
     222    LayoutRect layoutRect = layoutOverflowRectForBox(m_flowThread);
    230223    layoutRect.setLocation(contentBoxRect().location() + (layoutRect.location() - m_flowThreadPortionRect.location()));
    231224
  • trunk/Source/WebCore/rendering/RenderView.cpp

    r174725 r174761  
    13121312        return;
    13131313
    1314     RenderFlowThread* currentFlowThread = m_flowThreadController->currentRenderFlowThread();
     1314    RenderFlowThread* currentFlowThread = object.flowThreadContainingBlock();
    13151315    if (!currentFlowThread)
    13161316        return;
    13171317
     1318    m_layoutState->setCurrentRenderFlowThread(currentFlowThread);
     1319
    13181320    currentFlowThread->pushFlowThreadLayoutState(object);
    13191321}
     
    13241326        return;
    13251327
    1326     RenderFlowThread* currentFlowThread = m_flowThreadController->currentRenderFlowThread();
     1328    RenderFlowThread* currentFlowThread = m_layoutState->currentRenderFlowThread();
    13271329    if (!currentFlowThread)
    13281330        return;
  • trunk/Source/WebCore/rendering/RenderView.h

    r174725 r174761  
    296296    void pushLayoutStateForCurrentFlowThread(const RenderObject&);
    297297    void popLayoutStateForCurrentFlowThread();
    298    
     298
    299299    friend class LayoutStateMaintainer;
    300300    friend class LayoutStateDisabler;
Note: See TracChangeset for help on using the changeset viewer.