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

Changeset 276513 in webkit


Ignore:
Timestamp:
Apr 23, 2021, 12:51:44 PM (5 years ago)
Author:
Michael Catanzaro
Message:

Remove virtual function calls in GraphicsLayer destructors
https://bugs.webkit.org/show_bug.cgi?id=180232

Reviewed by Adrian Perez de Castro.

I notice that ~CoordinatedGraphicsLayer makes a virtual function call to
GraphicsLayer::willBeDestroyed, which makes a virtual function call to
CoordinatedGraphicsLayer::removeFromParent. I think that the functions are being called as
intended, because ~CoordinatedGraphicsLayer has not yet been fully destroyed. However, I'm
reminded of Effective C++ item #9: Never call virtual functions during construction or
destruction ("because such calls will never go to a more derived class than that of the
currently executing constructor or destructor"). This code is almost certain to break if
anyone tries in the future to subclass any of the existing subclasses of GraphicsLayer, so
let's refactor it a bit. This doesn't fix anything, but my hope is that it will make the
code a bit harder to break, and not the opposite.

The main risk here is that some reordering of operations is necessary. The derived class
portion of removeFromParent must now be executed before willBeDestroyed. It can't happen
after, because parent would already be unset by that point. It's hard to be certain that
this won't break anything, but I think it should be fine.

  • platform/graphics/GraphicsLayer.cpp:

(WebCore::GraphicsLayer::willBeDestroyed):
(WebCore::GraphicsLayer::removeFromParentInternal):
(WebCore::GraphicsLayer::removeFromParent):

  • platform/graphics/GraphicsLayer.h:
  • platform/graphics/ca/GraphicsLayerCA.cpp:

(WebCore::GraphicsLayerCA::~GraphicsLayerCA):
(WebCore::GraphicsLayerCA::willBeDestroyed): Deleted.

  • platform/graphics/ca/GraphicsLayerCA.h:
  • platform/graphics/texmap/coordinated/CoordinatedGraphicsLayer.cpp:

(WebCore::CoordinatedGraphicsLayer::~CoordinatedGraphicsLayer):

Location:
trunk/Source/WebCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r276510 r276513  
     12021-04-23  Michael Catanzaro  <mcatanzaro@igalia.com>
     2
     3        Remove virtual function calls in GraphicsLayer destructors
     4        https://bugs.webkit.org/show_bug.cgi?id=180232
     5
     6        Reviewed by Adrian Perez de Castro.
     7
     8        I notice that ~CoordinatedGraphicsLayer makes a virtual function call to
     9        GraphicsLayer::willBeDestroyed, which makes a virtual function call to
     10        CoordinatedGraphicsLayer::removeFromParent. I think that the functions are being called as
     11        intended, because ~CoordinatedGraphicsLayer has not yet been fully destroyed. However, I'm
     12        reminded of Effective C++ item #9: Never call virtual functions during construction or
     13        destruction ("because such calls will never go to a more derived class than that of the
     14        currently executing constructor or destructor"). This code is almost certain to break if
     15        anyone tries in the future to subclass any of the existing subclasses of GraphicsLayer, so
     16        let's refactor it a bit. This doesn't fix anything, but my hope is that it will make the
     17        code a bit harder to break, and not the opposite.
     18
     19        The main risk here is that some reordering of operations is necessary. The derived class
     20        portion of removeFromParent must now be executed before willBeDestroyed. It can't happen
     21        after, because parent would already be unset by that point. It's hard to be certain that
     22        this won't break anything, but I think it should be fine.
     23
     24        * platform/graphics/GraphicsLayer.cpp:
     25        (WebCore::GraphicsLayer::willBeDestroyed):
     26        (WebCore::GraphicsLayer::removeFromParentInternal):
     27        (WebCore::GraphicsLayer::removeFromParent):
     28        * platform/graphics/GraphicsLayer.h:
     29        * platform/graphics/ca/GraphicsLayerCA.cpp:
     30        (WebCore::GraphicsLayerCA::~GraphicsLayerCA):
     31        (WebCore::GraphicsLayerCA::willBeDestroyed): Deleted.
     32        * platform/graphics/ca/GraphicsLayerCA.h:
     33        * platform/graphics/texmap/coordinated/CoordinatedGraphicsLayer.cpp:
     34        (WebCore::CoordinatedGraphicsLayer::~CoordinatedGraphicsLayer):
     35
    1362021-04-23  Darin Adler  <darin@apple.com>
    237
  • trunk/Source/WebCore/platform/graphics/GraphicsLayer.cpp

    r276232 r276513  
    201201
    202202    removeAllChildren();
    203     removeFromParent();
     203    removeFromParentInternal();
    204204}
    205205
     
    336336}
    337337
    338 void GraphicsLayer::removeFromParent()
     338void GraphicsLayer::removeFromParentInternal()
    339339{
    340340    if (m_parent) {
     
    372372    else
    373373        m_childrenTransform = makeUnique<TransformationMatrix>(matrix);
     374}
     375
     376void GraphicsLayer::removeFromParent()
     377{
     378    // removeFromParentInternal is nonvirtual, for use in willBeDestroyed,
     379    // which is called from destructors.
     380    removeFromParentInternal();
    374381}
    375382
  • trunk/Source/WebCore/platform/graphics/GraphicsLayer.h

    r276232 r276513  
    639639
    640640    // Should be called from derived class destructors. Should call willBeDestroyed() on super.
    641     WEBCORE_EXPORT virtual void willBeDestroyed();
     641    WEBCORE_EXPORT void willBeDestroyed();
    642642    bool beingDestroyed() const { return m_beingDestroyed; }
    643643
     
    659659
    660660    virtual bool shouldRepaintOnSizeChange() const { return drawsContent(); }
     661
     662    void removeFromParentInternal();
    661663
    662664    // The layer being replicated.
  • trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp

    r276327 r276513  
    452452        layerDisplayListMap().remove(this);
    453453
    454     // Do cleanup while we can still safely call methods on the derived class.
    455     willBeDestroyed();
    456 }
    457 
    458 void GraphicsLayerCA::willBeDestroyed()
    459 {
    460454    // We release our references to the PlatformCALayers here, but do not actively unparent them,
    461455    // since that will cause a commit and break our batched commit model. The layers will
     
    489483    removeCloneLayers();
    490484
    491     GraphicsLayer::willBeDestroyed();
     485    if (m_parent)
     486        downcast<GraphicsLayerCA>(*m_parent).noteSublayersChanged();
     487
     488    willBeDestroyed();
    492489}
    493490
  • trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.h

    r276232 r276513  
    191191private:
    192192    bool isGraphicsLayerCA() const override { return true; }
    193 
    194     WEBCORE_EXPORT void willBeDestroyed() override;
    195193
    196194    // PlatformCALayerClient overrides
  • trunk/Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedGraphicsLayer.cpp

    r272141 r276513  
    168168    if (m_animatedBackingStoreHost)
    169169        m_animatedBackingStoreHost->layerWillBeDestroyed();
     170    if (CoordinatedGraphicsLayer* parentLayer = downcast<CoordinatedGraphicsLayer>(parent()))
     171        parentLayer->didChangeChildren();
    170172    willBeDestroyed();
    171173}
Note: See TracChangeset for help on using the changeset viewer.