Backed out 3 changesets (bug 1288870) for hazards a=backout
authorWes Kocher <wkocher@mozilla.com>
Thu, 18 Aug 2016 16:50:13 -0700
changeset 351494 93545d47fddbf51aba5f7127d66dca2f0383820d
parent 351493 02ededf61cbea5c1431d2945684630caa04873c1
child 351495 0c815fa01fda163324d9d9676dd134f3fcd8169f
push id6570
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:26:13 +0000
treeherdermozilla-beta@f455459b2ae5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1288870
milestone51.0a1
backs out83bbd356da976384d6971b5ef83d415b02c7193b
4f0ab1a0d8dd56c0deeda13250ebb69e37c4a575
8d71aba5c1e7b96308a6e87ba0c66edafbd1dbdc
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
Backed out 3 changesets (bug 1288870) for hazards a=backout Backed out changeset 83bbd356da97 (bug 1288870) Backed out changeset 4f0ab1a0d8dd (bug 1288870) Backed out changeset 8d71aba5c1e7 (bug 1288870)
js/xpconnect/src/XPCCallContext.cpp
js/xpconnect/src/XPCConvert.cpp
js/xpconnect/src/XPCInlines.h
js/xpconnect/src/XPCJSID.cpp
js/xpconnect/src/XPCJSRuntime.cpp
js/xpconnect/src/XPCWrappedNative.cpp
js/xpconnect/src/XPCWrappedNativeInfo.cpp
js/xpconnect/src/XPCWrappedNativeJSOps.cpp
js/xpconnect/src/nsXPConnect.cpp
js/xpconnect/src/xpcprivate.h
xpcom/glue/nsISupportsImpl.h
--- a/js/xpconnect/src/XPCCallContext.cpp
+++ b/js/xpconnect/src/XPCCallContext.cpp
@@ -194,18 +194,16 @@ void
 XPCCallContext::SystemIsBeingShutDown()
 {
     // XXX This is pretty questionable since the per thread cleanup stuff
     // can be making this call on one thread for call contexts on another
     // thread.
     NS_WARNING("Shutting Down XPConnect even through there is a live XPCCallContext");
     mXPCJSRuntime = nullptr;
     mState = SYSTEM_SHUTDOWN;
-    mInterface = nullptr;
-
     if (mPrevCallContext)
         mPrevCallContext->SystemIsBeingShutDown();
 }
 
 XPCCallContext::~XPCCallContext()
 {
     if (mXPCJSRuntime) {
         DebugOnly<XPCCallContext*> old = mXPCJSRuntime->SetCallContext(mPrevCallContext);
--- a/js/xpconnect/src/XPCConvert.cpp
+++ b/js/xpconnect/src/XPCConvert.cpp
@@ -815,18 +815,19 @@ XPCConvert::NativeInterface2JSObject(Mut
     if (cpow) {
         if (!JS_WrapObject(cx, &cpow))
             return false;
         d.setObject(*cpow);
         return true;
     }
 
     // Go ahead and create an XPCWrappedNative for this object.
-    RefPtr<XPCNativeInterface> iface =
-        XPCNativeInterface::GetNewOrUsed(iid);
+    AutoMarkingNativeInterfacePtr iface(cx);
+
+    iface = XPCNativeInterface::GetNewOrUsed(iid);
     if (!iface)
         return false;
 
     RefPtr<XPCWrappedNative> wrapper;
     nsresult rv = XPCWrappedNative::GetNewOrUsed(aHelper, xpcscope, iface,
                                                  getter_AddRefs(wrapper));
     if (NS_FAILED(rv) && pErr)
         *pErr = rv;
--- a/js/xpconnect/src/XPCInlines.h
+++ b/js/xpconnect/src/XPCInlines.h
@@ -114,16 +114,22 @@ XPCCallContext::CanGetSet() const
 
 inline XPCNativeSet*
 XPCCallContext::GetSet() const
 {
     CHECK_STATE(HAVE_NAME);
     return mSet;
 }
 
+inline bool
+XPCCallContext::CanGetInterface() const
+{
+    return mState >= HAVE_NAME;
+}
+
 inline XPCNativeInterface*
 XPCCallContext::GetInterface() const
 {
     CHECK_STATE(HAVE_NAME);
     return mInterface;
 }
 
 inline XPCNativeMember*
@@ -310,51 +316,50 @@ XPCNativeSet::FindMember(jsid name, XPCN
             return true;
         }
     }
     return false;
 }
 
 inline bool
 XPCNativeSet::FindMember(jsid name, XPCNativeMember** pMember,
-                         RefPtr<XPCNativeInterface>* pInterface) const
+                         XPCNativeInterface** pInterface) const
 {
     uint16_t index;
     if (!FindMember(name, pMember, &index))
         return false;
     *pInterface = mInterfaces[index];
     return true;
 }
 
 inline bool
 XPCNativeSet::FindMember(jsid name,
                          XPCNativeMember** pMember,
-                         RefPtr<XPCNativeInterface>* pInterface,
+                         XPCNativeInterface** pInterface,
                          XPCNativeSet* protoSet,
                          bool* pIsLocal) const
 {
     XPCNativeMember* Member;
-    RefPtr<XPCNativeInterface> Interface;
+    XPCNativeInterface* Interface;
     XPCNativeMember* protoMember;
 
     if (!FindMember(name, &Member, &Interface))
         return false;
 
     *pMember = Member;
+    *pInterface = Interface;
 
     *pIsLocal =
         !Member ||
         !protoSet ||
         (protoSet != this &&
          !protoSet->MatchesSetUpToInterface(this, Interface) &&
          (!protoSet->FindMember(name, &protoMember, (uint16_t*)nullptr) ||
           protoMember != Member));
 
-    *pInterface = Interface.forget();
-
     return true;
 }
 
 inline XPCNativeInterface*
 XPCNativeSet::FindNamedInterface(jsid name) const
 {
     XPCNativeInterface* const * pp = mInterfaces;
 
@@ -431,23 +436,36 @@ XPCNativeSet::MatchesSetUpToInterface(co
         if (cur == iface)
             return true;
     }
     return false;
 }
 
 inline void XPCNativeSet::Mark()
 {
-    mMarked = 1;
+    if (IsMarked())
+        return;
+
+    XPCNativeInterface* const * pp = mInterfaces;
+
+    for (int i = (int) mInterfaceCount; i > 0; i--, pp++)
+        (*pp)->Mark();
+
+    MarkSelfOnly();
 }
 
 #ifdef DEBUG
 inline void XPCNativeSet::ASSERT_NotMarked()
 {
     MOZ_ASSERT(!IsMarked(), "bad");
+
+    XPCNativeInterface* const * pp = mInterfaces;
+
+    for (int i = (int) mInterfaceCount; i > 0; i--, pp++)
+        MOZ_ASSERT(!(*pp)->IsMarked(), "bad");
 }
 #endif
 
 /***************************************************************************/
 
 inline
 JSObject* XPCWrappedNativeTearOff::GetJSObjectPreserveColor() const
 {
--- a/js/xpconnect/src/XPCJSID.cpp
+++ b/js/xpconnect/src/XPCJSID.cpp
@@ -381,18 +381,19 @@ nsJSIID::Resolve(nsIXPConnectWrappedNati
                  JSContext * cx, JSObject * objArg,
                  jsid idArg, bool* resolvedp,
                  bool* _retval)
 {
     RootedObject obj(cx, objArg);
     RootedId id(cx, idArg);
     XPCCallContext ccx(cx);
 
-    RefPtr<XPCNativeInterface> iface =
-        XPCNativeInterface::GetNewOrUsed(mInfo);
+    AutoMarkingNativeInterfacePtr iface(ccx);
+
+    iface = XPCNativeInterface::GetNewOrUsed(mInfo);
 
     if (!iface)
         return NS_OK;
 
     XPCNativeMember* member = iface->FindMember(id);
     if (member && member->IsConstant()) {
         RootedValue val(cx);
         if (!member->GetConstantValue(ccx, iface, val.address()))
@@ -411,18 +412,19 @@ NS_IMETHODIMP
 nsJSIID::Enumerate(nsIXPConnectWrappedNative* wrapper,
                    JSContext * cx, JSObject * objArg, bool* _retval)
 {
     // In this case, let's just eagerly resolve...
 
     RootedObject obj(cx, objArg);
     XPCCallContext ccx(cx);
 
-    RefPtr<XPCNativeInterface> iface =
-        XPCNativeInterface::GetNewOrUsed(mInfo);
+    AutoMarkingNativeInterfacePtr iface(ccx);
+
+    iface = XPCNativeInterface::GetNewOrUsed(mInfo);
 
     if (!iface)
         return NS_OK;
 
     uint16_t count = iface->GetMemberCount();
     for (uint16_t i = 0; i < count; i++) {
         XPCNativeMember* member = iface->GetMemberAt(i);
         if (member && member->IsConstant() &&
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -799,16 +799,21 @@ XPCJSRuntime::FinalizeCallback(JSFreeOp*
                     // complains if you ask for a set when
                     // it is in a state where the set could not
                     // possibly be valid.
                     if (ccxp->CanGetSet()) {
                         XPCNativeSet* set = ccxp->GetSet();
                         if (set)
                             set->Mark();
                     }
+                    if (ccxp->CanGetInterface()) {
+                        XPCNativeInterface* iface = ccxp->GetInterface();
+                        if (iface)
+                            iface->Mark();
+                    }
                     ccxp = ccxp->GetPrevCallContext();
                 }
             }
 
             // Do the sweeping. During a compartment GC, only
             // WrappedNativeProtos in collected compartments will be
             // marked. Therefore, some reachable NativeInterfaces will not be
             // marked, so it is not safe to sweep them. We still need to unmark
@@ -835,16 +840,27 @@ XPCJSRuntime::FinalizeCallback(JSFreeOp*
                 if (set->IsMarked()) {
                     set->Unmark();
                 } else if (doSweep) {
                     XPCNativeSet::DestroyInstance(set);
                     i.Remove();
                 }
             }
 
+            for (auto i = self->mIID2NativeInterfaceMap->Iter(); !i.Done(); i.Next()) {
+                auto entry = static_cast<IID2NativeInterfaceMap::Entry*>(i.Get());
+                XPCNativeInterface* iface = entry->value;
+                if (iface->IsMarked()) {
+                    iface->Unmark();
+                } else if (doSweep) {
+                    XPCNativeInterface::DestroyInstance(iface);
+                    i.Remove();
+                }
+            }
+
 #ifdef DEBUG
             XPCWrappedNativeScope::ASSERT_NoInterfaceSetsAreMarked();
 #endif
 
             // Now we are going to recycle any unused WrappedNativeTearoffs.
             // We do this by iterating all the live callcontexts
             // and marking the tearoffs in use. And then we
             // iterate over all the WrappedNative wrappers and sweep their
--- a/js/xpconnect/src/XPCWrappedNative.cpp
+++ b/js/xpconnect/src/XPCWrappedNative.cpp
@@ -261,17 +261,17 @@ XPCWrappedNative::WrapNewGlobal(xpcObjec
     success = wrapper->FinishInit();
     MOZ_ASSERT(success);
 
     // Go through some extra work to find the tearoff. This is kind of silly
     // on a conceptual level: the point of tearoffs is to cache the results
     // of QI-ing mIdentity to different interfaces, and we don't need that
     // since we're dealing with nsISupports. But lots of code expects tearoffs
     // to exist for everything, so we just follow along.
-    RefPtr<XPCNativeInterface> iface = XPCNativeInterface::GetNewOrUsed(&NS_GET_IID(nsISupports));
+    XPCNativeInterface* iface = XPCNativeInterface::GetNewOrUsed(&NS_GET_IID(nsISupports));
     MOZ_ASSERT(iface);
     nsresult status;
     success = wrapper->FindTearOff(iface, false, &status);
     if (!success)
         return status;
 
     // Call the common creation finish routine. This does all of the bookkeeping
     // like inserting the wrapper into the wrapper map and setting up the wrapper
@@ -422,17 +422,17 @@ XPCWrappedNative::GetNewOrUsed(xpcObject
 
     if (info && !isClassInfoSingleton) {
         proto = XPCWrappedNativeProto::GetNewOrUsed(Scope, info, &sciProto);
         if (!proto)
             return NS_ERROR_FAILURE;
 
         wrapper = new XPCWrappedNative(helper.forgetCanonical(), proto);
     } else {
-        RefPtr<XPCNativeInterface> iface = Interface;
+        AutoMarkingNativeInterfacePtr iface(cx, Interface);
         if (!iface)
             iface = XPCNativeInterface::GetISupports();
 
         AutoMarkingNativeSetPtr set(cx);
         set = XPCNativeSet::GetNewOrUsed(nullptr, iface, 0);
 
         if (!set)
             return NS_ERROR_FAILURE;
@@ -1083,17 +1083,19 @@ XPCWrappedNative::FindTearOff(XPCNativeI
 
     if (pError)
         *pError = rv;
     return to;
 }
 
 XPCWrappedNativeTearOff*
 XPCWrappedNative::FindTearOff(const nsIID& iid) {
-    RefPtr<XPCNativeInterface> iface = XPCNativeInterface::GetNewOrUsed(&iid);
+    AutoJSContext cx;
+    AutoMarkingNativeInterfacePtr iface(cx);
+    iface = XPCNativeInterface::GetNewOrUsed(&iid);
     return iface ? FindTearOff(iface) : nullptr;
 }
 
 nsresult
 XPCWrappedNative::InitTearOff(XPCWrappedNativeTearOff* aTearOff,
                               XPCNativeInterface* aInterface,
                               bool needJSObject)
 {
@@ -2108,17 +2110,17 @@ XPCWrappedNative::GetObjectPrincipal() c
     }
 #endif
     return principal;
 }
 
 NS_IMETHODIMP XPCWrappedNative::FindInterfaceWithMember(HandleId name,
                                                         nsIInterfaceInfo * *_retval)
 {
-    RefPtr<XPCNativeInterface> iface;
+    XPCNativeInterface* iface;
     XPCNativeMember*  member;
 
     if (GetSet()->FindMember(name, &member, &iface) && iface) {
         nsCOMPtr<nsIInterfaceInfo> temp = iface->GetInterfaceInfo();
         temp.forget(_retval);
     } else
         *_retval = nullptr;
     return NS_OK;
@@ -2204,22 +2206,22 @@ XPCWrappedNative::ToString(XPCWrappedNat
         name = JS_smprintf("%s", si->GetJSClass()->name);
     if (to) {
         const char* fmt = name ? " (%s)" : "%s";
         name = JS_sprintf_append(name, fmt,
                                  to->GetInterface()->GetNameString());
     } else if (!name) {
         XPCNativeSet* set = GetSet();
         XPCNativeInterface** array = set->GetInterfaceArray();
-        RefPtr<XPCNativeInterface> isupp = XPCNativeInterface::GetISupports();
         uint16_t count = set->GetInterfaceCount();
 
         if (count == 1)
             name = JS_sprintf_append(name, "%s", array[0]->GetNameString());
-        else if (count == 2 && array[0] == isupp) {
+        else if (count == 2 &&
+                 array[0] == XPCNativeInterface::GetISupports()) {
             name = JS_sprintf_append(name, "%s", array[1]->GetNameString());
         } else {
             for (uint16_t i = 0; i < count; i++) {
                 const char* fmt = (i == 0) ?
                                     "(%s" : (i == count-1) ?
                                         ", %s)" : ", %s";
                 name = JS_sprintf_append(name, fmt,
                                          array[i]->GetNameString());
--- a/js/xpconnect/src/XPCWrappedNativeInfo.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeInfo.cpp
@@ -18,17 +18,17 @@ using namespace mozilla;
 
 /***************************************************************************/
 
 // XPCNativeMember
 
 // static
 bool
 XPCNativeMember::GetCallInfo(JSObject* funobj,
-                             RefPtr<XPCNativeInterface>* pInterface,
+                             XPCNativeInterface** pInterface,
                              XPCNativeMember**    pMember)
 {
     funobj = js::UncheckedUnwrap(funobj);
     Value memberVal =
         js::GetFunctionNativeReserved(funobj,
                                       XPC_FUNCTION_NATIVE_MEMBER_SLOT);
 
     *pMember = static_cast<XPCNativeMember*>(memberVal.toPrivate());
@@ -102,118 +102,119 @@ XPCNativeMember::Resolve(XPCCallContext&
     vp->setObject(*funobj);
 
     return true;
 }
 
 /***************************************************************************/
 // XPCNativeInterface
 
-XPCNativeInterface::~XPCNativeInterface()
-{
-    XPCJSRuntime::Get()->GetIID2NativeInterfaceMap()->Remove(this);
-}
-
 // static
-already_AddRefed<XPCNativeInterface>
+XPCNativeInterface*
 XPCNativeInterface::GetNewOrUsed(const nsIID* iid)
 {
-    RefPtr<XPCNativeInterface> iface;
+    AutoJSContext cx;
+    AutoMarkingNativeInterfacePtr iface(cx);
     XPCJSRuntime* rt = XPCJSRuntime::Get();
 
     IID2NativeInterfaceMap* map = rt->GetIID2NativeInterfaceMap();
     if (!map)
         return nullptr;
 
     iface = map->Find(*iid);
 
     if (iface)
-        return iface.forget();
+        return iface;
 
     nsCOMPtr<nsIInterfaceInfo> info;
     XPTInterfaceInfoManager::GetSingleton()->GetInfoForIID(iid, getter_AddRefs(info));
     if (!info)
         return nullptr;
 
     iface = NewInstance(info);
     if (!iface)
         return nullptr;
 
     XPCNativeInterface* iface2 = map->Add(iface);
     if (!iface2) {
         NS_ERROR("failed to add our interface!");
+        DestroyInstance(iface);
         iface = nullptr;
     } else if (iface2 != iface) {
+        DestroyInstance(iface);
         iface = iface2;
     }
 
-    return iface.forget();
+    return iface;
 }
 
 // static
-already_AddRefed<XPCNativeInterface>
+XPCNativeInterface*
 XPCNativeInterface::GetNewOrUsed(nsIInterfaceInfo* info)
 {
-    RefPtr<XPCNativeInterface> iface;
+    AutoJSContext cx;
+    AutoMarkingNativeInterfacePtr iface(cx);
 
     const nsIID* iid;
     if (NS_FAILED(info->GetIIDShared(&iid)) || !iid)
         return nullptr;
 
     XPCJSRuntime* rt = XPCJSRuntime::Get();
 
     IID2NativeInterfaceMap* map = rt->GetIID2NativeInterfaceMap();
     if (!map)
         return nullptr;
 
     iface = map->Find(*iid);
 
     if (iface)
-        return iface.forget();
+        return iface;
 
     iface = NewInstance(info);
     if (!iface)
         return nullptr;
 
-    RefPtr<XPCNativeInterface> iface2 = map->Add(iface);
+    XPCNativeInterface* iface2 = map->Add(iface);
     if (!iface2) {
         NS_ERROR("failed to add our interface!");
+        DestroyInstance(iface);
         iface = nullptr;
     } else if (iface2 != iface) {
+        DestroyInstance(iface);
         iface = iface2;
     }
 
-    return iface.forget();
+    return iface;
 }
 
 // static
-already_AddRefed<XPCNativeInterface>
+XPCNativeInterface*
 XPCNativeInterface::GetNewOrUsed(const char* name)
 {
     nsCOMPtr<nsIInterfaceInfo> info;
     XPTInterfaceInfoManager::GetSingleton()->GetInfoForName(name, getter_AddRefs(info));
     return info ? GetNewOrUsed(info) : nullptr;
 }
 
 // static
-already_AddRefed<XPCNativeInterface>
+XPCNativeInterface*
 XPCNativeInterface::GetISupports()
 {
     // XXX We should optimize this to cache this common XPCNativeInterface.
     return GetNewOrUsed(&NS_GET_IID(nsISupports));
 }
 
 // static
-already_AddRefed<XPCNativeInterface>
+XPCNativeInterface*
 XPCNativeInterface::NewInstance(nsIInterfaceInfo* aInfo)
 {
     AutoJSContext cx;
     static const uint16_t MAX_LOCAL_MEMBER_COUNT = 16;
     XPCNativeMember local_members[MAX_LOCAL_MEMBER_COUNT];
-    RefPtr<XPCNativeInterface> obj;
+    XPCNativeInterface* obj = nullptr;
     XPCNativeMember* members = nullptr;
 
     int i;
     bool failed = false;
     uint16_t constCount;
     uint16_t methodCount;
     uint16_t totalCount;
     uint16_t realTotalCount = 0;
@@ -386,17 +387,17 @@ XPCNativeInterface::NewInstance(nsIInter
                 memcpy(obj->mMembers, members,
                        realTotalCount * sizeof(XPCNativeMember));
         }
     }
 
     if (members && members != local_members)
         delete [] members;
 
-    return obj.forget();
+    return obj;
 }
 
 // static
 void
 XPCNativeInterface::DestroyInstance(XPCNativeInterface* inst)
 {
     inst->~XPCNativeInterface();
     delete [] (char*) inst;
@@ -464,34 +465,34 @@ XPCNativeSetKey::Hash() const
 
 // static
 XPCNativeSet*
 XPCNativeSet::GetNewOrUsed(const nsIID* iid)
 {
     AutoJSContext cx;
     AutoMarkingNativeSetPtr set(cx);
 
-    RefPtr<XPCNativeInterface> iface =
-        XPCNativeInterface::GetNewOrUsed(iid);
+    AutoMarkingNativeInterfacePtr iface(cx);
+    iface = XPCNativeInterface::GetNewOrUsed(iid);
     if (!iface)
         return nullptr;
 
     XPCNativeSetKey key(nullptr, iface, 0);
 
     XPCJSRuntime* rt = XPCJSRuntime::Get();
     NativeSetMap* map = rt->GetNativeSetMap();
     if (!map)
         return nullptr;
 
     set = map->Find(&key);
 
     if (set)
         return set;
 
-    set = NewInstance({iface.forget()});
+    set = NewInstance({iface});
     if (!set)
         return nullptr;
 
     XPCNativeSet* set2 = map->Add(&key, set);
     if (!set2) {
         NS_ERROR("failed to add our set!");
         DestroyInstance(set);
         set = nullptr;
@@ -533,35 +534,36 @@ XPCNativeSet::GetNewOrUsed(nsIClassInfo*
         iidCount = 0;
     }
 
     MOZ_ASSERT((iidCount && iidArray) || !(iidCount || iidArray), "GetInterfaces returned bad array");
 
     // !!! from here on we only exit through the 'out' label !!!
 
     if (iidCount) {
-        nsTArray<RefPtr<XPCNativeInterface>> interfaceArray(iidCount);
+        nsTArray<XPCNativeInterface*> interfaceArray(iidCount);
+        AutoMarkingNativeInterfacePtrArrayPtr arrayMarker(cx, interfaceArray);
         nsIID** currentIID = iidArray;
 
         for (uint32_t i = 0; i < iidCount; i++) {
             nsIID* iid = *(currentIID++);
             if (!iid) {
                 NS_ERROR("Null found in classinfo interface list");
                 continue;
             }
 
-            RefPtr<XPCNativeInterface> iface =
+            XPCNativeInterface* iface =
                 XPCNativeInterface::GetNewOrUsed(iid);
 
             if (!iface) {
                 // XXX warn here
                 continue;
             }
 
-            interfaceArray.AppendElement(iface.forget());
+            interfaceArray.AppendElement(iface);
         }
 
         if (interfaceArray.Length() > 0) {
             set = NewInstance(Move(interfaceArray));
             if (set) {
                 NativeSetMap* map2 = rt->GetNativeSetMap();
                 if (!map2)
                     goto out;
@@ -696,27 +698,27 @@ XPCNativeSet::GetNewOrUsed(XPCNativeSet*
 
     // We've got the union set. Hand it back to the caller.
     MOZ_ASSERT(currentSet->mInterfaceCount == uniqueCount);
     return currentSet;
 }
 
 // static
 XPCNativeSet*
-XPCNativeSet::NewInstance(nsTArray<RefPtr<XPCNativeInterface>>&& array)
+XPCNativeSet::NewInstance(nsTArray<XPCNativeInterface*>&& array)
 {
     if (array.Length() == 0)
         return nullptr;
 
     // We impose the invariant:
     // "All sets have exactly one nsISupports interface and it comes first."
     // This is the place where we impose that rule - even if given inputs
     // that don't exactly follow the rule.
 
-    RefPtr<XPCNativeInterface> isup = XPCNativeInterface::GetISupports();
+    XPCNativeInterface* isup = XPCNativeInterface::GetISupports();
     uint16_t slots = array.Length() + 1;
 
     for (auto key = array.begin(); key != array.end(); key++) {
         if (*key == isup)
             slots--;
     }
 
     // Use placement new to create an object with the right amount of space
@@ -726,24 +728,24 @@ XPCNativeSet::NewInstance(nsTArray<RefPt
         size += (slots - 1) * sizeof(XPCNativeInterface*);
     void* place = new char[size];
     XPCNativeSet* obj = new(place) XPCNativeSet();
 
     // Stick the nsISupports in front and skip additional nsISupport(s)
     XPCNativeInterface** outp = (XPCNativeInterface**) &obj->mInterfaces;
     uint16_t memberCount = 1;   // for the one member in nsISupports
 
-    NS_ADDREF(*(outp++) = isup);
+    *(outp++) = isup;
 
     for (auto key = array.begin(); key != array.end(); key++) {
-        RefPtr<XPCNativeInterface> cur = key->forget();
+        XPCNativeInterface* cur = *key;
         if (isup == cur)
             continue;
+        *(outp++) = cur;
         memberCount += cur->GetMemberCount();
-        *(outp++) = cur.forget().take();
     }
     obj->mMemberCount = memberCount;
     obj->mInterfaceCount = slots;
 
     return obj;
 }
 
 // static
@@ -768,17 +770,20 @@ XPCNativeSet::NewInstanceMutate(XPCNativ
 
     obj->mMemberCount = otherSet->GetMemberCount() +
         newInterface->GetMemberCount();
     obj->mInterfaceCount = otherSet->mInterfaceCount + 1;
 
     XPCNativeInterface** src = otherSet->mInterfaces;
     XPCNativeInterface** dest = obj->mInterfaces;
     for (uint16_t i = 0; i < obj->mInterfaceCount; i++) {
-        NS_ADDREF(*dest++ = (i == position) ? newInterface : *src++);
+        if (i == position)
+            *dest++ = newInterface;
+        else
+            *dest++ = *src++;
     }
 
     return obj;
 }
 
 // static
 void
 XPCNativeSet::DestroyInstance(XPCNativeSet* inst)
--- a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
@@ -217,28 +217,27 @@ XPC_WN_DoubleWrappedGetter(JSContext* cx
  * We *never* set toString or toSource as JS_ENUMERATE.
  */
 
 static bool
 DefinePropertyIfFound(XPCCallContext& ccx,
                       HandleObject obj,
                       HandleId idArg,
                       XPCNativeSet* set,
-                      XPCNativeInterface* ifaceArg,
+                      XPCNativeInterface* iface,
                       XPCNativeMember* member,
                       XPCWrappedNativeScope* scope,
                       bool reflectToStringAndToSource,
                       XPCWrappedNative* wrapperToReflectInterfaceNames,
                       XPCWrappedNative* wrapperToReflectDoubleWrap,
                       XPCNativeScriptableInfo* scriptableInfo,
                       unsigned propFlags,
                       bool* resolved)
 {
     RootedId id(ccx, idArg);
-    RefPtr<XPCNativeInterface> iface = ifaceArg;
     XPCJSRuntime* rt = ccx.GetRuntime();
     bool found;
     const char* name;
 
     propFlags |= JSPROP_RESOLVING;
 
     if (set) {
         if (iface)
@@ -301,17 +300,17 @@ DefinePropertyIfFound(XPCCallContext& cc
         }
         // This *might* be a tearoff name that is not yet part of our
         // set. Let's lookup the name and see if it is the name of an
         // interface. Then we'll see if the object actually *does* this
         // interface and add a tearoff as necessary.
 
         if (wrapperToReflectInterfaceNames) {
             JSAutoByteString name;
-            RefPtr<XPCNativeInterface> iface2;
+            AutoMarkingNativeInterfacePtr iface2(ccx);
             XPCWrappedNativeTearOff* to;
             RootedObject jso(ccx);
             nsresult rv = NS_OK;
 
             if (JSID_IS_STRING(id) &&
                 name.encodeLatin1(ccx, JSID_TO_STRING(id)) &&
                 (iface2 = XPCNativeInterface::GetNewOrUsed(name.ptr()), iface2) &&
                 nullptr != (to = wrapperToReflectInterfaceNames->
@@ -830,17 +829,17 @@ XPC_WN_Helper_Resolve(JSContext* cx, Han
     } else if (wrapper->HasMutatedSet()) {
         // We are here if scriptable did not resolve this property and
         // it *might* be in the instance set but not the proto set.
 
         XPCNativeSet* set = wrapper->GetSet();
         XPCNativeSet* protoSet = wrapper->HasProto() ?
                                     wrapper->GetProto()->GetSet() : nullptr;
         XPCNativeMember* member;
-        RefPtr<XPCNativeInterface> iface;
+        XPCNativeInterface* iface;
         bool IsLocal;
 
         if (set->FindMember(id, &member, &iface, protoSet, &IsLocal) &&
             IsLocal) {
             XPCWrappedNative* oldResolvingWrapper;
 
             XPCNativeScriptableFlags siFlags(0);
             if (si)
@@ -1128,17 +1127,17 @@ XPC_WN_CallMethod(JSContext* cx, unsigne
         return false;
 
     obj = FixUpThisIfBroken(obj, funobj);
     XPCCallContext ccx(cx, obj, funobj, JSID_VOIDHANDLE, args.length(),
                        args.array(), vp);
     XPCWrappedNative* wrapper = ccx.GetWrapper();
     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
 
-    RefPtr<XPCNativeInterface> iface;
+    XPCNativeInterface* iface;
     XPCNativeMember*    member;
 
     if (!XPCNativeMember::GetCallInfo(funobj, &iface, &member))
         return Throw(NS_ERROR_XPC_CANT_GET_METHOD_INFO, cx);
     ccx.SetCallInfo(iface, member, false);
     return XPCWrappedNative::CallMethod(ccx);
 }
 
@@ -1154,17 +1153,17 @@ XPC_WN_GetterSetter(JSContext* cx, unsig
         return false;
 
     obj = FixUpThisIfBroken(obj, funobj);
     XPCCallContext ccx(cx, obj, funobj, JSID_VOIDHANDLE, args.length(),
                        args.array(), vp);
     XPCWrappedNative* wrapper = ccx.GetWrapper();
     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
 
-    RefPtr<XPCNativeInterface> iface;
+    XPCNativeInterface* iface;
     XPCNativeMember*    member;
 
     if (!XPCNativeMember::GetCallInfo(funobj, &iface, &member))
         return Throw(NS_ERROR_XPC_CANT_GET_METHOD_INFO, cx);
 
     if (args.length() != 0 && member->IsWritableAttribute()) {
         ccx.SetCallInfo(iface, member, true);
         bool retval = XPCWrappedNative::SetAttribute(ccx);
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -731,18 +731,18 @@ nsXPConnect::GetWrappedNativeOfNativeObj
     *_retval = nullptr;
 
     RootedObject aScope(aJSContext, aScopeArg);
 
     XPCWrappedNativeScope* scope = ObjectScope(aScope);
     if (!scope)
         return UnexpectedFailure(NS_ERROR_FAILURE);
 
-    RefPtr<XPCNativeInterface> iface =
-        XPCNativeInterface::GetNewOrUsed(&aIID);
+    AutoMarkingNativeInterfacePtr iface(aJSContext);
+    iface = XPCNativeInterface::GetNewOrUsed(&aIID);
     if (!iface)
         return NS_ERROR_FAILURE;
 
     XPCWrappedNative* wrapper;
 
     nsresult rv = XPCWrappedNative::GetUsedOnly(aCOMObj, scope, iface, &wrapper);
     if (NS_FAILED(rv))
         return NS_ERROR_FAILURE;
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -780,17 +780,17 @@ private:
     XPCCallContext*                 mPrevCallContext;
 
     XPCWrappedNative*               mWrapper;
     XPCWrappedNativeTearOff*        mTearOff;
 
     XPCNativeScriptableInfo*        mScriptableInfo;
 
     XPCNativeSet*                   mSet;
-    RefPtr<XPCNativeInterface>      mInterface;
+    XPCNativeInterface*             mInterface;
     XPCNativeMember*                mMember;
 
     JS::RootedId                    mName;
     bool                            mStaticMemberIsLocal;
 
     unsigned                        mArgc;
     JS::Value*                      mArgv;
     JS::Value*                      mRetVal;
@@ -1113,18 +1113,18 @@ private:
 // constant.
 
 // Tight. No virtual methods. Can be bitwise copied (until any resolution done).
 
 class XPCNativeMember final
 {
 public:
     static bool GetCallInfo(JSObject* funobj,
-                            RefPtr<XPCNativeInterface>* pInterface,
-                            XPCNativeMember** pMember);
+                            XPCNativeInterface** pInterface,
+                            XPCNativeMember**    pMember);
 
     jsid   GetName() const {return mName;}
 
     uint16_t GetIndex() const {return mIndex;}
 
     bool GetConstantValue(XPCCallContext& ccx, XPCNativeInterface* iface,
                           JS::Value* pval)
         {MOZ_ASSERT(IsConstant(),
@@ -1209,23 +1209,20 @@ private:
 // XPCNativeInterface represents a single idl declared interface. This is
 // primarily the set of XPCNativeMembers.
 
 // Tight. No virtual methods.
 
 class XPCNativeInterface final
 {
   public:
-    NS_INLINE_DECL_REFCOUNTING_WITH_DESTROY(XPCNativeInterface,
-                                            DestroyInstance(this))
-
-    static already_AddRefed<XPCNativeInterface> GetNewOrUsed(const nsIID* iid);
-    static already_AddRefed<XPCNativeInterface> GetNewOrUsed(nsIInterfaceInfo* info);
-    static already_AddRefed<XPCNativeInterface> GetNewOrUsed(const char* name);
-    static already_AddRefed<XPCNativeInterface> GetISupports();
+    static XPCNativeInterface* GetNewOrUsed(const nsIID* iid);
+    static XPCNativeInterface* GetNewOrUsed(nsIInterfaceInfo* info);
+    static XPCNativeInterface* GetNewOrUsed(const char* name);
+    static XPCNativeInterface* GetISupports();
 
     inline nsIInterfaceInfo* GetInterfaceInfo() const {return mInfo.get();}
     inline jsid              GetName()          const {return mName;}
 
     inline const nsIID* GetIID() const;
     inline const char*  GetNameString() const;
     inline XPCNativeMember* FindMember(jsid name) const;
 
@@ -1237,38 +1234,59 @@ class XPCNativeInterface final
     }
     XPCNativeMember* GetMemberAt(uint16_t i) {
         MOZ_ASSERT(i < mMemberCount, "bad index");
         return &mMembers[i];
     }
 
     void DebugDump(int16_t depth);
 
+    void Mark() {
+        mMarked = 1;
+    }
+
+    void Unmark() {
+        mMarked = 0;
+    }
+
+    bool IsMarked() const {
+        return mMarked != 0;
+    }
+
+    // NOP. This is just here to make the AutoMarkingPtr code compile.
+    inline void TraceJS(JSTracer* trc) {}
+    inline void AutoTrace(JSTracer* trc) {}
+
+    static void DestroyInstance(XPCNativeInterface* inst);
+
     size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
 
   protected:
-    static already_AddRefed<XPCNativeInterface> NewInstance(nsIInterfaceInfo* aInfo);
+    static XPCNativeInterface* NewInstance(nsIInterfaceInfo* aInfo);
 
     XPCNativeInterface() = delete;
     XPCNativeInterface(nsIInterfaceInfo* aInfo, jsid aName)
-      : mInfo(aInfo), mName(aName), mMemberCount(0)
-    {}
-    ~XPCNativeInterface();
+      : mInfo(aInfo), mName(aName), mMemberCount(0), mMarked(0)
+    {
+        MOZ_COUNT_CTOR(XPCNativeInterface);
+    }
+    ~XPCNativeInterface() {
+        MOZ_COUNT_DTOR(XPCNativeInterface);
+    }
 
     void* operator new(size_t, void* p) CPP_THROW_NEW {return p;}
 
     XPCNativeInterface(const XPCNativeInterface& r) = delete;
     XPCNativeInterface& operator= (const XPCNativeInterface& r) = delete;
 
-    static void DestroyInstance(XPCNativeInterface* inst);
-
 private:
     nsCOMPtr<nsIInterfaceInfo> mInfo;
     jsid                       mName;
-    uint16_t                   mMemberCount;
+    uint16_t                   mMemberCount : 15;
+    uint16_t                   mMarked : 1;
     XPCNativeMember            mMembers[1]; // always last - object sized for array
 };
 
 /***************************************************************************/
 // XPCNativeSetKey is used to key a XPCNativeSet in a NativeSetMap.
 
 class XPCNativeSetKey final
 {
@@ -1314,26 +1332,26 @@ class XPCNativeSet final
     // ordering might differ from |firstSet|.
     static XPCNativeSet* GetNewOrUsed(XPCNativeSet* firstSet,
                                       XPCNativeSet* secondSet,
                                       bool preserveFirstSetOrder);
 
     static void ClearCacheEntryForClassInfo(nsIClassInfo* classInfo);
 
     inline bool FindMember(jsid name, XPCNativeMember** pMember,
-                           uint16_t* pInterfaceIndex) const;
+                             uint16_t* pInterfaceIndex) const;
 
     inline bool FindMember(jsid name, XPCNativeMember** pMember,
-                           RefPtr<XPCNativeInterface>* pInterface) const;
+                             XPCNativeInterface** pInterface) const;
 
     inline bool FindMember(jsid name,
-                           XPCNativeMember** pMember,
-                           RefPtr<XPCNativeInterface>* pInterface,
-                           XPCNativeSet* protoSet,
-                           bool* pIsLocal) const;
+                             XPCNativeMember** pMember,
+                             XPCNativeInterface** pInterface,
+                             XPCNativeSet* protoSet,
+                             bool* pIsLocal) const;
 
     inline bool HasInterface(XPCNativeInterface* aInterface) const;
     inline bool HasInterfaceWithAncestor(XPCNativeInterface* aInterface) const;
     inline bool HasInterfaceWithAncestor(const nsIID* iid) const;
 
     inline XPCNativeInterface* FindInterfaceWithIID(const nsIID& iid) const;
 
     inline XPCNativeInterface* FindNamedInterface(jsid name) const;
@@ -1355,16 +1373,21 @@ class XPCNativeSet final
                                           XPCNativeInterface* iface) const;
 
     inline void Mark();
 
     // NOP. This is just here to make the AutoMarkingPtr code compile.
     inline void TraceJS(JSTracer* trc) {}
     inline void AutoTrace(JSTracer* trc) {}
 
+  private:
+    void MarkSelfOnly() {
+        mMarked = 1;
+    }
+
   public:
     void Unmark() {
         mMarked = 0;
     }
     bool IsMarked() const {
         return !!mMarked;
     }
 
@@ -1374,40 +1397,35 @@ class XPCNativeSet final
 
     void DebugDump(int16_t depth);
 
     static void DestroyInstance(XPCNativeSet* inst);
 
     size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
 
   protected:
-    static XPCNativeSet* NewInstance(nsTArray<RefPtr<XPCNativeInterface>>&& array);
+    static XPCNativeSet* NewInstance(nsTArray<XPCNativeInterface*>&& array);
     static XPCNativeSet* NewInstanceMutate(XPCNativeSet*       otherSet,
                                            XPCNativeInterface* newInterface,
                                            uint16_t            position);
     XPCNativeSet()
       : mMemberCount(0), mInterfaceCount(0), mMarked(0)
     {
         MOZ_COUNT_CTOR(XPCNativeSet);
     }
     ~XPCNativeSet() {
-        for (int i = 0; i < mInterfaceCount; i++) {
-            NS_RELEASE(mInterfaces[i]);
-        }
         MOZ_COUNT_DTOR(XPCNativeSet);
     }
     void* operator new(size_t, void* p) CPP_THROW_NEW {return p;}
 
   private:
     uint16_t                mMemberCount;
     uint16_t                mInterfaceCount : 15;
     uint16_t                mMarked : 1;
-    // Always last - object sized for array.
-    // These are strong references.
-    XPCNativeInterface*     mInterfaces[1];
+    XPCNativeInterface*     mInterfaces[1];  // always last - object sized for array
 };
 
 /***************************************************************************/
 // XPCNativeScriptableFlags is a wrapper class that holds the flags returned
 // from calls to nsIXPCScriptable::GetScriptableFlags(). It has convenience
 // methods to check for particular bitflags.
 
 class XPCNativeScriptableFlags final
@@ -2855,21 +2873,55 @@ class TypedAutoMarkingPtr : public AutoM
         if (mPtr)
             mPtr->Mark();
     }
 
   private:
     T* mPtr;
 };
 
+typedef TypedAutoMarkingPtr<XPCNativeInterface> AutoMarkingNativeInterfacePtr;
 typedef TypedAutoMarkingPtr<XPCNativeSet> AutoMarkingNativeSetPtr;
 typedef TypedAutoMarkingPtr<XPCWrappedNative> AutoMarkingWrappedNativePtr;
 typedef TypedAutoMarkingPtr<XPCWrappedNativeTearOff> AutoMarkingWrappedNativeTearOffPtr;
 typedef TypedAutoMarkingPtr<XPCWrappedNativeProto> AutoMarkingWrappedNativeProtoPtr;
 
+template<class T>
+class ArrayAutoMarkingPtr : public AutoMarkingPtr
+{
+  public:
+    ArrayAutoMarkingPtr(JSContext* cx, nsTArray<T*>& ptr)
+      : AutoMarkingPtr(cx), mPtr(ptr)
+    {}
+
+  protected:
+    virtual void TraceJS(JSTracer* trc)
+    {
+        for (uint32_t i = 0; i < mPtr.Length(); i++) {
+            if (mPtr[i]) {
+                mPtr[i]->TraceJS(trc);
+                mPtr[i]->AutoTrace(trc);
+            }
+        }
+    }
+
+    virtual void MarkAfterJSFinalize()
+    {
+        for (uint32_t i = 0; i < mPtr.Length(); i++) {
+            if (mPtr[i])
+                mPtr[i]->Mark();
+        }
+    }
+
+  private:
+    nsTArray<T*>& mPtr;
+};
+
+typedef ArrayAutoMarkingPtr<XPCNativeInterface> AutoMarkingNativeInterfacePtrArrayPtr;
+
 /***************************************************************************/
 namespace xpc {
 // Allocates a string that grants all access ("AllAccess")
 char*
 CloneAllAccess();
 
 // Returns access if wideName is in list
 char*
--- a/xpcom/glue/nsISupportsImpl.h
+++ b/xpcom/glue/nsISupportsImpl.h
@@ -487,58 +487,46 @@ public:
 
 ///////////////////////////////////////////////////////////////////////////////
 
 /**
  * Use this macro to declare and implement the AddRef & Release methods for a
  * given non-XPCOM <i>_class</i>.
  *
  * @param _class The name of the class implementing the method
- * @param _destroy A statement that is executed when the object's
- *   refcount drops to zero.
  * @param optional override Mark the AddRef & Release methods as overrides.
  */
-#define NS_INLINE_DECL_REFCOUNTING_WITH_DESTROY(_class, _destroy, ...)        \
+#define NS_INLINE_DECL_REFCOUNTING(_class, ...)                               \
 public:                                                                       \
   NS_METHOD_(MozExternalRefCountType) AddRef(void) __VA_ARGS__ {              \
     MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class)                                \
     MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt");                      \
     NS_ASSERT_OWNINGTHREAD(_class);                                           \
     ++mRefCnt;                                                                \
     NS_LOG_ADDREF(this, mRefCnt, #_class, sizeof(*this));                     \
     return mRefCnt;                                                           \
   }                                                                           \
   NS_METHOD_(MozExternalRefCountType) Release(void) __VA_ARGS__ {             \
     MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");                          \
     NS_ASSERT_OWNINGTHREAD(_class);                                           \
     --mRefCnt;                                                                \
     NS_LOG_RELEASE(this, mRefCnt, #_class);                                   \
     if (mRefCnt == 0) {                                                       \
       mRefCnt = 1; /* stabilize */                                            \
-      _destroy;                                                               \
+      delete this;                                                            \
       return 0;                                                               \
     }                                                                         \
     return mRefCnt;                                                           \
   }                                                                           \
   typedef mozilla::FalseType HasThreadSafeRefCnt;                             \
 protected:                                                                    \
   nsAutoRefCnt mRefCnt;                                                       \
   NS_DECL_OWNINGTHREAD                                                        \
 public:
 
-/**
- * Use this macro to declare and implement the AddRef & Release methods for a
- * given non-XPCOM <i>_class</i>.
- *
- * @param _class The name of the class implementing the method
- * @param optional override Mark the AddRef & Release methods as overrides.
- */
-#define NS_INLINE_DECL_REFCOUNTING(_class, ...)                               \
-  NS_INLINE_DECL_REFCOUNTING_WITH_DESTROY(_class, delete(this), __VA_ARGS__)
-
 #define NS_INLINE_DECL_THREADSAFE_REFCOUNTING_META(_class, _decl, ...)        \
 public:                                                                       \
   _decl(MozExternalRefCountType) AddRef(void) __VA_ARGS__ {                   \
     MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class)                                \
     MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt");                      \
     nsrefcnt count = ++mRefCnt;                                               \
     NS_LOG_ADDREF(this, count, #_class, sizeof(*this));                       \
     return (nsrefcnt) count;                                                  \