Bug 1543315 - part 13: Mark PresShell::Paint() as MOZ_CAN_RUN_SCRIPT r=smaug
authorMasayuki Nakano <masayuki@d-toybox.com>
Mon, 06 May 2019 13:25:35 +0000
changeset 531502 59633bc3f7619ec93c0a978861c2f466d7fd3433
parent 531501 61594665f837fa18a2ab243b861d14aef813b8ed
child 531503 e2969c920810b32d97f6dd72b1f84a94fadddc77
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1543315
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1543315 - part 13: Mark PresShell::Paint() as MOZ_CAN_RUN_SCRIPT r=smaug Differential Revision: https://phabricator.services.mozilla.com/D30008
dom/base/nsDOMWindowUtils.cpp
dom/ipc/BrowserChild.h
layout/base/PresShell.h
layout/forms/nsComboboxControlFrame.cpp
layout/forms/nsComboboxControlFrame.h
layout/xul/nsXULPopupManager.h
view/nsView.h
view/nsViewManager.cpp
view/nsViewManager.h
widget/nsIRollupListener.h
widget/nsIWidgetListener.h
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -373,18 +373,17 @@ NS_IMETHODIMP
 nsDOMWindowUtils::UpdateLayerTree() {
   if (RefPtr<PresShell> presShell = GetPresShell()) {
     // Don't flush throttled animations since it might fire MozAfterPaint event
     // (in WebRender it constantly does), thus the reftest harness can't take
     // any snapshot until the throttled animations finished.
     presShell->FlushPendingNotifications(
         ChangesToFlush(FlushType::Display, false /* flush animations */));
     RefPtr<nsViewManager> vm = presShell->GetViewManager();
-    nsView* view = vm->GetRootView();
-    if (view) {
+    if (nsView* view = vm->GetRootView()) {
       nsAutoScriptBlocker scriptBlocker;
       presShell->Paint(
           view, view->GetBounds(),
           PaintFlags::PaintLayers | PaintFlags::PaintSyncDecodeImages);
       presShell->GetLayerManager()->WaitOnTransactionProcessed();
     }
   }
   return NS_OK;
--- a/dom/ipc/BrowserChild.h
+++ b/dom/ipc/BrowserChild.h
@@ -696,16 +696,17 @@ class BrowserChild final : public Browse
 
   virtual bool DeallocPBrowserBridgeChild(PBrowserBridgeChild* aActor) override;
 
   virtual mozilla::ipc::IPCResult RecvDestroy() override;
 
   virtual mozilla::ipc::IPCResult RecvSetDocShellIsActive(
       const bool& aIsActive) override;
 
+  MOZ_CAN_RUN_SCRIPT_BOUNDARY
   virtual mozilla::ipc::IPCResult RecvRenderLayers(
       const bool& aEnabled, const bool& aForce,
       const layers::LayersObserverEpoch& aEpoch) override;
 
   virtual mozilla::ipc::IPCResult RecvRequestRootPaint(
       const IntRect& aRect, const float& aScale,
       const nscolor& aBackgroundColor,
       RequestRootPaintResolver&& aResolve) override;
--- a/layout/base/PresShell.h
+++ b/layout/base/PresShell.h
@@ -1277,18 +1277,17 @@ class PresShell final : public nsStubDoc
                                    ResolutionChangeOrigin aOrigin);
 
   // Widget notificiations
   void WindowSizeMoveDone();
   void SysColorChanged() { mPresContext->SysColorChanged(); }
   void ThemeChanged() { mPresContext->ThemeChanged(); }
   void BackingScaleFactorChanged() { mPresContext->UIResolutionChangedSync(); }
 
-  // nsIViewObserver interface
-
+  MOZ_CAN_RUN_SCRIPT
   void Paint(nsView* aViewToPaint, const nsRegion& aDirtyRegion,
              PaintFlags aFlags);
 
   /**
    * Notify that we're going to call Paint with PaintFlags::PaintLayers
    * on the pres shell for a widget (which might not be this one, since
    * WillPaint is called on all presshells in the same toplevel window as the
    * painted widget). This is issued at a time when it's safe to modify
--- a/layout/forms/nsComboboxControlFrame.cpp
+++ b/layout/forms/nsComboboxControlFrame.cpp
@@ -1383,17 +1383,18 @@ bool nsComboboxControlFrame::Rollup(uint
   ShowDropDown(false);  // might destroy us
   if (weakFrame.IsAlive()) {
     mListControlFrame->CaptureMouseEvents(false);
   }
 
   if (aFlush && weakFrame.IsAlive()) {
     // The popup's visibility doesn't update until the minimize animation has
     // finished, so call UpdateWidgetGeometry to update it right away.
-    nsViewManager* viewManager = mDropdownFrame->GetView()->GetViewManager();
+    RefPtr<nsViewManager> viewManager =
+        mDropdownFrame->GetView()->GetViewManager();
     viewManager->UpdateWidgetGeometry();  // might destroy us
   }
 
   if (!weakFrame.IsAlive()) {
     return consume;
   }
 
   if (aLastRolledUp) {
--- a/layout/forms/nsComboboxControlFrame.h
+++ b/layout/forms/nsComboboxControlFrame.h
@@ -179,16 +179,17 @@ class nsComboboxControlFrame final : pub
   NS_IMETHOD_(void)
   OnSetSelectedIndex(int32_t aOldIndex, int32_t aNewIndex) override;
 
   // nsIRollupListener
   /**
    * Hide the dropdown menu and stop capturing mouse events.
    * @note This method might destroy |this|.
    */
+  MOZ_CAN_RUN_SCRIPT_BOUNDARY
   virtual bool Rollup(uint32_t aCount, bool aFlush, const nsIntPoint* pos,
                       nsIContent** aLastRolledUp) override;
   virtual void NotifyGeometryChange() override;
 
   /**
    * A combobox should roll up if a mousewheel event happens outside of
    * the popup area.
    */
--- a/layout/xul/nsXULPopupManager.h
+++ b/layout/xul/nsXULPopupManager.h
@@ -328,16 +328,17 @@ class nsXULPopupManager final : public n
   friend class nsXULMenuCommandEvent;
   friend class TransitionEnder;
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
   NS_DECL_NSIDOMEVENTLISTENER
 
   // nsIRollupListener
+  MOZ_CAN_RUN_SCRIPT_BOUNDARY
   virtual bool Rollup(uint32_t aCount, bool aFlush, const nsIntPoint* pos,
                       nsIContent** aLastRolledUp) override;
   virtual bool ShouldRollupOnMouseWheelEvent() override;
   virtual bool ShouldConsumeOnMouseWheelEvent() override;
   virtual bool ShouldRollupOnMouseActivate() override;
   virtual uint32_t GetSubmenuWidgetChain(
       nsTArray<nsIWidget*>* aWidgetChain) override;
   virtual void NotifyGeometryChange() override {}
--- a/view/nsView.h
+++ b/view/nsView.h
@@ -384,17 +384,19 @@ class nsView final : public nsIWidgetLis
 
   // nsIWidgetListener
   virtual mozilla::PresShell* GetPresShell() override;
   virtual nsView* GetView() override { return this; }
   virtual bool WindowMoved(nsIWidget* aWidget, int32_t x, int32_t y) override;
   virtual bool WindowResized(nsIWidget* aWidget, int32_t aWidth,
                              int32_t aHeight) override;
   virtual bool RequestWindowClose(nsIWidget* aWidget) override;
+  MOZ_CAN_RUN_SCRIPT_BOUNDARY
   virtual void WillPaintWindow(nsIWidget* aWidget) override;
+  MOZ_CAN_RUN_SCRIPT_BOUNDARY
   virtual bool PaintWindow(nsIWidget* aWidget,
                            LayoutDeviceIntRegion aRegion) override;
   virtual void DidPaintWindow() override;
   virtual void DidCompositeWindow(
       mozilla::layers::TransactionId aTransactionId,
       const mozilla::TimeStamp& aCompositeStart,
       const mozilla::TimeStamp& aCompositeEnd) override;
   virtual void RequestRepaint() override;
--- a/view/nsViewManager.cpp
+++ b/view/nsViewManager.cpp
@@ -321,28 +321,27 @@ void nsViewManager::Refresh(nsView* aVie
 
   {
     nsAutoScriptBlocker scriptBlocker;
     SetPainting(true);
 
     NS_ASSERTION(GetDisplayRootFor(aView) == aView,
                  "Widgets that we paint must all be display roots");
 
-    if (mPresShell) {
+    if (RefPtr<PresShell> presShell = mPresShell) {
 #ifdef MOZ_DUMP_PAINTING
       if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
-        printf_stderr("--COMPOSITE-- %p\n", mPresShell);
+        printf_stderr("--COMPOSITE-- %p\n", presShell.get());
       }
 #endif
-      PaintFlags paintFlags = PaintFlags::PaintComposite;
       LayerManager* manager = widget->GetLayerManager();
       if (!manager->NeedsWidgetInvalidation()) {
         manager->FlushRendering();
       } else {
-        mPresShell->Paint(aView, damageRegion, paintFlags);
+        presShell->Paint(aView, damageRegion, PaintFlags::PaintComposite);
       }
 #ifdef MOZ_DUMP_PAINTING
       if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
         printf_stderr("--ENDCOMPOSITE--\n");
       }
 #endif
       mozilla::StartupTimeline::RecordOnce(
           mozilla::StartupTimeline::FIRST_PAINT);
@@ -389,17 +388,18 @@ void nsViewManager::ProcessPendingUpdate
   }
   if (aFlushDirtyRegion) {
     nsAutoScriptBlocker scriptBlocker;
     SetPainting(true);
     for (uint32_t i = 0; i < widgets.Length(); ++i) {
       nsIWidget* widget = widgets[i];
       nsView* view = nsView::GetViewFor(widget);
       if (view) {
-        view->GetViewManager()->ProcessPendingUpdatesPaint(widget);
+        RefPtr<nsViewManager> viewManager = view->GetViewManager();
+        viewManager->ProcessPendingUpdatesPaint(MOZ_KnownLive(widget));
       }
     }
     SetPainting(false);
   }
 }
 
 void nsViewManager::ProcessPendingUpdatesRecurse(
     nsView* aView, AutoTArray<nsCOMPtr<nsIWidget>, 1>& aWidgets) {
@@ -445,26 +445,26 @@ void nsViewManager::ProcessPendingUpdate
     nsIWidgetListener* previousListener =
         aWidget->GetPreviouslyAttachedWidgetListener();
 
     if (previousListener && previousListener != view &&
         view->IsPrimaryFramePaintSuppressed()) {
       return;
     }
 
-    if (mPresShell) {
+    if (RefPtr<PresShell> presShell = mPresShell) {
 #ifdef MOZ_DUMP_PAINTING
       if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
         printf_stderr(
             "---- PAINT START ----PresShell(%p), nsView(%p), nsIWidget(%p)\n",
-            mPresShell, view, aWidget);
+            presShell.get(), view, aWidget);
       }
 #endif
 
-      mPresShell->Paint(view, nsRegion(), PaintFlags::PaintLayers);
+      presShell->Paint(view, nsRegion(), PaintFlags::PaintLayers);
       view->SetForcedRepaint(false);
 
 #ifdef MOZ_DUMP_PAINTING
       if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
         printf_stderr("---- PAINT END ----\n");
       }
 #endif
     }
@@ -1001,40 +1001,41 @@ LayoutDeviceIntRect nsViewManager::ViewT
 }
 
 void nsViewManager::IsPainting(bool& aIsPainting) {
   aIsPainting = IsPainting();
 }
 
 void nsViewManager::ProcessPendingUpdates() {
   if (!IsRootVM()) {
-    RootViewManager()->ProcessPendingUpdates();
+    RefPtr<nsViewManager> rootViewManager = RootViewManager();
+    rootViewManager->ProcessPendingUpdates();
     return;
   }
 
   // Flush things like reflows by calling WillPaint on observer presShells.
   if (mPresShell) {
     mPresShell->GetPresContext()->RefreshDriver()->RevokeViewManagerFlush();
 
     RefPtr<nsViewManager> strongThis(this);
     CallWillPaintOnObservers();
 
     ProcessPendingUpdatesForView(mRootView, true);
   }
 }
 
 void nsViewManager::UpdateWidgetGeometry() {
   if (!IsRootVM()) {
-    RootViewManager()->UpdateWidgetGeometry();
+    RefPtr<nsViewManager> rootViewManager = RootViewManager();
+    rootViewManager->UpdateWidgetGeometry();
     return;
   }
 
   if (mHasPendingWidgetGeometryChanges) {
     mHasPendingWidgetGeometryChanges = false;
-    RefPtr<nsViewManager> strongThis(this);
     ProcessPendingUpdatesForView(mRootView, false);
   }
 }
 
 void nsViewManager::CallWillPaintOnObservers() {
   MOZ_ASSERT(IsRootVM(), "Must be root VM for this to be called!");
 
   if (NS_WARN_IF(!gViewManagers)) {
--- a/view/nsViewManager.h
+++ b/view/nsViewManager.h
@@ -305,53 +305,56 @@ class nsViewManager final {
    * the nearest enclosing popup or the root view for the root document.
    */
   static nsView* GetDisplayRootFor(nsView* aView);
 
   /**
    * Flush the accumulated dirty region to the widget and update widget
    * geometry.
    */
-  void ProcessPendingUpdates();
+  MOZ_CAN_RUN_SCRIPT void ProcessPendingUpdates();
 
   /**
    * Just update widget geometry without flushing the dirty region
    */
-  void UpdateWidgetGeometry();
+  MOZ_CAN_RUN_SCRIPT void UpdateWidgetGeometry();
 
   int32_t AppUnitsPerDevPixel() const {
     return mContext->AppUnitsPerDevPixel();
   }
 
  private:
   static uint32_t gLastUserEventTime;
 
   /* Update the cached RootViewManager pointer on this view manager. */
   void InvalidateHierarchy();
   void FlushPendingInvalidates();
 
+  MOZ_CAN_RUN_SCRIPT
   void ProcessPendingUpdatesForView(nsView* aView,
                                     bool aFlushDirtyRegion = true);
   void ProcessPendingUpdatesRecurse(
       nsView* aView, AutoTArray<nsCOMPtr<nsIWidget>, 1>& aWidgets);
+  MOZ_CAN_RUN_SCRIPT
   void ProcessPendingUpdatesPaint(nsIWidget* aWidget);
 
   void FlushDirtyRegionToWidget(nsView* aView);
   /**
    * Call WillPaint() on all view observers under this vm root.
    */
   MOZ_CAN_RUN_SCRIPT_BOUNDARY void CallWillPaintOnObservers();
   void ReparentChildWidgets(nsView* aView, nsIWidget* aNewWidget);
   void ReparentWidgets(nsView* aView, nsView* aParent);
   void InvalidateWidgetArea(nsView* aWidgetView,
                             const nsRegion& aDamagedRegion);
 
   void InvalidateViews(nsView* aView);
 
   // aView is the view for aWidget and aRegion is relative to aWidget.
+  MOZ_CAN_RUN_SCRIPT
   void Refresh(nsView* aView, const LayoutDeviceIntRegion& aRegion);
 
   // Utilities
 
   bool IsViewInserted(nsView* aView);
 
   /**
    * Intersects aRect with aView's bounds and then transforms it from aView's
@@ -375,17 +378,18 @@ class nsViewManager final {
 
   // Whether synchronous painting is allowed at the moment. For example,
   // widget geometry changes can cause synchronous painting, so they need to
   // be deferred while refresh is disabled.
   bool IsPaintingAllowed() {
     return RootViewManager()->mRefreshDisableCount == 0;
   }
 
-  void WillPaintWindow(nsIWidget* aWidget);
+  MOZ_CAN_RUN_SCRIPT void WillPaintWindow(nsIWidget* aWidget);
+  MOZ_CAN_RUN_SCRIPT
   bool PaintWindow(nsIWidget* aWidget, const LayoutDeviceIntRegion& aRegion);
   void DidPaintWindow();
 
   // Call this when you need to let the viewmanager know that it now has
   // pending updates.
   void PostPendingUpdate();
 
   RefPtr<nsDeviceContext> mContext;
--- a/widget/nsIRollupListener.h
+++ b/widget/nsIRollupListener.h
@@ -26,16 +26,17 @@ class nsIRollupListener {
    *
    * aCount is the number of popups in a chain to close. If this is
    * UINT32_MAX, then all popups are closed.
    * If aLastRolledUp is non-null, it will be set to the last rolled up popup,
    * if this is supported. aLastRolledUp is not addrefed.
    *
    * Returns true if the event that the caller is processing should be consumed.
    */
+  MOZ_CAN_RUN_SCRIPT_BOUNDARY
   virtual bool Rollup(uint32_t aCount, bool aFlush, const nsIntPoint* aPoint,
                       nsIContent** aLastRolledUp) = 0;
 
   /**
    * Asks the RollupListener if it should rollup on mouse wheel events
    */
   virtual bool ShouldRollupOnMouseWheelEvent() = 0;
 
--- a/widget/nsIWidgetListener.h
+++ b/widget/nsIWidgetListener.h
@@ -132,24 +132,26 @@ class nsIWidgetListener {
    */
   virtual bool RequestWindowClose(nsIWidget* aWidget);
 
   /*
    * Indicate that a paint is about to occur on this window. This is called
    * at a time when it's OK to change the geometry of this widget or of
    * other widgets. Must be called before every call to PaintWindow.
    */
+  MOZ_CAN_RUN_SCRIPT_BOUNDARY
   virtual void WillPaintWindow(nsIWidget* aWidget);
 
   /**
    * Paint the specified region of the window. Returns true if the
    * notification was handled.
    * This is called at a time when it is not OK to change the geometry of
    * this widget or of other widgets.
    */
+  MOZ_CAN_RUN_SCRIPT_BOUNDARY
   virtual bool PaintWindow(nsIWidget* aWidget,
                            mozilla::LayoutDeviceIntRegion aRegion);
 
   /**
    * Indicates that a paint occurred.
    * This is called at a time when it is OK to change the geometry of
    * this widget or of other widgets.
    * Must be called after every call to PaintWindow.