Bug 942528 - Make XPCWN more of a normal cycle collected class. r=smaug
authorAndrew McCreight <continuation@gmail.com>
Mon, 02 Dec 2013 13:17:29 -0800
changeset 173051 f7330220c26d10fd651acea98b81d68188a0c86e
parent 173050 a7731ef783483203d26cc378581c142b24650952
child 173052 bf6688c7464be2123398a7a82d618cea5965a4a4
push id3224
push userlsblakk@mozilla.com
push dateTue, 04 Feb 2014 01:06:49 +0000
treeherdermozilla-beta@60c04d0987f1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs942528
milestone28.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 942528 - Make XPCWN more of a normal cycle collected class. r=smaug
js/xpconnect/src/XPCWrappedNative.cpp
js/xpconnect/src/xpcprivate.h
--- a/js/xpconnect/src/XPCWrappedNative.cpp
+++ b/js/xpconnect/src/XPCWrappedNative.cpp
@@ -36,16 +36,20 @@ xpc_OkToHandOutWrapper(nsWrapperCache *c
                "Must have XPCWrappedNative wrapper");
     return !XPCWrappedNative::Get(cache->GetWrapper())->NeedsSOW();
 }
 
 /***************************************************************************/
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(XPCWrappedNative)
 
+// No need to unlink the JS objects: if the XPCWrappedNative is cycle
+// collected then its mFlatJSObject will be cycle collected too and
+// finalization of the mFlatJSObject will unlink the JS objects (see
+// XPC_WN_NoHelper_Finalize and FlatJSObjectFinalized).
 NS_IMETHODIMP_(void)
 NS_CYCLE_COLLECTION_CLASSNAME(XPCWrappedNative)::Unlink(void *p)
 {
     XPCWrappedNative *tmp = static_cast<XPCWrappedNative*>(p);
     tmp->ExpireWrapper();
 }
 
 NS_IMETHODIMP
@@ -595,32 +599,36 @@ XPCWrappedNative::GetUsedOnly(nsISupport
 
 // This ctor is used if this object will have a proto.
 XPCWrappedNative::XPCWrappedNative(already_AddRefed<nsISupports> aIdentity,
                                    XPCWrappedNativeProto* aProto)
     : mMaybeProto(aProto),
       mSet(aProto->GetSet()),
       mScriptableInfo(nullptr)
 {
+    MOZ_ASSERT(NS_IsMainThread());
+
     mIdentity = aIdentity.get();
     mFlatJSObject.setFlags(FLAT_JS_OBJECT_VALID);
 
     MOZ_ASSERT(mMaybeProto, "bad ctor param");
     MOZ_ASSERT(mSet, "bad ctor param");
 }
 
 // This ctor is used if this object will NOT have a proto.
 XPCWrappedNative::XPCWrappedNative(already_AddRefed<nsISupports> aIdentity,
                                    XPCWrappedNativeScope* aScope,
                                    XPCNativeSet* aSet)
 
     : mMaybeScope(TagScope(aScope)),
       mSet(aSet),
       mScriptableInfo(nullptr)
 {
+    MOZ_ASSERT(NS_IsMainThread());
+
     mIdentity = aIdentity.get();
     mFlatJSObject.setFlags(FLAT_JS_OBJECT_VALID);
 
     MOZ_ASSERT(aScope, "bad ctor param");
     MOZ_ASSERT(aSet, "bad ctor param");
 }
 
 XPCWrappedNative::~XPCWrappedNative()
@@ -900,20 +908,24 @@ XPCWrappedNative::FinishInit()
     return true;
 }
 
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(XPCWrappedNative)
   NS_INTERFACE_MAP_ENTRY(nsIXPConnectWrappedNative)
   NS_INTERFACE_MAP_ENTRY(nsIXPConnectJSObjectHolder)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXPConnectWrappedNative)
-NS_INTERFACE_MAP_END_THREADSAFE
-
-NS_IMPL_ADDREF(XPCWrappedNative)
-NS_IMPL_RELEASE(XPCWrappedNative)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(XPCWrappedNative)
+
+// Release calls Destroy() immediately when the refcount drops to 0 to
+// clear the weak references nsXPConnect has to XPCWNs and to ensure there
+// are no pointers to dying protos.
+NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(XPCWrappedNative, Destroy())
 
 /*
  *  Wrapped Native lifetime management is messy!
  *
  *  - At creation we push the refcount to 2 (only one of which is owned by
  *    the native caller that caused the wrapper creation).
  *  - During the JS GC Mark phase we mark any wrapper with a refcount > 1.
  *  - The *only* thing that can make the wrapper get destroyed is the
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -2002,39 +2002,21 @@ TraceXPCGlobal(JSTracer *trc, JSObject *
 
 /***************************************************************************/
 // XPCWrappedNative the wrapper around one instance of a native xpcom object
 // to be used from JavaScript.
 
 class XPCWrappedNative : public nsIXPConnectWrappedNative
 {
 public:
-    NS_DECL_THREADSAFE_ISUPPORTS
+    NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     NS_DECL_NSIXPCONNECTJSOBJECTHOLDER
     NS_DECL_NSIXPCONNECTWRAPPEDNATIVE
-    // No need to unlink the JS objects, if the XPCWrappedNative will be cycle
-    // collected then its mFlatJSObject will be cycle collected too and
-    // finalization of the mFlatJSObject will unlink the js objects (see
-    // XPC_WN_NoHelper_Finalize and FlatJSObjectFinalized).
-    // We also give XPCWrappedNative empty Root/Unroot methods, to avoid
-    // root/unrooting the JS objects from addrefing/releasing the
-    // XPCWrappedNative during unlinking, which would make the JS objects
-    // uncollectable to the JS GC.
-    class NS_CYCLE_COLLECTION_INNERCLASS
-     : public nsXPCOMCycleCollectionParticipant
-    {
-      NS_DECL_CYCLE_COLLECTION_CLASS_BODY(XPCWrappedNative, XPCWrappedNative)
-      NS_IMETHOD_(void) Root(void *p) { }
-      NS_IMETHOD_(void) Unroot(void *p) { }
-      NS_IMPL_GET_XPCOM_CYCLE_COLLECTION_PARTICIPANT(XPCWrappedNative)
-    };
-    NS_CHECK_FOR_RIGHT_PARTICIPANT_IMPL(XPCWrappedNative);
-    static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME;
-
-    void DeleteCycleCollectable() {}
+
+    NS_DECL_CYCLE_COLLECTION_CLASS(XPCWrappedNative)
 
     nsIPrincipal* GetObjectPrincipal() const;
 
     bool
     IsValid() const { return mFlatJSObject.hasFlag(FLAT_JS_OBJECT_VALID); }
 
 #define XPC_SCOPE_WORD(s)   (intptr_t(s))
 #define XPC_SCOPE_MASK      (intptr_t(0x3))