Merge remote-tracking branch 'origin/tracking' into custom

This commit is contained in:
roytam1 2025-01-20 21:13:46 +08:00
commit 904406a497
154 changed files with 402 additions and 422 deletions

View file

@ -248,9 +248,24 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsAggregatedCycleCollectionParticipant,
#define NS_INTERFACE_MAP_BEGIN_AGGREGATED(_class) \
NS_IMPL_AGGREGATED_QUERY_HEAD(_class)
#define NS_IMPL_QUERY_CYCLE_COLLECTION(_class) \
if ( aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant)) ) { \
*aInstancePtr = NS_CYCLE_COLLECTION_PARTICIPANT(_class); \
return NS_OK; \
} else
#define NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_AGGREGATED(_class) \
NS_IMPL_QUERY_CYCLE_COLLECTION(_class)
#define NS_IMPL_QUERY_CYCLE_COLLECTION_ISUPPORTS(_class) \
if ( aIID.Equals(NS_GET_IID(nsCycleCollectionISupports)) ) { \
*aInstancePtr = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this); \
return NS_OK; \
} else
#define NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_ISUPPORTS(_class) \
NS_IMPL_QUERY_CYCLE_COLLECTION_ISUPPORTS(_class)
#define NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION_AGGREGATED(_class) \
NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_AGGREGATED(_class) \
NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_ISUPPORTS(_class)

View file

@ -961,27 +961,6 @@ CanonicalizeXPCOMParticipant(nsISupports* aIn)
return out;
}
static inline void
ToParticipant(nsISupports* aPtr, nsXPCOMCycleCollectionParticipant** aCp);
static void
CanonicalizeParticipant(void** aParti, nsCycleCollectionParticipant** aCp)
{
// If the participant is null, this is an nsISupports participant,
// so we must QI to get the real participant.
if (!*aCp) {
nsISupports* nsparti = static_cast<nsISupports*>(*aParti);
nsparti = CanonicalizeXPCOMParticipant(nsparti);
NS_ASSERTION(nsparti,
"Don't add objects that don't participate in collection!");
nsXPCOMCycleCollectionParticipant* xcp;
ToParticipant(nsparti, &xcp);
*aParti = nsparti;
*aCp = xcp;
}
}
struct nsPurpleBufferEntry
{
nsPurpleBufferEntry(void* aObject, nsCycleCollectingAutoRefCnt* aRefCnt,
@ -1414,6 +1393,21 @@ ToParticipant(nsISupports* aPtr, nsXPCOMCycleCollectionParticipant** aCp)
CallQueryInterface(aPtr, aCp);
}
static void
ToParticipant(void* aParti, nsCycleCollectionParticipant** aCp)
{
// If the participant is null, this is an nsISupports participant,
// so we must QI to get the real participant.
if (!*aCp) {
nsISupports* nsparti = static_cast<nsISupports*>(aParti);
MOZ_ASSERT(CanonicalizeXPCOMParticipant(nsparti) == nsparti);
nsXPCOMCycleCollectionParticipant* xcp;
ToParticipant(nsparti, &xcp);
*aCp = xcp;
}
}
template<class Visitor>
MOZ_NEVER_INLINE void
GraphWalker<Visitor>::Walk(PtrInfo* aPi)
@ -2094,7 +2088,7 @@ private:
public:
// nsCycleCollectionNoteRootCallback methods.
NS_IMETHOD_(void) NoteXPCOMRoot(nsISupports* aRoot);
NS_IMETHOD_(void) NoteXPCOMRoot(nsISupports* aRoot, nsCycleCollectionParticipant* aParticipant);
NS_IMETHOD_(void) NoteJSRoot(JSObject* aRoot);
NS_IMETHOD_(void) NoteNativeRoot(void* aRoot,
nsCycleCollectionParticipant* aParticipant);
@ -2220,7 +2214,7 @@ CCGraphBuilder::AddNode(void* aPtr, nsCycleCollectionParticipant* aParticipant)
bool
CCGraphBuilder::AddPurpleRoot(void* aRoot, nsCycleCollectionParticipant* aParti)
{
CanonicalizeParticipant(&aRoot, &aParti);
ToParticipant(aRoot, &aParti);
if (WantAllTraces() || !aParti->CanSkipInCC(aRoot)) {
PtrInfo* pinfo = AddNode(aRoot, aParti);
@ -2287,16 +2281,17 @@ CCGraphBuilder::BuildGraph(SliceBudget& aBudget)
}
NS_IMETHODIMP_(void)
CCGraphBuilder::NoteXPCOMRoot(nsISupports* aRoot)
CCGraphBuilder::NoteXPCOMRoot(nsISupports* aRoot, nsCycleCollectionParticipant* aParticipant)
{
aRoot = CanonicalizeXPCOMParticipant(aRoot);
NS_ASSERTION(aRoot,
"Don't add objects that don't participate in collection!");
MOZ_ASSERT(aRoot == CanonicalizeXPCOMParticipant(aRoot));
#ifdef DEBUG
nsXPCOMCycleCollectionParticipant* cp;
ToParticipant(aRoot, &cp);
MOZ_ASSERT(aParticipant == cp);
#endif
NoteRoot(aRoot, cp);
NoteRoot(aRoot, aParticipant);
}
NS_IMETHODIMP_(void)
@ -2658,7 +2653,7 @@ public:
if (!aEntry->mRefCnt->get()) {
void* o = aEntry->mObject;
nsCycleCollectionParticipant* cp = aEntry->mParticipant;
CanonicalizeParticipant(&o, &cp);
ToParticipant(o, &cp);
SnowWhiteObject swo = { o, cp, aEntry->mRefCnt };
mObjects.InfallibleAppend(swo);
aBuffer.Remove(aEntry);
@ -2774,7 +2769,7 @@ public:
}
void* o = aEntry->mObject;
nsCycleCollectionParticipant* cp = aEntry->mParticipant;
CanonicalizeParticipant(&o, &cp);
ToParticipant(o, &cp);
if (aEntry->mRefCnt->IsPurple() && !cp->CanSkip(o, false) &&
(!mRemoveChildlessNodes || MayHaveChild(o, cp))) {
return;
@ -2981,10 +2976,8 @@ public:
"Snow-white objects shouldn't be in the purple buffer.");
void* obj = aEntry->mObject;
if (!aEntry->mParticipant) {
obj = CanonicalizeXPCOMParticipant(static_cast<nsISupports*>(obj));
MOZ_ASSERT(obj, "Don't add objects that don't participate in collection!");
}
MOZ_ASSERT(aEntry->mParticipant || CanonicalizeXPCOMParticipant(static_cast<nsISupports*>(obj)) == obj,
"Suspect nsISupports pointer must be canonical");
PtrInfo* pi = mGraph.FindNode(obj);
if (!pi) {
@ -3455,6 +3448,9 @@ nsCycleCollector::Suspect(void* aPtr, nsCycleCollectionParticipant* aParti,
MOZ_ASSERT(HasParticipant(aPtr, aParti),
"Suspected nsISupports pointer must QI to nsXPCOMCycleCollectionParticipant");
MOZ_ASSERT(aParti || CanonicalizeXPCOMParticipant(static_cast<nsISupports*>(aPtr)) == aPtr,
"Suspect nsISupports pointer must be canonical");
mPurpleBuf.Put(aPtr, aParti, aRefCnt);
}
@ -3953,7 +3949,7 @@ SuspectAfterShutdown(void* aPtr, nsCycleCollectionParticipant* aCp,
if (aRefCnt->get() == 0) {
if (!aShouldDelete) {
// The CC is shut down, so we can't be in the middle of an ICC.
CanonicalizeParticipant(&aPtr, &aCp);
ToParticipant(aPtr, &aCp);
aRefCnt->stabilizeForDeletion();
aCp->DeleteCycleCollectable(aPtr);
} else {

View file

@ -12,7 +12,9 @@ class nsISupports;
class nsCycleCollectionNoteRootCallback
{
public:
NS_IMETHOD_(void) NoteXPCOMRoot(nsISupports* aRoot) = 0;
// aRoot must be canonical (ie the result of QIing to nsCycleCollectionISupports).
NS_IMETHOD_(void) NoteXPCOMRoot(nsISupports* aRoot,
nsCycleCollectionParticipant* aParticipant) = 0;
NS_IMETHOD_(void) NoteJSRoot(JSObject* aRoot) = 0;
NS_IMETHOD_(void) NoteNativeRoot(void* aRoot,
nsCycleCollectionParticipant* aParticipant) = 0;

View file

@ -11,12 +11,17 @@
#include "nsCycleCollectionNoteChild.h"
#include "js/RootingAPI.h"
/**
* Note: the two IIDs below only differ in one bit in the last byte. This
* is an intentional hack in order to speed up the comparison inside
* NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED.
*/
#define NS_XPCOMCYCLECOLLECTIONPARTICIPANT_IID \
{ \
0x9674489b, \
0x1f6f, \
0x4550, \
{ 0xa7, 0x30, 0xcc, 0xae, 0xdd, 0x10, 0x4c, 0xf9 } \
0xc61eac14, \
0x5f7a, \
0x4481, \
{ 0x96, 0x5e, 0x7e, 0xaa, 0x6e, 0xff, 0xa8, 0x5e } \
}
/**
@ -251,51 +256,65 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsXPCOMCycleCollectionParticipant,
#define NS_CYCLE_COLLECTION_CLASSNAME(_class) \
_class::NS_CYCLE_COLLECTION_INNERCLASS
#define NS_IMPL_QUERY_CYCLE_COLLECTION(_class) \
if ( aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant)) ) { \
*aInstancePtr = NS_CYCLE_COLLECTION_PARTICIPANT(_class); \
return NS_OK; \
} else
#define NS_IMPL_QUERY_CYCLE_COLLECTION_ISUPPORTS(_class) \
if ( aIID.Equals(NS_GET_IID(nsCycleCollectionISupports)) ) { \
*aInstancePtr = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this); \
return NS_OK; \
} else
#define NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION(_class) \
NS_IMPL_QUERY_CYCLE_COLLECTION(_class)
#define NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_ISUPPORTS(_class) \
NS_IMPL_QUERY_CYCLE_COLLECTION_ISUPPORTS(_class)
// The IIDs for nsXPCOMCycleCollectionParticipant and nsCycleCollectionISupports
// are special in that they only differ in their last byte. This allows for the
// optimization below where we first check the first three words of the IID and
// if we find a match we check the last word to decide which case we have to
// deal with.
#define NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(_class) \
NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION(_class) \
NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_ISUPPORTS(_class)
if (TopThreeWordsEquals(aIID, NS_GET_IID(nsXPCOMCycleCollectionParticipant), \
NS_GET_IID(nsCycleCollectionISupports)) && \
/* The calls to LowWordEquals here are repeated inside the if branch. \
This is due to the fact that we need to maintain the if/else chain \
for these macros, so that the control flow never enters the if branch\
unless if we're certain one of the LowWordEquals() branches will get \
executed. */ \
(LowWordEquals(aIID, NS_GET_IID(nsXPCOMCycleCollectionParticipant)) || \
LowWordEquals(aIID, NS_GET_IID(nsCycleCollectionISupports)))) { \
if (LowWordEquals(aIID, NS_GET_IID(nsXPCOMCycleCollectionParticipant))) { \
*aInstancePtr = NS_CYCLE_COLLECTION_PARTICIPANT(_class); \
return NS_OK; \
} \
if (LowWordEquals(aIID, NS_GET_IID(nsCycleCollectionISupports))) { \
*aInstancePtr = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this); \
return NS_OK; \
} else { \
/* Avoid warnings about foundInterface being left uninitialized. */ \
foundInterface = nullptr; \
} \
} else
#define NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(_class) \
NS_INTERFACE_MAP_BEGIN(_class) \
NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(_class)
#define NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(_class) \
NS_INTERFACE_MAP_BEGIN(_class) \
NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION(_class)
#define NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(_class) \
if (rv == NS_OK) return rv; \
nsISupports* foundInterface; \
NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(_class)
// The IIDs for nsXPCOMCycleCollectionParticipant and nsCycleCollectionISupports
// are special in that they only differ in their last byte. This allows for the
// optimization below where we first check the first three words of the IID and
// if we find a match we check the last word to decide which case we have to
// deal with.
#define NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(_class) \
NS_IMETHODIMP _class::QueryInterface(REFNSIID aIID, void** aInstancePtr) \
{ \
NS_PRECONDITION(aInstancePtr, "null out param"); \
\
if ( aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant)) ) { \
*aInstancePtr = NS_CYCLE_COLLECTION_PARTICIPANT(_class); \
return NS_OK; \
if (TopThreeWordsEquals(aIID, NS_GET_IID(nsXPCOMCycleCollectionParticipant), \
NS_GET_IID(nsCycleCollectionISupports))) { \
if (LowWordEquals(aIID, NS_GET_IID(nsXPCOMCycleCollectionParticipant))) { \
*aInstancePtr = NS_CYCLE_COLLECTION_PARTICIPANT(_class); \
return NS_OK; \
} \
if (LowWordEquals(aIID, NS_GET_IID(nsCycleCollectionISupports))) { \
*aInstancePtr = NS_CYCLE_COLLECTION_CLASSNAME(_class)::Upcast(this); \
return NS_OK; \
} \
} \
nsresult rv;
nsresult rv = NS_ERROR_FAILURE;
#define NS_CYCLE_COLLECTION_UPCAST(obj, clazz) \
NS_CYCLE_COLLECTION_CLASSNAME(clazz)::Upcast(obj)
@ -867,4 +886,46 @@ static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME;
#define NS_CYCLE_COLLECTION_NOTE_EDGE_NAME CycleCollectionNoteEdgeName
/**
* Convenience macros for defining nISupports methods in a cycle collected class.
*/
#define NS_IMPL_QUERY_INTERFACE_CYCLE_COLLECTION_INHERITED(aClass, aSuper, ...) \
NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(aClass) \
NS_INTERFACE_TABLE_INHERITED(aClass, __VA_ARGS__) \
NS_INTERFACE_TABLE_TAIL_INHERITING(aSuper)
#define NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(aClass, aSuper, ...) \
NS_IMPL_QUERY_INTERFACE_CYCLE_COLLECTION_INHERITED(aClass, aSuper, __VA_ARGS__) \
NS_IMPL_ADDREF_INHERITED(aClass, aSuper) \
NS_IMPL_RELEASE_INHERITED(aClass, aSuper)
// *** Fast IID comparison helper functions ***
/**
* Equivalency of the high three words where two IIDs have the same
* top three words but not the same low word.
*/
inline bool TopThreeWordsEquals(const nsID& aID,
const nsID& aOther1,
const nsID& aOther2)
{
MOZ_ASSERT((((uint32_t*)&aOther1.m0)[0] == ((uint32_t*)&aOther2.m0)[0]) &&
(((uint32_t*)&aOther1.m0)[1] == ((uint32_t*)&aOther2.m0)[1]) &&
(((uint32_t*)&aOther1.m0)[2] == ((uint32_t*)&aOther2.m0)[2]) &&
(((uint32_t*)&aOther1.m0)[3] != ((uint32_t*)&aOther2.m0)[3]));
return ((((uint32_t*)&aID.m0)[0] == ((uint32_t*)&aOther1.m0)[0]) &&
(((uint32_t*)&aID.m0)[1] == ((uint32_t*)&aOther1.m0)[1]) &&
(((uint32_t*)&aID.m0)[2] == ((uint32_t*)&aOther1.m0)[2]));
}
/**
* Equivalency of the fourth word where the two IIDs have the same
* top three words but not the same low word.
*/
inline bool LowWordEquals(const nsID& aID, const nsID& aOther)
{
return (((uint32_t*)&aID.m0)[3] == ((uint32_t*)&aOther.m0)[3]);
}
#endif // nsCycleCollectionParticipant_h__