Bug 944492, part 2 - Make XPCWrappedJS a proper skippable class. r=smaug

This commit is contained in:
Andrew McCreight 2013-12-12 19:38:50 -08:00
Родитель 59eb74b6f5
Коммит a324b39e7f
3 изменённых файлов: 54 добавлений и 37 удалений

Просмотреть файл

@ -668,35 +668,6 @@ XPCJSRuntime::SuspectWrappedNative(XPCWrappedNative *wrapper,
cb.NoteJSRoot(obj);
}
bool
CanSkipWrappedJS(nsXPCWrappedJS *wrappedJS)
{
JSObject *obj = wrappedJS->GetJSObjectPreserveColor();
// If traversing wrappedJS wouldn't release it, nor
// cause any other objects to be added to the graph, no
// need to add it to the graph at all.
bool isRootWrappedJS = wrappedJS->IsRootWrapper();
if (nsCCUncollectableMarker::sGeneration &&
(!obj || !xpc_IsGrayGCThing(obj)) &&
!wrappedJS->IsSubjectToFinalization() &&
(isRootWrappedJS || CanSkipWrappedJS(wrappedJS->GetRootWrapper()))) {
if (!wrappedJS->IsAggregatedToNative() || !isRootWrappedJS) {
return true;
} else {
nsISupports* agg = wrappedJS->GetAggregatedNativeObject();
nsXPCOMCycleCollectionParticipant* cp = nullptr;
CallQueryInterface(agg, &cp);
nsISupports* canonical = nullptr;
agg->QueryInterface(NS_GET_IID(nsCycleCollectionISupports),
reinterpret_cast<void**>(&canonical));
if (cp && canonical && cp->CanSkipInCC(canonical)) {
return true;
}
}
}
return false;
}
void
XPCJSRuntime::TraverseAdditionalNativeRoots(nsCycleCollectionNoteRootCallback &cb)
{
@ -714,13 +685,7 @@ XPCJSRuntime::TraverseAdditionalNativeRoots(nsCycleCollectionNoteRootCallback &c
}
for (XPCRootSetElem *e = mWrappedJSRoots; e ; e = e->GetNextRoot()) {
nsXPCWrappedJS *wrappedJS = static_cast<nsXPCWrappedJS*>(e);
if (!cb.WantAllTraces() &&
CanSkipWrappedJS(wrappedJS)) {
continue;
}
cb.NoteXPCOMRoot(static_cast<nsIXPConnectWrappedJS *>(wrappedJS));
cb.NoteXPCOMRoot(ToSupports(static_cast<nsXPCWrappedJS*>(e)));
}
}

Просмотреть файл

@ -8,6 +8,7 @@
#include "xpcprivate.h"
#include "jsprf.h"
#include "nsCCUncollectableMarker.h"
#include "nsCxPusher.h"
#include "nsContentUtils.h"
#include "nsThreadUtils.h"
@ -50,6 +51,42 @@ using namespace mozilla;
// result in a leak if a wrapper in the non-rooting state has an aggregated native that
// keeps alive the wrapper's JS object. See bug 947049.
// If traversing wrappedJS wouldn't release it, nor cause any other objects to be
// added to the graph, there is no need to add it to the graph at all.
bool
nsXPCWrappedJS::CanSkip()
{
if (!nsCCUncollectableMarker::sGeneration)
return false;
if (IsSubjectToFinalization())
return true;
// If this wrapper holds a gray object, need to trace it.
JSObject *obj = GetJSObjectPreserveColor();
if (obj && xpc_IsGrayGCThing(obj))
return false;
// For non-root wrappers, check if the root wrapper will be
// added to the CC graph.
if (!IsRootWrapper())
return mRoot->CanSkip();
// For the root wrapper, check if there is an aggregated
// native object that will be added to the CC graph.
if (!IsAggregatedToNative())
return true;
nsISupports* agg = GetAggregatedNativeObject();
nsXPCOMCycleCollectionParticipant* cp = nullptr;
CallQueryInterface(agg, &cp);
nsISupports* canonical = nullptr;
agg->QueryInterface(NS_GET_IID(nsCycleCollectionISupports),
reinterpret_cast<void**>(&canonical));
return cp && canonical && cp->CanSkipThis(canonical);
}
NS_IMETHODIMP
NS_CYCLE_COLLECTION_CLASSNAME(nsXPCWrappedJS)::Traverse
(void *p, nsCycleCollectionTraversalCallback &cb)
@ -103,6 +140,20 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXPCWrappedJS)
tmp->Unlink();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
// XPCJSRuntime keeps a table of WJS, so we can remove them from
// the purple buffer in between CCs.
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsXPCWrappedJS)
return true;
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsXPCWrappedJS)
return tmp->CanSkip();
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsXPCWrappedJS)
return tmp->CanSkip();
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
NS_IMETHODIMP
nsXPCWrappedJS::AggregatedQueryInterface(REFNSIID aIID, void** aInstancePtr)
{

Просмотреть файл

@ -2470,7 +2470,7 @@ public:
NS_DECL_NSISUPPORTSWEAKREFERENCE
NS_DECL_NSIPROPERTYBAG
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXPCWrappedJS, nsIXPConnectWrappedJS)
NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS_AMBIGUOUS(nsXPCWrappedJS, nsIXPConnectWrappedJS)
NS_IMETHOD CallMethod(uint16_t methodIndex,
const XPTMethodDescriptor *info,
@ -2533,6 +2533,7 @@ protected:
nsXPCWrappedJS* root,
nsISupports* aOuter);
bool CanSkip();
void Destroy();
void Unlink();