Bug 1444580: Devirtualize the IntersectionObserver bits. r=smaug draft
authorEmilio Cobos Álvarez <emilio@crisal.io>
Sat, 10 Mar 2018 05:45:59 +0100
changeset 765775 e175d6a95fd5e49f5337e4d57201e0b009325e7c
parent 765774 d0aac71b2af5b10f038f0b27f8aee5a14efaf03c
child 765776 df89bbcb6e91a4408081b3308e9b061d4e8e7bc5
push id102161
push userbmo:emilio@crisal.io
push dateSat, 10 Mar 2018 07:39:34 +0000
reviewerssmaug
bugs1444580
milestone60.0a1
Bug 1444580: Devirtualize the IntersectionObserver bits. r=smaug MozReview-Commit-ID: 65WtMQPu7f4
dom/base/nsDocument.cpp
dom/base/nsDocument.h
dom/base/nsIDocument.h
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -12353,71 +12353,57 @@ nsDocument::ReportUseCounters(UseCounter
 
   if (IsContentDocument() || IsResourceDoc()) {
     uint16_t num = mIncCounters[eIncCounter_ScriptTag];
     Telemetry::Accumulate(Telemetry::DOM_SCRIPT_EVAL_PER_DOCUMENT, num);
   }
 }
 
 void
-nsDocument::AddIntersectionObserver(DOMIntersectionObserver* aObserver)
-{
-  MOZ_ASSERT(!mIntersectionObservers.Contains(aObserver),
-             "Intersection observer already in the list");
-  mIntersectionObservers.PutEntry(aObserver);
-}
-
-void
-nsDocument::RemoveIntersectionObserver(DOMIntersectionObserver* aObserver)
-{
-  mIntersectionObservers.RemoveEntry(aObserver);
-}
-
-void
-nsDocument::UpdateIntersectionObservations()
+nsIDocument::UpdateIntersectionObservations()
 {
   if (mIntersectionObservers.IsEmpty()) {
     return;
   }
 
   DOMHighResTimeStamp time = 0;
   if (nsPIDOMWindowInner* window = GetInnerWindow()) {
     Performance* perf = window->GetPerformance();
     if (perf) {
       time = perf->Now();
     }
   }
   nsTArray<RefPtr<DOMIntersectionObserver>> observers(mIntersectionObservers.Count());
   for (auto iter = mIntersectionObservers.Iter(); !iter.Done(); iter.Next()) {
     DOMIntersectionObserver* observer = iter.Get()->GetKey();
-      observers.AppendElement(observer);
+    observers.AppendElement(observer);
   }
   for (const auto& observer : observers) {
     if (observer) {
       observer->Update(this, time);
     }
   }
 }
 
 void
-nsDocument::ScheduleIntersectionObserverNotification()
+nsIDocument::ScheduleIntersectionObserverNotification()
 {
   if (mIntersectionObservers.IsEmpty()) {
     return;
   }
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   nsCOMPtr<nsIRunnable> notification =
     NewRunnableMethod("nsDocument::NotifyIntersectionObservers",
                       this,
                       &nsDocument::NotifyIntersectionObservers);
   Dispatch(TaskCategory::Other, notification.forget());
 }
 
 void
-nsDocument::NotifyIntersectionObservers()
+nsIDocument::NotifyIntersectionObservers()
 {
   nsTArray<RefPtr<DOMIntersectionObserver>> observers(mIntersectionObservers.Count());
   for (auto iter = mIntersectionObservers.Iter(); !iter.Done(); iter.Next()) {
     DOMIntersectionObserver* observer = iter.Get()->GetKey();
     observers.AppendElement(observer);
   }
   for (const auto& observer : observers) {
     if (observer) {
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -472,28 +472,16 @@ public:
     // Flush use counters for the document and for its external resource
     // documents. (Should only be necessary for tests, where we need
     // flushing to happen synchronously and deterministically.)
     eIncludeExternalResources,
   };
 
   void ReportUseCounters(UseCounterReportKind aKind = UseCounterReportKind::eDefault);
 
-  virtual void AddIntersectionObserver(
-    mozilla::dom::DOMIntersectionObserver* aObserver) override;
-  virtual void RemoveIntersectionObserver(
-    mozilla::dom::DOMIntersectionObserver* aObserver) override;
-  virtual void UpdateIntersectionObservations() override;
-  virtual void ScheduleIntersectionObserverNotification() override;
-  virtual void NotifyIntersectionObservers() override;
-  virtual bool HasIntersectionObservers() const override
-  {
-    return !mIntersectionObservers.IsEmpty();
-  }
-
   virtual void NotifyLayerManagerRecreated() override;
 
   bool IsSynthesized();
 
   // Check whether shadow DOM is enabled for the global of aObject.
   static bool IsShadowDOMEnabled(JSContext* aCx, JSObject* aObject);
   // Check whether shadow DOM is enabled for the document this node belongs to.
   static bool IsShadowDOMEnabled(const nsINode* aNode);
@@ -845,20 +833,16 @@ protected:
   // Apply the fullscreen state to the document, and trigger related
   // events. It returns false if the fullscreen element ready check
   // fails and nothing gets changed.
   bool ApplyFullscreen(const FullscreenRequest& aRequest);
 
   // Array of owning references to all children
   nsAttrAndChildArray mChildren;
 
-  // Array of intersection observers
-  nsTHashtable<nsPtrHashKey<mozilla::dom::DOMIntersectionObserver>>
-    mIntersectionObservers;
-
   // Tracker for animations that are waiting to start.
   // nullptr until GetOrCreatePendingAnimationTracker is called.
   RefPtr<mozilla::PendingAnimationTracker> mPendingAnimationTracker;
 
   // Stack of full-screen elements. When we request full-screen we push the
   // full-screen element onto this stack, and when we cancel full-screen we
   // pop one off this stack, restoring the previous full-screen state
   nsTArray<nsWeakPtr> mFullScreenStack;
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -3183,25 +3183,36 @@ public:
   void ReportHasScrollLinkedEffect();
   bool HasScrollLinkedEffect() const
   {
     return mHasScrollLinkedEffect;
   }
 
   mozilla::dom::DocGroup* GetDocGroup() const;
 
-  virtual void AddIntersectionObserver(
-    mozilla::dom::DOMIntersectionObserver* aObserver) = 0;
-  virtual void RemoveIntersectionObserver(
-    mozilla::dom::DOMIntersectionObserver* aObserver) = 0;
-
-  virtual void UpdateIntersectionObservations() = 0;
-  virtual void ScheduleIntersectionObserverNotification() = 0;
-  virtual void NotifyIntersectionObservers() = 0;
-  virtual bool HasIntersectionObservers() const = 0;
+  void AddIntersectionObserver(mozilla::dom::DOMIntersectionObserver* aObserver)
+  {
+    MOZ_ASSERT(!mIntersectionObservers.Contains(aObserver),
+               "Intersection observer already in the list");
+    mIntersectionObservers.PutEntry(aObserver);
+  }
+
+  void RemoveIntersectionObserver(mozilla::dom::DOMIntersectionObserver* aObserver)
+  {
+    mIntersectionObservers.RemoveEntry(aObserver);
+  }
+
+  bool HasIntersectionObservers() const
+  {
+    return !mIntersectionObservers.IsEmpty();
+  }
+
+  void UpdateIntersectionObservations();
+  void ScheduleIntersectionObserverNotification();
+  void NotifyIntersectionObservers();
 
   // Dispatch a runnable related to the document.
   virtual nsresult Dispatch(mozilla::TaskCategory aCategory,
                             already_AddRefed<nsIRunnable>&& aRunnable) override;
 
   virtual nsISerialEventTarget*
   EventTargetFor(mozilla::TaskCategory aCategory) const override;
 
@@ -3984,16 +3995,20 @@ protected:
 
   nsWeakPtr mAutoFocusElement;
 
   // Weak reference to the scope object (aka the script global object)
   // that, unlike mScriptGlobalObject, is never unset once set. This
   // is a weak reference to avoid leaks due to circular references.
   nsWeakPtr mScopeObject;
 
+  // Array of intersection observers
+  nsTHashtable<nsPtrHashKey<mozilla::dom::DOMIntersectionObserver>>
+    mIntersectionObservers;
+
   nsTArray<RefPtr<mozilla::StyleSheet>> mOnDemandBuiltInUASheets;
   nsTArray<RefPtr<mozilla::StyleSheet>> mAdditionalSheets[AdditionalSheetTypeCount];
 
   // Member to store out last-selected stylesheet set.
   nsString mLastStyleSheetSet;
   RefPtr<nsDOMStyleSheetSetList> mStyleSheetSetList;
 
   // We lazily calculate declaration blocks for SVG elements with mapped