Issue #2678 - Optimize inherited cycle-collectible QueryInterface() implementations for nsCycleCollectionISupports;

This commit is contained in:
Moonchild 2025-01-17 14:54:40 +01:00 committed by roytam1
commit 85aa4cb31e

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 } \
}
/**
@ -263,8 +268,33 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsXPCOMCycleCollectionParticipant,
return NS_OK; \
} else
// 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_ENTRY_CYCLE_COLLECTION(_class) \
NS_IMPL_QUERY_CYCLE_COLLECTION(_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_ENTRY_CYCLE_COLLECTION_ISUPPORTS(_class) \
NS_IMPL_QUERY_CYCLE_COLLECTION_ISUPPORTS(_class)
@ -279,21 +309,34 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsXPCOMCycleCollectionParticipant,
#define NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(_class) \
NS_INTERFACE_MAP_BEGIN(_class) \
NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION(_class)
NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION(_class) \
NS_INTERFACE_MAP_ENTRY_CYCLE_COLLECTION_ISUPPORTS(_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;
@ -867,4 +910,32 @@ static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME;
#define NS_CYCLE_COLLECTION_NOTE_EDGE_NAME CycleCollectionNoteEdgeName
// *** 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__