Bug 1518202 - Make RemoteObjectProxies add the edge to the native object to the CC. r=bzbarsky
authorPeter Van der Beken <peterv@propagandism.org>
Thu, 28 Feb 2019 19:34:02 +0000
changeset 519655 58405fa4f0d960b05cb4f16fbfd66bf816d5ee61
parent 519654 71fd1aa112d88b818be2d2ab003ecc37cc592300
child 519656 d1e480941a33654feb86f4da38efe7f36ede439a
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky
bugs1518202
milestone67.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 1518202 - Make RemoteObjectProxies add the edge to the native object to the CC. r=bzbarsky Depends on D15848 Differential Revision: https://phabricator.services.mozilla.com/D21497
docshell/base/BrowsingContext.cpp
docshell/base/BrowsingContext.h
dom/base/RemoteOuterWindowProxy.cpp
dom/bindings/RemoteObjectProxy.h
xpcom/base/CycleCollectedJSRuntime.cpp
--- a/docshell/base/BrowsingContext.cpp
+++ b/docshell/base/BrowsingContext.cpp
@@ -550,16 +550,24 @@ class RemoteLocationProxy
     : public RemoteObjectProxy<BrowsingContext::LocationProxy,
                                Location_Binding::sCrossOriginAttributes,
                                Location_Binding::sCrossOriginMethods> {
  public:
   typedef RemoteObjectProxy Base;
 
   constexpr RemoteLocationProxy()
       : RemoteObjectProxy(prototypes::id::Location) {}
+
+  void NoteChildren(JSObject* aProxy,
+                    nsCycleCollectionTraversalCallback& aCb) const override {
+    auto location =
+        static_cast<BrowsingContext::LocationProxy*>(GetNative(aProxy));
+    CycleCollectionNoteChild(aCb, location->GetBrowsingContext(),
+                             "js::GetObjectPrivate(obj)->GetBrowsingContext()");
+  }
 };
 
 static const RemoteLocationProxy sSingleton;
 
 // Give RemoteLocationProxy 2 reserved slots, like the other wrappers,
 // so JSObject::swap can swap it with CrossCompartmentWrappers without requiring
 // malloc.
 template <>
--- a/docshell/base/BrowsingContext.h
+++ b/docshell/base/BrowsingContext.h
@@ -345,16 +345,17 @@ class BrowsingContext : public nsWrapper
     }
 
     void SetHref(const nsAString& aHref, nsIPrincipal& aSubjectPrincipal,
                  ErrorResult& aError);
     void Replace(const nsAString& aUrl, nsIPrincipal& aSubjectPrincipal,
                  ErrorResult& aError);
 
    private:
+    friend class RemoteLocationProxy;
     BrowsingContext* GetBrowsingContext() {
       return reinterpret_cast<BrowsingContext*>(
           uintptr_t(this) - offsetof(BrowsingContext, mLocation));
     }
   };
 
   // Type of BrowsingContent
   const Type mType;
--- a/dom/base/RemoteOuterWindowProxy.cpp
+++ b/dom/base/RemoteOuterWindowProxy.cpp
@@ -42,16 +42,23 @@ class RemoteOuterWindowProxy
       JSContext* aCx, JS::Handle<JSObject*> aProxy, JS::Handle<jsid> aId,
       JS::MutableHandle<JS::PropertyDescriptor> aDesc) const final;
   bool ownPropertyKeys(JSContext* aCx, JS::Handle<JSObject*> aProxy,
                        JS::AutoIdVector& aProps) const final;
 
   // SpiderMonkey extensions
   bool getOwnEnumerablePropertyKeys(JSContext* cx, JS::Handle<JSObject*> proxy,
                                     JS::AutoIdVector& props) const final;
+
+  void NoteChildren(JSObject* aProxy,
+                    nsCycleCollectionTraversalCallback& aCb) const override {
+    CycleCollectionNoteChild(aCb,
+                             static_cast<BrowsingContext*>(GetNative(aProxy)),
+                             "js::GetObjectPrivate(obj)");
+  }
 };
 
 static const RemoteOuterWindowProxy sSingleton;
 
 // Give RemoteOuterWindowProxy 2 reserved slots, like the other wrappers,
 // so JSObject::swap can swap it with CrossCompartmentWrappers without requiring
 // malloc.
 template <>
--- a/dom/bindings/RemoteObjectProxy.h
+++ b/dom/bindings/RemoteObjectProxy.h
@@ -71,16 +71,19 @@ class RemoteObjectProxyBase : public js:
                                     JS::Handle<JSObject*> aProxy,
                                     JS::AutoIdVector& aProps) const override;
   const char* className(JSContext* aCx,
                         JS::Handle<JSObject*> aProxy) const final;
 
   bool isCallable(JSObject* aObj) const final { return false; }
   bool isConstructor(JSObject* aObj) const final { return false; }
 
+  virtual void NoteChildren(JSObject* aProxy,
+                            nsCycleCollectionTraversalCallback& aCb) const = 0;
+
   static void* GetNative(JSObject* aProxy) {
     return js::GetProxyPrivate(aProxy).toPrivate();
   }
 
   /**
    * Returns true if aProxy is a cross-process proxy that represents
    * an object implementing the WebIDL interface for aProtoID. aProxy
    * should be a proxy object.
--- a/xpcom/base/CycleCollectedJSRuntime.cpp
+++ b/xpcom/base/CycleCollectedJSRuntime.cpp
@@ -633,33 +633,39 @@ void CycleCollectedJSRuntime::NoteGCThin
   //     that do hold a strong reference, but that might not be possible.
   if (aClasp->flags & JSCLASS_HAS_PRIVATE &&
       aClasp->flags & JSCLASS_PRIVATE_IS_NSISUPPORTS) {
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "js::GetObjectPrivate(obj)");
     aCb.NoteXPCOMChild(static_cast<nsISupports*>(js::GetObjectPrivate(aObj)));
     return;
   }
 
-  const DOMJSClass* domClass = GetDOMClass(aObj);
+  const DOMJSClass* domClass = GetDOMClass(aClasp);
   if (domClass) {
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "UnwrapDOMObject(obj)");
     // It's possible that our object is an unforgeable holder object, in
     // which case it doesn't actually have a C++ DOM object associated with
     // it.  Use UnwrapPossiblyNotInitializedDOMObject, which produces null in
     // that case, since NoteXPCOMChild/NoteNativeChild are null-safe.
     if (domClass->mDOMObjectIsISupports) {
       aCb.NoteXPCOMChild(
           UnwrapPossiblyNotInitializedDOMObject<nsISupports>(aObj));
     } else if (domClass->mParticipant) {
       aCb.NoteNativeChild(UnwrapPossiblyNotInitializedDOMObject<void>(aObj),
                           domClass->mParticipant);
     }
     return;
   }
 
+  if (IsRemoteObjectProxy(aObj)) {
+    auto handler =
+        static_cast<const RemoteObjectProxyBase*>(js::GetProxyHandler(aObj));
+    return handler->NoteChildren(aObj, aCb);
+  }
+
   JS::Value value = js::MaybeGetScriptPrivate(aObj);
   if (!value.isUndefined()) {
     aCb.NoteXPCOMChild(static_cast<nsISupports*>(value.toPrivate()));
   }
 }
 
 void CycleCollectedJSRuntime::TraverseGCThing(
     TraverseSelect aTs, JS::GCCellPtr aThing,