зеркало из https://github.com/mozilla/gecko-dev.git
Bug 944492, part 2 - Make XPCWrappedJS a proper skippable class. r=smaug
This commit is contained in:
Родитель
59eb74b6f5
Коммит
a324b39e7f
|
@ -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();
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче