--- a/accessible/src/base/AccEvent.cpp
+++ b/accessible/src/base/AccEvent.cpp
@@ -83,17 +83,17 @@ AccEvent::CreateXPCOMObject()
nsAccEvent* event = new nsAccEvent(this);
NS_IF_ADDREF(event);
return event;
}
////////////////////////////////////////////////////////////////////////////////
// AccEvent cycle collection
-NS_IMPL_CYCLE_COLLECTION_CLASS(AccEvent)
+NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(AccEvent)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(AccEvent)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mAccessible)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(AccEvent)
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mAccessible");
cb.NoteXPCOMChild(static_cast<nsIAccessible*>(tmp->mAccessible));
--- a/accessible/src/base/NotificationController.cpp
+++ b/accessible/src/base/NotificationController.cpp
@@ -51,17 +51,17 @@ NotificationController::~NotificationCon
}
////////////////////////////////////////////////////////////////////////////////
// NotificationCollector: AddRef/Release and cycle collection
NS_IMPL_ADDREF(NotificationController)
NS_IMPL_RELEASE(NotificationController)
-NS_IMPL_CYCLE_COLLECTION_CLASS(NotificationController)
+NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(NotificationController)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(NotificationController)
if (tmp->mDocument)
tmp->Shutdown();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(NotificationController)
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mDocument");
@@ -807,17 +807,17 @@ NotificationController::ContentInsertion
}
node = node->GetNextSibling();
}
return haveToUpdate;
}
-NS_IMPL_CYCLE_COLLECTION_CLASS(NotificationController::ContentInsertion)
+NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(NotificationController::ContentInsertion)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(NotificationController::ContentInsertion)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContainer)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(NotificationController::ContentInsertion)
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mContainer");
cb.NoteXPCOMChild(static_cast<nsIAccessible*>(tmp->mContainer.get()));
--- a/accessible/src/generic/Accessible.cpp
+++ b/accessible/src/generic/Accessible.cpp
@@ -106,17 +106,17 @@ NS_IMPL_RELEASE_INHERITED(Accessible, ns
nsresult
Accessible::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
// Custom-built QueryInterface() knows when we support nsIAccessibleSelectable
// based on role attribute and aria-multiselectable
*aInstancePtr = nsnull;
if (aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant))) {
- *aInstancePtr = &NS_CYCLE_COLLECTION_NAME(Accessible);
+ *aInstancePtr = NS_CYCLE_COLLECTION_PARTICIPANT(Accessible);
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsIAccessible))) {
*aInstancePtr = static_cast<nsIAccessible*>(this);
NS_ADDREF_THIS();
return NS_OK;
}
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -85,26 +85,28 @@ public:
XRE_GetFileFromPathType XRE_GetFileFromPath;
XRE_CreateAppDataType XRE_CreateAppData;
XRE_FreeAppDataType XRE_FreeAppData;
#ifdef XRE_HAS_DLL_BLOCKLIST
XRE_SetupDllBlocklistType XRE_SetupDllBlocklist;
#endif
XRE_TelemetryAccumulateType XRE_TelemetryAccumulate;
+XRE_StartupTimelineRecordType XRE_StartupTimelineRecord;
XRE_mainType XRE_main;
static const nsDynamicFunctionLoad kXULFuncs[] = {
{ "XRE_GetFileFromPath", (NSFuncPtr*) &XRE_GetFileFromPath },
{ "XRE_CreateAppData", (NSFuncPtr*) &XRE_CreateAppData },
{ "XRE_FreeAppData", (NSFuncPtr*) &XRE_FreeAppData },
#ifdef XRE_HAS_DLL_BLOCKLIST
{ "XRE_SetupDllBlocklist", (NSFuncPtr*) &XRE_SetupDllBlocklist },
#endif
{ "XRE_TelemetryAccumulate", (NSFuncPtr*) &XRE_TelemetryAccumulate },
+ { "XRE_StartupTimelineRecord", (NSFuncPtr*) &XRE_StartupTimelineRecord },
{ "XRE_main", (NSFuncPtr*) &XRE_main },
{ nsnull, nsnull }
};
static int do_main(int argc, char* argv[])
{
nsCOMPtr<nsIFile> appini;
nsresult rv;
@@ -184,18 +186,41 @@ bool IsPrefetchDisabledViaService()
RegQueryValueExW(baseKey, L"FFPrefetchDisabled", 0, NULL,
reinterpret_cast<LPBYTE>(&disabledValue),
&disabledValueSize);
RegCloseKey(baseKey);
return disabledValue == 1;
}
#endif
+/* Local implementation of PR_Now, since the executable can't depend on NSPR */
+static PRTime _PR_Now()
+{
+#ifdef XP_WIN
+ MOZ_STATIC_ASSERT(sizeof(PRTime) == sizeof(FILETIME), "PRTime must have the same size as FILETIME");
+ FILETIME ft;
+ GetSystemTimeAsFileTime(&ft);
+ PRTime now;
+ CopyMemory(&now, &ft, sizeof(PRTime));
+#ifdef __GNUC__
+ return (now - 116444736000000000LL) / 10LL;
+#else
+ return (now - 116444736000000000i64) / 10i64;
+#endif
+
+#else
+ struct timeval tm;
+ gettimeofday(&tm, 0);
+ return (((PRTime)tm.tv_sec * 1000000LL) + (PRTime)tm.tv_usec);
+#endif
+}
+
int main(int argc, char* argv[])
{
+ PRTime start = _PR_Now();
char exePath[MAXPATHLEN];
#ifdef XP_MACOSX
TriggerQuirks();
#endif
nsresult rv = mozilla::BinaryPath::Get(argv[0], exePath);
if (NS_FAILED(rv)) {
@@ -212,34 +237,24 @@ int main(int argc, char* argv[])
int gotCounters;
#if defined(XP_UNIX)
struct rusage initialRUsage;
gotCounters = !getrusage(RUSAGE_SELF, &initialRUsage);
#elif defined(XP_WIN)
// Don't change the order of these enumeration constants, the order matters
// for reporting telemetry data. If new values are added adjust the
// STARTUP_USING_PRELOAD histogram.
- enum PreloadReason { PRELOAD_NONE, PRELOAD_SERVICE, PRELOAD_IOCOUNT };
+ enum PreloadReason { PRELOAD_NONE, PRELOAD_SERVICE };
PreloadReason preloadReason = PRELOAD_NONE;
- // GetProcessIoCounters().ReadOperationCount seems to have little to
- // do with actual read operations. It reports 0 or 1 at this stage
- // in the program. Luckily 1 coincides with when prefetch is
- // enabled. If Windows prefetch didn't happen we can do our own
- // faster dll preloading.
- // The MozillaMaintenance service issues a command to disable the
- // prefetch by replacing all found .pf files with 0 byte read only
- // files.
IO_COUNTERS ioCounters;
gotCounters = GetProcessIoCounters(GetCurrentProcess(), &ioCounters);
if (IsPrefetchDisabledViaService()) {
preloadReason = PRELOAD_SERVICE;
- } else if ((gotCounters && !ioCounters.ReadOperationCount)) {
- preloadReason = PRELOAD_IOCOUNT;
}
if (preloadReason != PRELOAD_NONE)
#endif
{
XPCOMGlueEnablePreload();
}
@@ -252,16 +267,18 @@ int main(int argc, char* argv[])
*lastSlash = 0;
rv = XPCOMGlueLoadXULFunctions(kXULFuncs);
if (NS_FAILED(rv)) {
Output("Couldn't load XRE functions.\n");
return 255;
}
+ XRE_StartupTimelineRecord(mozilla::StartupTimeline::START, start);
+
#ifdef XRE_HAS_DLL_BLOCKLIST
XRE_SetupDllBlocklist();
#endif
#if defined(XP_WIN)
XRE_TelemetryAccumulate(mozilla::Telemetry::STARTUP_USING_PRELOAD,
preloadReason);
#endif
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -2153,17 +2153,17 @@ private:
static nsString* sModifierSeparator;
};
typedef nsCharSeparatedTokenizerTemplate<nsContentUtils::IsHTMLWhitespace>
HTMLSplitOnSpacesTokenizer;
#define NS_HOLD_JS_OBJECTS(obj, clazz) \
nsContentUtils::HoldJSObjects(NS_CYCLE_COLLECTION_UPCAST(obj, clazz), \
- &NS_CYCLE_COLLECTION_NAME(clazz))
+ NS_CYCLE_COLLECTION_PARTICIPANT(clazz))
#define NS_DROP_JS_OBJECTS(obj, clazz) \
nsContentUtils::DropJSObjects(NS_CYCLE_COLLECTION_UPCAST(obj, clazz))
class NS_STACK_CLASS nsCxPusher
{
public:
--- a/content/base/src/nsNodeInfoManager.cpp
+++ b/content/base/src/nsNodeInfoManager.cpp
@@ -125,17 +125,17 @@ nsNodeInfoManager::~nsNodeInfoManager()
PR_LOG(gNodeInfoManagerLeakPRLog, PR_LOG_DEBUG,
("NODEINFOMANAGER %p destroyed", this));
#endif
nsLayoutStatics::Release();
}
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsNodeInfoManager)
+NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsNodeInfoManager)
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsNodeInfoManager, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsNodeInfoManager, Release)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NATIVE_0(nsNodeInfoManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(nsNodeInfoManager)
if (tmp->mDocument &&
nsCCUncollectableMarker::InGeneration(cb,
tmp->mDocument->GetMarkedCCGeneration())) {
return NS_SUCCESS_INTERRUPTED_TRAVERSE;
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -140,17 +140,17 @@ nsEventListenerManager::RemoveAllListene
}
void
nsEventListenerManager::Shutdown()
{
nsDOMEvent::Shutdown();
}
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsEventListenerManager)
+NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsEventListenerManager)
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsEventListenerManager, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsEventListenerManager, Release)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(nsEventListenerManager)
PRUint32 count = tmp->mListeners.Length();
for (PRUint32 i = 0; i < count; i++) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mListeners[i] mListener");
--- a/content/xbl/src/nsXBLBinding.cpp
+++ b/content/xbl/src/nsXBLBinding.cpp
@@ -252,17 +252,17 @@ TraverseKey(nsISupports* aKey, nsInserti
cb.NoteXPCOMChild(aKey);
if (aData) {
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY(*aData, nsXBLInsertionPoint,
"mInsertionPointTable value")
}
return PL_DHASH_NEXT;
}
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLBinding)
+NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsXBLBinding)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXBLBinding)
// XXX Probably can't unlink mPrototypeBinding->XBLDocumentInfo(), because
// mPrototypeBinding is weak.
if (tmp->mContent) {
nsXBLBinding::UninstallAnonymousContent(tmp->mContent->OwnerDoc(),
tmp->mContent);
}
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContent)
--- a/content/xbl/src/nsXBLInsertionPoint.cpp
+++ b/content/xbl/src/nsXBLInsertionPoint.cpp
@@ -19,17 +19,17 @@ nsXBLInsertionPoint::nsXBLInsertionPoint
nsXBLInsertionPoint::~nsXBLInsertionPoint()
{
if (mDefaultContent) {
nsXBLBinding::UninstallAnonymousContent(mDefaultContent->OwnerDoc(),
mDefaultContent);
}
}
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLInsertionPoint)
+NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsXBLInsertionPoint)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXBLInsertionPoint)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mElements)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDefaultContentTemplate)
if (tmp->mDefaultContent) {
nsXBLBinding::UninstallAnonymousContent(tmp->mDefaultContent->OwnerDoc(),
tmp->mDefaultContent);
}
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDefaultContent)
--- a/content/xbl/src/nsXBLPrototypeBinding.cpp
+++ b/content/xbl/src/nsXBLPrototypeBinding.cpp
@@ -222,17 +222,17 @@ private:
static nsFixedSizeAllocator* kPool;
static PRUint32 gRefCnt;
};
PRUint32 nsXBLInsertionPointEntry::gRefCnt = 0;
nsFixedSizeAllocator* nsXBLInsertionPointEntry::kPool;
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLInsertionPointEntry)
+NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsXBLInsertionPointEntry)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXBLInsertionPointEntry)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mInsertionParent)
if (tmp->mDefaultContent) {
nsAutoScriptBlocker scriptBlocker;
// mDefaultContent is a sort of anonymous content within the XBL
// document, and we own and manage it. Unhook it here, since we're going
// away.
tmp->mDefaultContent->UnbindFromTree();
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -750,17 +750,17 @@ nsScriptEventHandlerOwnerTearoff::Compil
if (attr) {
XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheFills);
// take a copy of the event handler, and tell the language about it.
if (aHandler) {
NS_ASSERTION(!attr->mEventHandler, "Leaking handler.");
if (!elem->mHoldsScriptObject) {
rv = nsContentUtils::HoldJSObjects(
- elem, &NS_CYCLE_COLLECTION_NAME(nsXULPrototypeNode));
+ elem, NS_CYCLE_COLLECTION_PARTICIPANT(nsXULPrototypeNode));
NS_ENSURE_SUCCESS(rv, rv);
}
elem->mHoldsScriptObject = true;
}
attr->mEventHandler = aHandler.get();
}
@@ -3093,17 +3093,17 @@ nsXULPrototypeScript::Set(JSScript* aObj
{
NS_ASSERTION(!mScriptObject.mObject, "Leaking script object.");
if (!aObject) {
mScriptObject.mObject = nsnull;
return;
}
nsresult rv = nsContentUtils::HoldJSObjects(
- this, &NS_CYCLE_COLLECTION_NAME(nsXULPrototypeNode));
+ this, NS_CYCLE_COLLECTION_PARTICIPANT(nsXULPrototypeNode));
if (NS_SUCCEEDED(rv)) {
mScriptObject.mObject = aObject;
}
}
//----------------------------------------------------------------------
//
// nsXULPrototypeText
--- a/content/xul/templates/src/nsXMLBinding.cpp
+++ b/content/xul/templates/src/nsXMLBinding.cpp
@@ -5,17 +5,17 @@
#include "nsXULTemplateQueryProcessorXML.h"
#include "nsXULTemplateResultXML.h"
#include "nsXMLBinding.h"
NS_IMPL_ADDREF(nsXMLBindingSet)
NS_IMPL_RELEASE(nsXMLBindingSet)
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsXMLBindingSet)
+NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsXMLBindingSet)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXMLBindingSet)
nsXMLBinding* binding = tmp->mFirst;
while (binding) {
binding->mExpr = nsnull;
binding = binding->mNext;
}
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
--- a/content/xul/templates/src/nsXULTemplateQueryProcessorXML.cpp
+++ b/content/xul/templates/src/nsXULTemplateQueryProcessorXML.cpp
@@ -80,17 +80,17 @@ nsXULTemplateResultSetXML::GetNext(nsISu
static PLDHashOperator
TraverseRuleToBindingsMap(nsISupports* aKey, nsXMLBindingSet* aMatch, void* aContext)
{
nsCycleCollectionTraversalCallback *cb =
static_cast<nsCycleCollectionTraversalCallback*>(aContext);
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mRuleToBindingsMap key");
cb->NoteXPCOMChild(aKey);
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mRuleToBindingsMap value");
- cb->NoteNativeChild(aMatch, &NS_CYCLE_COLLECTION_NAME(nsXMLBindingSet));
+ cb->NoteNativeChild(aMatch, NS_CYCLE_COLLECTION_PARTICIPANT(nsXMLBindingSet));
return PL_DHASH_NEXT;
}
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULTemplateQueryProcessorXML)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXULTemplateQueryProcessorXML)
if (tmp->mRuleToBindingsMap.IsInitialized()) {
tmp->mRuleToBindingsMap.Clear();
}
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -534,17 +534,17 @@ nsTimeout::~nsTimeout()
--gTimeoutCnt;
}
#endif
MOZ_COUNT_DTOR(nsTimeout);
}
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsTimeout)
+NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsTimeout)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NATIVE_0(nsTimeout)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(nsTimeout)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mWindow,
nsIScriptGlobalObject)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPrincipal)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mScriptHandler)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsTimeout, AddRef)
@@ -1221,17 +1221,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOpenerScriptPrincipal)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mListenerManager,
nsEventListenerManager)
for (nsTimeout* timeout = tmp->FirstTimeout();
tmp->IsTimeout(timeout);
timeout = timeout->Next()) {
- cb.NoteNativeChild(timeout, &NS_CYCLE_COLLECTION_NAME(nsTimeout));
+ cb.NoteNativeChild(timeout, NS_CYCLE_COLLECTION_PARTICIPANT(nsTimeout));
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLocalStorage)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mSessionStorage)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mApplicationCache)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocumentPrincipal)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDoc)
--- a/editor/txmgr/src/nsTransactionItem.cpp
+++ b/editor/txmgr/src/nsTransactionItem.cpp
@@ -38,17 +38,17 @@ nsTransactionItem::Release() {
if (mRefCnt == 0) {
mRefCnt = 1;
delete this;
return 0;
}
return mRefCnt;
}
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsTransactionItem)
+NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsTransactionItem)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsTransactionItem)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTransaction)
if (tmp->mRedoStack) {
tmp->mRedoStack->DoUnlink();
}
if (tmp->mUndoStack) {
tmp->mUndoStack->DoUnlink();
--- a/editor/txmgr/src/nsTransactionStack.cpp
+++ b/editor/txmgr/src/nsTransactionStack.cpp
@@ -90,12 +90,12 @@ nsTransactionStack::Clear()
void
nsTransactionStack::DoTraverse(nsCycleCollectionTraversalCallback &cb)
{
for (PRInt32 i = 0, qcount = mQue.GetSize(); i < qcount; ++i) {
nsTransactionItem *item =
static_cast<nsTransactionItem*>(mQue.ObjectAt(i));
if (item) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "transaction stack mQue[i]");
- cb.NoteNativeChild(item, &NS_CYCLE_COLLECTION_NAME(nsTransactionItem));
+ cb.NoteNativeChild(item, NS_CYCLE_COLLECTION_PARTICIPANT(nsTransactionItem));
}
}
}
--- a/js/xpconnect/src/XPCWrappedJS.cpp
+++ b/js/xpconnect/src/XPCWrappedJS.cpp
@@ -12,18 +12,19 @@
#include "nsThreadUtils.h"
#include "nsTextFormatter.h"
// NOTE: much of the fancy footwork is done in xpcstubs.cpp
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXPCWrappedJS)
NS_IMETHODIMP
-NS_CYCLE_COLLECTION_CLASSNAME(nsXPCWrappedJS)::Traverse
- (void *p, nsCycleCollectionTraversalCallback &cb)
+NS_CYCLE_COLLECTION_CLASSNAME(nsXPCWrappedJS)::TraverseImpl
+ (NS_CYCLE_COLLECTION_CLASSNAME(nsXPCWrappedJS) *that, void *p,
+ nsCycleCollectionTraversalCallback &cb)
{
nsISupports *s = static_cast<nsISupports*>(p);
NS_ASSERTION(CheckForRightISupports(s),
"not the nsISupports pointer we expect");
nsXPCWrappedJS *tmp = Downcast(s);
nsrefcnt refcnt = tmp->mRefCnt.get();
if (cb.WantDebugInfo()) {
@@ -93,17 +94,17 @@ NS_IMETHODIMP
nsXPCWrappedJS::QueryInterface(REFNSIID aIID, void** aInstancePtr)
{
if (nsnull == aInstancePtr) {
NS_PRECONDITION(0, "null pointer");
return NS_ERROR_NULL_POINTER;
}
if ( aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant)) ) {
- *aInstancePtr = & NS_CYCLE_COLLECTION_NAME(nsXPCWrappedJS);
+ *aInstancePtr = NS_CYCLE_COLLECTION_PARTICIPANT(nsXPCWrappedJS);
return NS_OK;
}
if (aIID.Equals(NS_GET_IID(nsCycleCollectionISupports))) {
*aInstancePtr =
NS_CYCLE_COLLECTION_CLASSNAME(nsXPCWrappedJS)::Upcast(this);
return NS_OK;
}
--- a/js/xpconnect/src/XPCWrappedNative.cpp
+++ b/js/xpconnect/src/XPCWrappedNative.cpp
@@ -39,26 +39,27 @@ xpc_OkToHandOutWrapper(nsWrapperCache *c
NeedsSOW();
}
/***************************************************************************/
NS_IMPL_CYCLE_COLLECTION_CLASS(XPCWrappedNative)
NS_IMETHODIMP
-NS_CYCLE_COLLECTION_CLASSNAME(XPCWrappedNative)::Unlink(void *p)
+NS_CYCLE_COLLECTION_CLASSNAME(XPCWrappedNative)::UnlinkImpl(void *p)
{
XPCWrappedNative *tmp = static_cast<XPCWrappedNative*>(p);
tmp->ExpireWrapper();
return NS_OK;
}
NS_IMETHODIMP
-NS_CYCLE_COLLECTION_CLASSNAME(XPCWrappedNative)::Traverse(void *p,
- nsCycleCollectionTraversalCallback &cb)
+NS_CYCLE_COLLECTION_CLASSNAME(XPCWrappedNative)::TraverseImpl
+ (NS_CYCLE_COLLECTION_CLASSNAME(XPCWrappedNative) *that, void *p,
+ nsCycleCollectionTraversalCallback &cb)
{
XPCWrappedNative *tmp = static_cast<XPCWrappedNative*>(p);
if (!tmp->IsValid())
return NS_OK;
if (NS_UNLIKELY(cb.WantDebugInfo())) {
char name[72];
XPCNativeScriptableInfo* si = tmp->GetScriptableInfo();
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -538,38 +538,43 @@ nsXPConnect::NotifyEnterMainThread()
nsresult
nsXPConnect::FinishTraverse()
{
if (mCycleCollectionContext)
mCycleCollectionContext = nsnull;
return NS_OK;
}
+class nsXPConnectParticipant: public nsCycleCollectionParticipant
+{
+public:
+ static NS_METHOD RootImpl(void *n)
+ {
+ return NS_OK;
+ }
+ static NS_METHOD UnlinkImpl(void *n)
+ {
+ return NS_OK;
+ }
+ static NS_METHOD UnrootImpl(void *n)
+ {
+ return NS_OK;
+ }
+ static NS_METHOD TraverseImpl(nsXPConnectParticipant *that, void *n,
+ nsCycleCollectionTraversalCallback &cb);
+};
+
+static CCParticipantVTable<nsXPConnectParticipant>::Type XPConnect_cycleCollectorGlobal = {
+ NS_IMPL_CYCLE_COLLECTION_NATIVE_VTABLE(nsXPConnectParticipant)
+};
+
nsCycleCollectionParticipant *
nsXPConnect::GetParticipant()
{
- return this;
-}
-
-NS_IMETHODIMP
-nsXPConnect::Root(void *p)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXPConnect::Unlink(void *p)
-{
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsXPConnect::Unroot(void *p)
-{
- return NS_OK;
+ return XPConnect_cycleCollectorGlobal.GetParticipant();
}
JSBool
xpc_GCThingIsGrayCCThing(void *thing)
{
return AddToCCKind(js_GetGCThingTraceKind(thing)) &&
xpc_IsGrayGCThing(thing);
}
@@ -751,18 +756,19 @@ WrapperIsNotMainThreadOnly(XPCWrappedNat
// If the native participates in cycle collection then we know it can only
// be used on the main thread, in that case we assume the wrapped native
// can only be used on the main thread too.
nsXPCOMCycleCollectionParticipant* participant;
return NS_FAILED(CallQueryInterface(wrapper->Native(), &participant));
}
-NS_IMETHODIMP
-nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
+NS_METHOD
+nsXPConnectParticipant::TraverseImpl(nsXPConnectParticipant *that, void *p,
+ nsCycleCollectionTraversalCallback &cb)
{
JSGCTraceKind traceKind = js_GetGCThingTraceKind(p);
JSObject *obj = nsnull;
js::Class *clazz = nsnull;
// We do not want to add wrappers to the cycle collector if they're not
// explicitly marked as main thread only, because the cycle collector isn't
// able to deal with objects that might be used off of the main thread. We
@@ -838,17 +844,17 @@ nsXPConnect::Traverse(void *p, nsCycleCo
// GC. Any JS objects hanging from them will already be marked. Only do this
// if cb.WantAllTraces() is false, otherwise we do want to know about all JS
// objects to get better graphs and explanations.
if (!cb.WantAllTraces() && isMarked)
return NS_OK;
TraversalTracer trc(cb);
- JS_TracerInit(&trc, GetRuntime()->GetJSRuntime(), NoteJSChild);
+ JS_TracerInit(&trc, nsXPConnect::GetRuntimeInstance()->GetJSRuntime(), NoteJSChild);
trc.eagerlyTraceWeakMaps = false;
JS_TraceChildren(&trc, p, traceKind);
if (traceKind != JSTRACE_OBJECT || dontTraverse)
return NS_OK;
if (clazz == &XPC_WN_Tearoff_JSClass) {
// A tearoff holds a strong reference to its native object
@@ -892,33 +898,34 @@ nsXPConnect::GetOutstandingRequests(JSCo
--n;
}
return n;
}
class JSContextParticipant : public nsCycleCollectionParticipant
{
public:
- NS_IMETHOD Root(void *n)
+ static NS_METHOD RootImpl(void *n)
{
return NS_OK;
}
- NS_IMETHOD Unlink(void *n)
+ static NS_METHOD UnlinkImpl(void *n)
{
JSContext *cx = static_cast<JSContext*>(n);
JSAutoRequest ar(cx);
NS_ASSERTION(JS_GetGlobalObject(cx), "global object NULL before unlinking");
JS_SetGlobalObject(cx, NULL);
return NS_OK;
}
- NS_IMETHOD Unroot(void *n)
+ static NS_METHOD UnrootImpl(void *n)
{
return NS_OK;
}
- NS_IMETHODIMP Traverse(void *n, nsCycleCollectionTraversalCallback &cb)
+ static NS_METHOD TraverseImpl(JSContextParticipant *that, void *n,
+ nsCycleCollectionTraversalCallback &cb)
{
JSContext *cx = static_cast<JSContext*>(n);
// Add outstandingRequests to the count, if there are outstanding
// requests the context needs to be kept alive and adding unknown
// edges will ensure that any cycles this context is in won't be
// collected.
unsigned refCount = nsXPConnect::GetXPConnect()->GetOutstandingRequests(cx) + 1;
@@ -927,30 +934,32 @@ public:
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "[global object]");
cb.NoteJSChild(global);
}
return NS_OK;
}
};
-static JSContextParticipant JSContext_cycleCollectorGlobal;
+static CCParticipantVTable<JSContextParticipant>::Type JSContext_cycleCollectorGlobal = {
+ NS_IMPL_CYCLE_COLLECTION_NATIVE_VTABLE(JSContextParticipant)
+};
// static
nsCycleCollectionParticipant*
nsXPConnect::JSContextParticipant()
{
- return &JSContext_cycleCollectorGlobal;
+ return JSContext_cycleCollectorGlobal.GetParticipant();
}
NS_IMETHODIMP_(void)
nsXPConnect::NoteJSContext(JSContext *aJSContext,
nsCycleCollectionTraversalCallback &aCb)
{
- aCb.NoteNativeChild(aJSContext, &JSContext_cycleCollectorGlobal);
+ aCb.NoteNativeChild(aJSContext, JSContext_cycleCollectorGlobal.GetParticipant());
}
/***************************************************************************/
/***************************************************************************/
// nsIXPConnect interface methods...
inline nsresult UnexpectedFailure(nsresult rv)
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -473,17 +473,16 @@ AddToCCKind(JSGCTraceKind kind)
{
return kind == JSTRACE_OBJECT || kind == JSTRACE_XML || kind == JSTRACE_SCRIPT;
}
class nsXPConnect : public nsIXPConnect,
public nsIThreadObserver,
public nsSupportsWeakReference,
public nsCycleCollectionJSRuntime,
- public nsCycleCollectionParticipant,
public nsIJSRuntimeService,
public nsIThreadJSContextStack,
public nsIJSEngineTelemetryStats
{
public:
// all the interface method declarations...
NS_DECL_ISUPPORTS
NS_DECL_NSIXPCONNECT
@@ -534,23 +533,16 @@ public:
JSBool IsShuttingDown() const {return mShuttingDown;}
void EnsureGCBeforeCC() { mNeedGCBeforeCC = true; }
void ClearGCBeforeCC() { mNeedGCBeforeCC = false; }
nsresult GetInfoForIID(const nsIID * aIID, nsIInterfaceInfo** info);
nsresult GetInfoForName(const char * name, nsIInterfaceInfo** info);
- // nsCycleCollectionParticipant
- NS_IMETHOD Root(void *p);
- NS_IMETHOD Unlink(void *p);
- NS_IMETHOD Unroot(void *p);
- NS_IMETHOD Traverse(void *p,
- nsCycleCollectionTraversalCallback &cb);
-
// nsCycleCollectionLanguageRuntime
virtual bool NotifyLeaveMainThread();
virtual void NotifyEnterCycleCollectionThread();
virtual void NotifyLeaveCycleCollectionThread();
virtual void NotifyEnterMainThread();
virtual nsresult BeginCycleCollection(nsCycleCollectionTraversalCallback &cb);
virtual nsresult FinishTraverse();
virtual nsCycleCollectionParticipant *GetParticipant();
@@ -2550,19 +2542,19 @@ public:
// root/unrooting the JS objects from addrefing/releasing the
// XPCWrappedNative during unlinking, which would make the JS objects
// uncollectable to the JS GC.
class NS_CYCLE_COLLECTION_INNERCLASS
: public nsXPCOMCycleCollectionParticipant
{
NS_DECL_CYCLE_COLLECTION_CLASS_BODY_NO_UNLINK(XPCWrappedNative,
XPCWrappedNative)
- NS_IMETHOD Root(void *p) { return NS_OK; }
- NS_IMETHOD Unlink(void *p);
- NS_IMETHOD Unroot(void *p) { return NS_OK; }
+ static NS_METHOD RootImpl(void *p) { return NS_OK; }
+ static NS_METHOD UnlinkImpl(void *p);
+ static NS_METHOD UnrootImpl(void *p) { return NS_OK; }
};
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
NS_DECL_CYCLE_COLLECTION_UNMARK_PURPLE_STUB(XPCWrappedNative)
nsIPrincipal* GetObjectPrincipal() const;
JSBool
IsValid() const {return nsnull != mFlatJSObject;}
new file mode 100644
--- /dev/null
+++ b/mfbt/TypeTraits.h
@@ -0,0 +1,54 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_TypeTraits_h_
+#define mozilla_TypeTraits_h_
+
+/* Template-based metaprogramming and type-testing facilities. */
+
+namespace mozilla {
+
+/*
+ * IsBaseOf allows to know whether a given class is derived from another.
+ *
+ * Consider the following class definitions:
+ *
+ * class A {};
+ * class B : public A {};
+ * class C {};
+ *
+ * mozilla::IsBaseOf<A, B>::value is true;
+ * mozilla::IsBaseOf<A, C>::value is false;
+ */
+template <class Base, class Derived>
+class IsBaseOf
+{
+ private:
+ static char Test(Base *);
+ static int Test(...);
+ public:
+ static const bool value = (sizeof(Test(static_cast<Derived *>(0))) == sizeof(char));
+};
+
+/*
+ * Conditional selects a class between two, depending on a given boolean value.
+ *
+ * mozilla::Conditional<true, A, B>::Type is A;
+ * mozilla::Conditional<false, A, B>::Type is B;
+ */
+template <bool condition, class A, class B>
+struct Conditional
+{
+ typedef A Type;
+};
+
+template <class A, class B>
+struct Conditional<false, A, B>
+{
+ typedef B Type;
+};
+
+} /* namespace mozilla */
+
+#endif /* mozilla_TypeTraits_h_ */
--- a/mfbt/exported_headers.mk
+++ b/mfbt/exported_headers.mk
@@ -19,11 +19,12 @@ EXPORTS_mozilla += \
Likely.h \
LinkedList.h \
MSStdInt.h \
RangedPtr.h \
RefPtr.h \
Scoped.h \
StandardInteger.h \
ThreadLocal.h \
+ TypeTraits.h \
Types.h \
Util.h \
$(NULL)
--- a/testing/marionette/client/marionette/runtests.py
+++ b/testing/marionette/client/marionette/runtests.py
@@ -229,27 +229,35 @@ class MarionetteTestRunner(object):
noWindow=self.noWindow,
logcat_dir=self.logcat_dir)
else:
raise Exception("must specify binary, address or emulator")
def post_to_autolog(self, elapsedtime):
self.logger.info('posting results to autolog')
+ logfile = None
+ if self.emulator:
+ filename = os.path.join(os.path.abspath(self.logcat_dir),
+ "emulator-%d.log" % self.marionette.emulator.port)
+ if os.access(filename, os.F_OK):
+ logfile = filename
+
# This is all autolog stuff.
# See: https://wiki.mozilla.org/Auto-tools/Projects/Autolog
from mozautolog import RESTfulAutologTestGroup
testgroup = RESTfulAutologTestGroup(
testgroup = self.testgroup,
os = 'android',
platform = 'emulator',
harness = 'marionette',
server = self.es_server,
restserver = self.rest_server,
- machine = socket.gethostname())
+ machine = socket.gethostname(),
+ logfile = logfile)
testgroup.set_primary_product(
tree = 'b2g',
buildtype = 'opt',
revision = self.revision)
testgroup.add_test_suite(
testsuite = 'b2g emulator testsuite',
--- a/toolkit/components/startup/StartupTimeline.cpp
+++ b/toolkit/components/startup/StartupTimeline.cpp
@@ -1,16 +1,28 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "StartupTimeline.h"
+#include "nsXULAppAPI.h"
namespace mozilla {
PRTime StartupTimeline::sStartupTimeline[StartupTimeline::MAX_EVENT_ID];
const char *StartupTimeline::sStartupTimelineDesc[StartupTimeline::MAX_EVENT_ID] = {
#define mozilla_StartupTimeline_Event(ev, desc) desc,
#include "StartupTimeline.h"
#undef mozilla_StartupTimeline_Event
};
+} /* namespace mozilla */
+
+/**
+ * The XRE_StartupTimeline_Record function is to be used by embedding applications
+ * that can't use mozilla::StartupTimeline::Record() directly.
+ */
+void
+XRE_StartupTimelineRecord(int aEvent, PRTime aWhen)
+{
+ mozilla::StartupTimeline::Record((mozilla::StartupTimeline::Event) aEvent, aWhen);
}
+
--- a/toolkit/components/startup/StartupTimeline.h
+++ b/toolkit/components/startup/StartupTimeline.h
@@ -1,14 +1,15 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifdef mozilla_StartupTimeline_Event
mozilla_StartupTimeline_Event(PROCESS_CREATION, "process")
+mozilla_StartupTimeline_Event(START, "start")
mozilla_StartupTimeline_Event(MAIN, "main")
// Record the beginning and end of startup crash detection to compare with crash stats to know whether
// detection should be improved to start or end sooner.
mozilla_StartupTimeline_Event(STARTUP_CRASH_DETECTION_BEGIN, "startupCrashDetectionBegin")
mozilla_StartupTimeline_Event(STARTUP_CRASH_DETECTION_END, "startupCrashDetectionEnd")
mozilla_StartupTimeline_Event(FIRST_PAINT, "firstPaint")
mozilla_StartupTimeline_Event(SESSION_RESTORED, "sessionRestored")
mozilla_StartupTimeline_Event(CREATE_TOP_LEVEL_WINDOW, "createTopLevelWindow")
--- a/xpcom/base/nsAgg.h
+++ b/xpcom/base/nsAgg.h
@@ -67,20 +67,21 @@ private:
\
public: \
#define NS_DECL_AGGREGATED_CYCLE_COLLECTION_CLASS(_class) \
class NS_CYCLE_COLLECTION_INNERCLASS \
: public nsXPCOMCycleCollectionParticipant \
{ \
public: \
- NS_IMETHOD Unlink(void *p); \
- NS_IMETHOD Traverse(void *p, \
- nsCycleCollectionTraversalCallback &cb); \
- NS_IMETHOD_(void) UnmarkIfPurple(nsISupports *p) \
+ static NS_METHOD UnlinkImpl(void *p); \
+ static NS_METHOD TraverseImpl(NS_CYCLE_COLLECTION_INNERCLASS *that, \
+ void *p, \
+ nsCycleCollectionTraversalCallback &cb); \
+ static NS_METHOD_(void) UnmarkIfPurpleImpl(nsISupports *p) \
{ \
Downcast(p)->UnmarkIfPurple(); \
} \
static _class* Downcast(nsISupports* s) \
{ \
return (_class*)((char*)(s) - offsetof(_class, fAggregated)); \
} \
static nsISupports* Upcast(_class *p) \
@@ -258,24 +259,24 @@ nsresult
if ( aIID.Equals(NS_GET_IID(nsISupports)) ) \
foundInterface = InnerObject(); \
else
#define NS_IMPL_AGGREGATED_QUERY_CYCLE_COLLECTION(_class) \
if (aIID.Equals(IsPartOfAggregated() ? \
NS_GET_IID(nsCycleCollectionParticipant) : \
NS_GET_IID(nsAggregatedCycleCollectionParticipant))) \
- foundInterface = & NS_CYCLE_COLLECTION_NAME(_class); \
+ foundInterface = NS_CYCLE_COLLECTION_PARTICIPANT(_class); \
else
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_AGGREGATED(_class) \
- NS_IMETHODIMP \
- NS_CYCLE_COLLECTION_CLASSNAME(_class)::Traverse \
- (void *p, \
- nsCycleCollectionTraversalCallback &cb) \
+ NS_METHOD \
+ NS_CYCLE_COLLECTION_CLASSNAME(_class)::TraverseImpl \
+ (NS_CYCLE_COLLECTION_CLASSNAME(_class) *that, \
+ void *p, nsCycleCollectionTraversalCallback &cb) \
{ \
nsISupports *s = static_cast<nsISupports*>(p); \
NS_ASSERTION(CheckForRightISupports(s), \
"not the nsISupports pointer we expect"); \
_class *tmp = static_cast<_class*>(Downcast(s)); \
if (!tmp->IsPartOfAggregated()) \
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class, tmp->mRefCnt.get())
--- a/xpcom/build/nsXULAppAPI.h
+++ b/xpcom/build/nsXULAppAPI.h
@@ -435,16 +435,19 @@ XRE_API(void,
XRE_API(void,
XRE_SetupDllBlocklist, ())
#endif
XRE_API(void,
XRE_TelemetryAccumulate, (int aID, PRUint32 aSample))
XRE_API(void,
+ XRE_StartupTimelineRecord, (int aEvent, PRTime aWhen))
+
+XRE_API(void,
XRE_InitOmnijar, (nsIFile* greOmni,
nsIFile* appOmni))
#ifdef XP_WIN
/**
* Valid environment types for XRE_GetWindowsEnvironment.
*/
enum WindowsEnvironmentType {
--- a/xpcom/glue/nsCycleCollectionParticipant.cpp
+++ b/xpcom/glue/nsCycleCollectionParticipant.cpp
@@ -1,69 +1,64 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsCycleCollectionParticipant.h"
#include "nsCOMPtr.h"
-static void
-NoteChild(void *aScriptThing, const char *name, void *aClosure)
+void
+nsScriptObjectTracer::NoteJSChild(void *aScriptThing, const char *name,
+ void *aClosure)
{
nsCycleCollectionTraversalCallback *cb =
static_cast<nsCycleCollectionTraversalCallback*>(aClosure);
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, name);
cb->NoteJSChild(aScriptThing);
}
-void
-nsScriptObjectTracer::TraverseScriptObjects(void *p,
- nsCycleCollectionTraversalCallback &cb)
-{
- Trace(p, NoteChild, &cb);
-}
-
nsresult
-nsXPCOMCycleCollectionParticipant::Root(void *p)
+nsXPCOMCycleCollectionParticipant::RootImpl(void *p)
{
nsISupports *s = static_cast<nsISupports*>(p);
NS_ADDREF(s);
return NS_OK;
}
nsresult
-nsXPCOMCycleCollectionParticipant::Unlink(void *p)
+nsXPCOMCycleCollectionParticipant::UnlinkImpl(void *p)
{
return NS_OK;
}
nsresult
-nsXPCOMCycleCollectionParticipant::Unroot(void *p)
+nsXPCOMCycleCollectionParticipant::UnrootImpl(void *p)
{
nsISupports *s = static_cast<nsISupports*>(p);
NS_RELEASE(s);
return NS_OK;
}
nsresult
-nsXPCOMCycleCollectionParticipant::Traverse
- (void *p, nsCycleCollectionTraversalCallback &cb)
+nsXPCOMCycleCollectionParticipant::TraverseImpl
+ (nsXPCOMCycleCollectionParticipant* that, void *p,
+ nsCycleCollectionTraversalCallback &cb)
{
return NS_OK;
}
void
-nsXPCOMCycleCollectionParticipant::UnmarkIfPurple(nsISupports *n)
+nsXPCOMCycleCollectionParticipant::UnmarkIfPurpleImpl(nsISupports *n)
{
}
NS_IMETHODIMP_(void)
-nsXPCOMCycleCollectionParticipant::Trace(void *p, TraceCallback cb,
- void *closure)
+nsXPCOMCycleCollectionParticipant::TraceImpl(void *p, TraceCallback cb,
+ void *closure)
{
}
bool
nsXPCOMCycleCollectionParticipant::CheckForRightISupports(nsISupports *s)
{
nsISupports* foo;
s->QueryInterface(NS_GET_IID(nsCycleCollectionISupports),
--- a/xpcom/glue/nsCycleCollectionParticipant.h
+++ b/xpcom/glue/nsCycleCollectionParticipant.h
@@ -1,16 +1,17 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsCycleCollectionParticipant_h__
#define nsCycleCollectionParticipant_h__
+#include "mozilla/TypeTraits.h"
#include "nsISupports.h"
#define NS_CYCLECOLLECTIONPARTICIPANT_IID \
{ \
0x9674489b, \
0x1f6f, \
0x4550, \
{ 0xa7, 0x30, 0xcc, 0xae, 0xdd, 0x10, 0x4c, 0xf9 } \
@@ -38,17 +39,28 @@ class nsCycleCollectionISupports
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_CYCLECOLLECTIONISUPPORTS_IID)
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsCycleCollectionISupports,
NS_CYCLECOLLECTIONISUPPORTS_IID)
+/**
+ * Forward declarations
+ */
class nsCycleCollectionParticipant;
+class nsScriptObjectTracer;
+class nsXPCOMCycleCollectionParticipant;
+
+/**
+ * Callback definitions
+ */
+typedef void
+(* TraceCallback)(void *p, const char *name, void *closure);
class NS_NO_VTABLE nsCycleCollectionTraversalCallback
{
public:
// You must call DescribeRefCountedNode() with an accurate
// refcount, otherwise cycle collection will fail, and probably crash.
// If the callback cares about objsz or objname, it should
// put WANT_DEBUG_INFO in mFlags.
@@ -92,138 +104,239 @@ public:
bool WantDebugInfo() const { return (mFlags & WANT_DEBUG_INFO) != 0; }
bool WantAllTraces() const { return (mFlags & WANT_ALL_TRACES) != 0; }
protected:
nsCycleCollectionTraversalCallback() : mFlags(0) {}
PRUint32 mFlags;
};
-class NS_NO_VTABLE nsCycleCollectionParticipant
+/**
+ * VTables
+ *
+ * When using global scope static initialization for simple types with virtual
+ * member functions, GCC creates static initializer functions. In order to
+ * avoid this from happening, cycle collection participants are defined as
+ * function tables.
+ *
+ * The Traverse function may require calling another function from the cycle
+ * collection participant function table, so a pointer to the function table
+ * is given to it. Using member function pointers would be less awkward, but
+ * in MSVC, the size of such a member function pointer depends on the class
+ * the function is member of. This makes it hard to make them compatible with
+ * a generic function table. Moreover, static initialization of the function
+ * table then uses a static initializer function.
+ *
+ * Finally, it is not possible to use an initializer list for non-aggregate
+ * types. Separate types are thus required for static initialization. For
+ * convenience and to avoid repetitions that could lead to discrepancies,
+ * function table members for sub-types are declared independently, and
+ * different aggregate types are defined for static initialization.
+ */
+
+/* Base functions for nsCycleCollectionParticipant */
+template <typename T>
+struct nsCycleCollectionParticipantVTableCommon
+{
+ nsresult (NS_STDCALL *TraverseReal)
+ (T *that, void *p, nsCycleCollectionTraversalCallback &cb);
+
+ nsresult (NS_STDCALL *Root)(void *p);
+ nsresult (NS_STDCALL *Unlink)(void *p);
+ nsresult (NS_STDCALL *Unroot)(void *p);
+
+ bool (NS_STDCALL *CanSkipReal)(void *p, bool aRemovingAllowed);
+ bool (NS_STDCALL *CanSkipInCCReal)(void *p);
+ bool (NS_STDCALL *CanSkipThisReal)(void *p);
+};
+
+typedef nsCycleCollectionParticipantVTableCommon<nsCycleCollectionParticipant>
+ nsCycleCollectionParticipantVTable;
+
+/* Additional functions for nsScriptObjectTracer */
+struct nsScriptObjectTracerVTable
+{
+ void (NS_STDCALL *Trace)(void *p, TraceCallback cb, void *closure);
+};
+
+/* Additional functions for nsXPCOMCycleCollectionParticipant */
+struct nsXPCOMCycleCollectionParticipantVTable
+{
+ void (NS_STDCALL *UnmarkIfPurple)(nsISupports *p);
+};
+
+/**
+ * Types for static initialization
+ *
+ * Considering T, the cycle collection participant class, subclass of either
+ * nsCycleCollectionParticipant, nsScriptObjectTracer or
+ * nsXPCOMCycleCollectionParticipant, static initialization goes as follows:
+ *
+ * CCParticipantVTable<T>::type T::_cycleCollectorGlobal = {{...} ...};
+ *
+ * CCParticipantVTable<T>::type automatically defines the right type considering
+ * what particular cycle collection participant class T derives from.
+ *
+ * The NS_IMPL_CYCLE_COLLECTION_NATIVE_VTABLE(classname),
+ * NS_IMPL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_VTABLE(classname), and
+ * NS_IMPL_CYCLE_COLLECTION_VTABLE(classname) macros may be used as helpers
+ * for static initialization:
+ *
+ * CCParticipantVTable<T>::type T::_cycleCollectorGlobal = {
+ * NS_IMPL_CYCLE_COLLECTION_NATIVE_VTABLE(classname);
+ * };
+ */
+
+enum nsCycleCollectionParticipantType
+{
+ eInvalid,
+ eCycleCollectionParticipant,
+ eScriptObjectTracer,
+ eXPCOMCycleCollectionParticipant
+};
+
+template <typename T, enum nsCycleCollectionParticipantType ParticipantType>
+struct CCParticipantVTableImpl { };
+
+/* CCParticipantVTable for nsCycleCollectionParticipant */
+template <typename T>
+struct CCParticipantVTableImpl<T, eCycleCollectionParticipant>
+{
+ nsCycleCollectionParticipant *GetParticipant()
+ {
+ return reinterpret_cast<nsCycleCollectionParticipant *>(this);
+ }
+ nsCycleCollectionParticipantVTableCommon<T> cycleCollectionParticipant;
+};
+
+/* CCParticipantVTable for nsScriptObjectTracer */
+template <typename T>
+struct CCParticipantVTableImpl<T, eScriptObjectTracer>
+{
+ nsScriptObjectTracer *GetParticipant()
+ {
+ return reinterpret_cast<nsScriptObjectTracer *>(this);
+ }
+ nsCycleCollectionParticipantVTableCommon<T> cycleCollectionParticipant;
+ nsScriptObjectTracerVTable scriptObjectTracer;
+};
+
+/* CCParticipantVTable for nsXPCOMCycleCollectionParticipant */
+template <typename T>
+struct CCParticipantVTableImpl<T, eXPCOMCycleCollectionParticipant>
+{
+ nsXPCOMCycleCollectionParticipant *GetParticipant()
+ {
+ return reinterpret_cast<nsXPCOMCycleCollectionParticipant *>(this);
+ }
+ nsCycleCollectionParticipantVTableCommon<T> cycleCollectionParticipant;
+ nsScriptObjectTracerVTable scriptObjectTracer;
+ nsXPCOMCycleCollectionParticipantVTable XPCOMCycleCollectionParticipant;
+};
+
+template <typename T>
+struct CCParticipantVTable
+{
+ static const enum nsCycleCollectionParticipantType ParticipantType =
+ mozilla::IsBaseOf<nsXPCOMCycleCollectionParticipant, T>::value ? eXPCOMCycleCollectionParticipant :
+ mozilla::IsBaseOf<nsScriptObjectTracer, T>::value ? eScriptObjectTracer :
+ mozilla::IsBaseOf<nsCycleCollectionParticipant, T>::value ? eCycleCollectionParticipant :
+ eInvalid;
+ typedef CCParticipantVTableImpl<T, ParticipantType> Type;
+};
+
+/**
+ * Participant implementation classes
+ */
+class nsCycleCollectionParticipant : public nsCycleCollectionParticipantVTable
{
public:
- nsCycleCollectionParticipant() : mMightSkip(false) {}
- nsCycleCollectionParticipant(bool aSkip) : mMightSkip(aSkip) {}
-
+ static const bool isSkippable = false;
+
NS_DECLARE_STATIC_IID_ACCESSOR(NS_CYCLECOLLECTIONPARTICIPANT_IID)
- NS_IMETHOD Traverse(void *p, nsCycleCollectionTraversalCallback &cb) = 0;
-
- NS_IMETHOD Root(void *p) = 0;
- NS_IMETHOD Unlink(void *p) = 0;
- NS_IMETHOD Unroot(void *p) = 0;
-
+ // Helper function to avoid painful syntax for member function call using
+ // the VTable entry.
+ NS_METHOD Traverse(void *p, nsCycleCollectionTraversalCallback &cb) {
+ return TraverseReal(this, p, cb);
+ }
// If CanSkip returns true, p is removed from the purple buffer during
// a call to nsCycleCollector_forgetSkippable().
// Note, calling CanSkip may remove objects from the purple buffer!
// If aRemovingAllowed is true, p can be removed from the purple buffer.
bool CanSkip(void *p, bool aRemovingAllowed)
{
- return mMightSkip ? CanSkipReal(p, aRemovingAllowed) : false;
+ return CanSkipReal ? CanSkipReal(p, aRemovingAllowed) : false;
}
// If CanSkipInCC returns true, p is skipped when selecting roots for the
// cycle collector graph.
// Note, calling CanSkipInCC may remove other objects from the purple buffer!
bool CanSkipInCC(void *p)
{
- return mMightSkip ? CanSkipInCCReal(p) : false;
+ return CanSkipInCCReal ? CanSkipInCCReal(p) : false;
}
// If CanSkipThis returns true, p is not added to the graph.
// This method is called during cycle collection, so don't
// change the state of any objects!
bool CanSkipThis(void *p)
{
- return mMightSkip ? CanSkipThisReal(p) : false;
- }
-protected:
- NS_IMETHOD_(bool) CanSkipReal(void *p, bool aRemovingAllowed)
- {
- NS_ASSERTION(false, "Forgot to implement CanSkipReal?");
- return false;
+ return CanSkipThisReal ? CanSkipThisReal(p) : false;
}
- NS_IMETHOD_(bool) CanSkipInCCReal(void *p)
- {
- NS_ASSERTION(false, "Forgot to implement CanSkipInCCReal?");
- return false;
- }
- NS_IMETHOD_(bool) CanSkipThisReal(void *p)
- {
- NS_ASSERTION(false, "Forgot to implement CanSkipThisReal?");
- return false;
- }
-
- bool mMightSkip;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsCycleCollectionParticipant,
NS_CYCLECOLLECTIONPARTICIPANT_IID)
-#undef IMETHOD_VISIBILITY
-#define IMETHOD_VISIBILITY NS_COM_GLUE
-
-typedef void
-(* TraceCallback)(void *p, const char *name, void *closure);
-
-class NS_NO_VTABLE nsScriptObjectTracer : public nsCycleCollectionParticipant
+class nsScriptObjectTracer
+ : public nsCycleCollectionParticipant, public nsScriptObjectTracerVTable
{
public:
- nsScriptObjectTracer() : nsCycleCollectionParticipant(false) {}
- nsScriptObjectTracer(bool aSkip) : nsCycleCollectionParticipant(aSkip) {}
-
- NS_IMETHOD_(void) Trace(void *p, TraceCallback cb, void *closure) = 0;
- void NS_COM_GLUE TraverseScriptObjects(void *p,
- nsCycleCollectionTraversalCallback &cb);
+ static void NS_COM_GLUE NoteJSChild(void *aScriptThing, const char *name,
+ void *aClosure);
};
-class NS_COM_GLUE nsXPCOMCycleCollectionParticipant
- : public nsScriptObjectTracer
+class nsXPCOMCycleCollectionParticipant
+ : public nsScriptObjectTracer, public nsXPCOMCycleCollectionParticipantVTable
{
public:
- nsXPCOMCycleCollectionParticipant()
- : nsScriptObjectTracer(false) {}
- nsXPCOMCycleCollectionParticipant(bool aSkip)
- : nsScriptObjectTracer(aSkip) {}
+ static NS_METHOD TraverseImpl(nsXPCOMCycleCollectionParticipant *that,
+ void *p, nsCycleCollectionTraversalCallback &cb);
- NS_IMETHOD Traverse(void *p, nsCycleCollectionTraversalCallback &cb);
+ static NS_METHOD RootImpl(void *p);
+ static NS_METHOD UnlinkImpl(void *p);
+ static NS_METHOD UnrootImpl(void *p);
- NS_IMETHOD Root(void *p);
- NS_IMETHOD Unlink(void *p);
- NS_IMETHOD Unroot(void *p);
-
- NS_IMETHOD_(void) Trace(void *p, TraceCallback cb, void *closure);
+ static NS_METHOD_(void) TraceImpl(void *p, TraceCallback cb, void *closure);
- NS_IMETHOD_(void) UnmarkIfPurple(nsISupports *p);
+ static NS_METHOD_(void) UnmarkIfPurpleImpl(nsISupports *p);
- bool CheckForRightISupports(nsISupports *s);
+ static bool CheckForRightISupports(nsISupports *s);
};
-#undef IMETHOD_VISIBILITY
-#define IMETHOD_VISIBILITY NS_VISIBILITY_HIDDEN
-
///////////////////////////////////////////////////////////////////////////////
// Helpers for implementing a QI to nsXPCOMCycleCollectionParticipant
///////////////////////////////////////////////////////////////////////////////
#define NS_CYCLE_COLLECTION_INNERCLASS \
cycleCollection
#define NS_CYCLE_COLLECTION_CLASSNAME(_class) \
_class::NS_CYCLE_COLLECTION_INNERCLASS
#define NS_CYCLE_COLLECTION_INNERNAME \
_cycleCollectorGlobal
-#define NS_CYCLE_COLLECTION_NAME(_class) \
- _class::NS_CYCLE_COLLECTION_INNERNAME
+#define NS_CYCLE_COLLECTION_PARTICIPANT(_class) \
+ _class::NS_CYCLE_COLLECTION_INNERNAME.GetParticipant()
#define NS_IMPL_QUERY_CYCLE_COLLECTION(_class) \
if ( aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant)) ) { \
- *aInstancePtr = & NS_CYCLE_COLLECTION_NAME(_class); \
+ *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
@@ -252,97 +365,97 @@ public:
NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(_class)
#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_NAME(_class); \
+ *aInstancePtr = NS_CYCLE_COLLECTION_PARTICIPANT(_class); \
return NS_OK; \
} \
nsresult rv;
#define NS_CYCLE_COLLECTION_UPCAST(obj, clazz) \
NS_CYCLE_COLLECTION_CLASSNAME(clazz)::Upcast(obj)
///////////////////////////////////////////////////////////////////////////////
// Helpers for implementing CanSkip methods
///////////////////////////////////////////////////////////////////////////////
#define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(_class) \
- NS_IMETHODIMP_(bool) \
- NS_CYCLE_COLLECTION_CLASSNAME(_class)::CanSkipReal(void *p, \
+ NS_METHOD_(bool) \
+ NS_CYCLE_COLLECTION_CLASSNAME(_class)::CanSkipImpl(void *p, \
bool aRemovingAllowed) \
{ \
nsISupports *s = static_cast<nsISupports*>(p); \
NS_ASSERTION(CheckForRightISupports(s), \
"not the nsISupports pointer we expect"); \
_class *tmp = Downcast(s);
#define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END \
(void)tmp; \
return false; \
}
#define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(_class) \
- NS_IMETHODIMP_(bool) \
- NS_CYCLE_COLLECTION_CLASSNAME(_class)::CanSkipInCCReal(void *p) \
+ NS_METHOD_(bool) \
+ NS_CYCLE_COLLECTION_CLASSNAME(_class)::CanSkipInCCImpl(void *p) \
{ \
nsISupports *s = static_cast<nsISupports*>(p); \
NS_ASSERTION(CheckForRightISupports(s), \
"not the nsISupports pointer we expect"); \
_class *tmp = Downcast(s);
#define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END \
(void)tmp; \
return false; \
}
#define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(_class) \
- NS_IMETHODIMP_(bool) \
- NS_CYCLE_COLLECTION_CLASSNAME(_class)::CanSkipThisReal(void *p) \
+ NS_METHOD_(bool) \
+ NS_CYCLE_COLLECTION_CLASSNAME(_class)::CanSkipThisImpl(void *p) \
{ \
nsISupports *s = static_cast<nsISupports*>(p); \
NS_ASSERTION(CheckForRightISupports(s), \
"not the nsISupports pointer we expect"); \
_class *tmp = Downcast(s);
#define NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END \
(void)tmp; \
return false; \
}
///////////////////////////////////////////////////////////////////////////////
// Helpers for implementing nsCycleCollectionParticipant::Unlink
///////////////////////////////////////////////////////////////////////////////
#define NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(_class) \
- NS_IMETHODIMP \
- NS_CYCLE_COLLECTION_CLASSNAME(_class)::Unlink(void *p) \
+ NS_METHOD \
+ NS_CYCLE_COLLECTION_CLASSNAME(_class)::UnlinkImpl(void *p) \
{ \
nsISupports *s = static_cast<nsISupports*>(p); \
NS_ASSERTION(CheckForRightISupports(s), \
"not the nsISupports pointer we expect"); \
_class *tmp = Downcast(s);
#define NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(_class, _base_class) \
- NS_IMETHODIMP \
- NS_CYCLE_COLLECTION_CLASSNAME(_class)::Unlink(void *p) \
+ NS_METHOD \
+ NS_CYCLE_COLLECTION_CLASSNAME(_class)::UnlinkImpl(void *p) \
{ \
nsISupports *s = static_cast<nsISupports*>(p); \
NS_ASSERTION(CheckForRightISupports(s), \
"not the nsISupports pointer we expect"); \
_class *tmp = static_cast<_class*>(Downcast(s)); \
- NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Unlink(s);
+ NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::UnlinkImpl(s);
#define NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(_class) \
- NS_IMETHODIMP \
- NS_CYCLE_COLLECTION_CLASSNAME(_class)::Unlink(void *p) \
+ NS_METHOD \
+ NS_CYCLE_COLLECTION_CLASSNAME(_class)::UnlinkImpl(void *p) \
{ \
_class *tmp = static_cast<_class*>(p);
#define NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(_field) \
tmp->_field = NULL;
#define NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(_field) \
tmp->_field.Clear();
@@ -351,43 +464,43 @@ public:
tmp->_field.Clear();
#define NS_IMPL_CYCLE_COLLECTION_UNLINK_END \
(void)tmp; \
return NS_OK; \
}
#define NS_IMPL_CYCLE_COLLECTION_UNLINK_0(_class) \
- NS_IMETHODIMP \
- NS_CYCLE_COLLECTION_CLASSNAME(_class)::Unlink(void *p) \
+ NS_METHOD \
+ NS_CYCLE_COLLECTION_CLASSNAME(_class)::UnlinkImpl(void *p) \
{ \
NS_ASSERTION(CheckForRightISupports(static_cast<nsISupports*>(p)), \
"not the nsISupports pointer we expect"); \
return NS_OK; \
}
#define NS_IMPL_CYCLE_COLLECTION_UNLINK_NATIVE_0(_class) \
- NS_IMETHODIMP \
- NS_CYCLE_COLLECTION_CLASSNAME(_class)::Unlink(void *p) \
+ NS_METHOD \
+ NS_CYCLE_COLLECTION_CLASSNAME(_class)::UnlinkImpl(void *p) \
{ \
return NS_OK; \
}
///////////////////////////////////////////////////////////////////////////////
// Helpers for implementing nsCycleCollectionParticipant::Traverse
///////////////////////////////////////////////////////////////////////////////
#define NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class, _refcnt) \
cb.DescribeRefCountedNode(_refcnt, sizeof(_class), #_class);
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(_class) \
- NS_IMETHODIMP \
- NS_CYCLE_COLLECTION_CLASSNAME(_class)::Traverse \
- (void *p, \
+ NS_METHOD \
+ NS_CYCLE_COLLECTION_CLASSNAME(_class)::TraverseImpl \
+ (NS_CYCLE_COLLECTION_CLASSNAME(_class) *that, void *p,\
nsCycleCollectionTraversalCallback &cb) \
{ \
nsISupports *s = static_cast<nsISupports*>(p); \
NS_ASSERTION(CheckForRightISupports(s), \
"not the nsISupports pointer we expect"); \
_class *tmp = static_cast<_class*>(Downcast(s));
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class) \
@@ -397,25 +510,25 @@ public:
// Base class' CC participant should return NS_SUCCESS_INTERRUPTED_TRAVERSE
// from Traverse if it wants derived classes to not traverse anything from
// their CC participant.
#define NS_SUCCESS_INTERRUPTED_TRAVERSE \
NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_XPCOM, 2)
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(_class, _base_class) \
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(_class) \
- if (NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Traverse(s, cb) == \
- NS_SUCCESS_INTERRUPTED_TRAVERSE) { \
+ if (NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::TraverseImpl(that, s, cb) \
+ == NS_SUCCESS_INTERRUPTED_TRAVERSE) { \
return NS_SUCCESS_INTERRUPTED_TRAVERSE; \
}
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(_class) \
- NS_IMETHODIMP \
- NS_CYCLE_COLLECTION_CLASSNAME(_class)::Traverse \
- (void *p, \
+ NS_METHOD \
+ NS_CYCLE_COLLECTION_CLASSNAME(_class)::TraverseImpl \
+ (NS_CYCLE_COLLECTION_CLASSNAME(_class) *that, void *p,\
nsCycleCollectionTraversalCallback &cb) \
{ \
_class *tmp = static_cast<_class*>(p); \
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class, tmp->mRefCnt.get())
#define NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(_cb, _name) \
PR_BEGIN_MACRO \
if (NS_UNLIKELY((_cb).WantDebugInfo())) { \
@@ -448,17 +561,17 @@ public:
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, #_field "[i]"); \
cb.NoteXPCOMChild(tmp->_field[i]); \
} \
}
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR(_ptr, _ptr_class, _name) \
PR_BEGIN_MACRO \
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, _name); \
- cb.NoteNativeChild(_ptr, &NS_CYCLE_COLLECTION_NAME(_ptr_class)); \
+ cb.NoteNativeChild(_ptr, NS_CYCLE_COLLECTION_PARTICIPANT(_ptr_class)); \
PR_END_MACRO;
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(_field, _field_class) \
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR(tmp->_field, _field_class, \
#_field)
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY(_array, _element_class, \
_name) \
@@ -480,56 +593,56 @@ public:
}
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY_MEMBER(_field, \
_element_class) \
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY(tmp->_field, _element_class, \
#_field)
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS \
- TraverseScriptObjects(p, cb);
+ that->Trace(p, &nsScriptObjectTracer::NoteJSChild, &cb);
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END \
return NS_OK; \
}
///////////////////////////////////////////////////////////////////////////////
// Helpers for implementing nsScriptObjectTracer::Trace
///////////////////////////////////////////////////////////////////////////////
#define NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(_class) \
void \
- NS_CYCLE_COLLECTION_CLASSNAME(_class)::Trace(void *p, \
- TraceCallback aCallback, \
- void *aClosure) \
+ NS_CYCLE_COLLECTION_CLASSNAME(_class)::TraceImpl(void *p, \
+ TraceCallback aCallback, \
+ void *aClosure) \
{ \
nsISupports *s = static_cast<nsISupports*>(p); \
NS_ASSERTION(CheckForRightISupports(s), \
"not the nsISupports pointer we expect"); \
_class *tmp = Downcast(s);
#define NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(_class, _base_class) \
void \
- NS_CYCLE_COLLECTION_CLASSNAME(_class)::Trace(void *p, \
- TraceCallback aCallback, \
- void *aClosure) \
+ NS_CYCLE_COLLECTION_CLASSNAME(_class)::TraceImpl(void *p, \
+ TraceCallback aCallback, \
+ void *aClosure) \
{ \
nsISupports *s = static_cast<nsISupports*>(p); \
NS_ASSERTION(CheckForRightISupports(s), \
"not the nsISupports pointer we expect"); \
_class *tmp = static_cast<_class*>(Downcast(s)); \
- NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Trace(s, \
- aCallback, \
- aClosure);
+ NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::TraceImpl(s, \
+ aCallback, \
+ aClosure);
#define NS_IMPL_CYCLE_COLLECTION_TRACE_NATIVE_BEGIN(_class) \
void \
- NS_CYCLE_COLLECTION_CLASSNAME(_class)::Trace(void *p, \
- TraceCallback aCallback, \
- void *aClosure) \
+ NS_CYCLE_COLLECTION_CLASSNAME(_class)::TraceImpl(void *p, \
+ TraceCallback aCallback, \
+ void *aClosure) \
{ \
_class *tmp = static_cast<_class*>(p);
#define NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(_object, _name) \
if (_object) \
aCallback(_object, _name, aClosure);
#define NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(_field) \
@@ -548,38 +661,39 @@ public:
(void)tmp; \
}
///////////////////////////////////////////////////////////////////////////////
// Helpers for implementing a concrete nsCycleCollectionParticipant
///////////////////////////////////////////////////////////////////////////////
#define NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE \
- static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME;
+ static CCParticipantVTable<NS_CYCLE_COLLECTION_INNERCLASS>::Type \
+ NS_CYCLE_COLLECTION_INNERNAME;
#define NS_DECL_CYCLE_COLLECTION_CLASS_BODY_NO_UNLINK(_class, _base) \
public: \
- NS_IMETHOD Traverse(void *p, \
- nsCycleCollectionTraversalCallback &cb); \
- NS_IMETHOD_(void) UnmarkIfPurple(nsISupports *s) \
+ static NS_METHOD TraverseImpl(NS_CYCLE_COLLECTION_CLASSNAME(_class) *that, \
+ void *p, nsCycleCollectionTraversalCallback &cb); \
+ static NS_METHOD_(void) UnmarkIfPurpleImpl(nsISupports *s) \
{ \
Downcast(s)->UnmarkIfPurple(); \
} \
static _class* Downcast(nsISupports* s) \
{ \
return static_cast<_class*>(static_cast<_base*>(s)); \
} \
static nsISupports* Upcast(_class *p) \
{ \
return NS_ISUPPORTS_CAST(_base*, p); \
}
#define NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base) \
NS_DECL_CYCLE_COLLECTION_CLASS_BODY_NO_UNLINK(_class, _base) \
- NS_IMETHOD Unlink(void *p);
+ static NS_METHOD UnlinkImpl(void *p);
#define NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(_class, _base) \
class NS_CYCLE_COLLECTION_INNERCLASS \
: public nsXPCOMCycleCollectionParticipant \
{ \
NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base) \
}; \
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
@@ -587,116 +701,106 @@ NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
#define NS_DECL_CYCLE_COLLECTION_CLASS(_class) \
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(_class, _class)
// Cycle collector helper for ambiguous classes that can sometimes be skipped.
#define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS_AMBIGUOUS(_class, _base) \
class NS_CYCLE_COLLECTION_INNERCLASS \
: public nsXPCOMCycleCollectionParticipant \
{ \
-public: \
- NS_CYCLE_COLLECTION_INNERCLASS () : nsXPCOMCycleCollectionParticipant(true) {} \
NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base) \
-protected: \
- NS_IMETHOD_(bool) CanSkipReal(void *p, bool aRemovingAllowed); \
- NS_IMETHOD_(bool) CanSkipInCCReal(void *p); \
- NS_IMETHOD_(bool) CanSkipThisReal(void *p); \
+ static const bool isSkippable = true; \
+ static NS_METHOD_(bool) CanSkipImpl(void *p, bool aRemovingAllowed); \
+ static NS_METHOD_(bool) CanSkipInCCImpl(void *p); \
+ static NS_METHOD_(bool) CanSkipThisImpl(void *p); \
}; \
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
#define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS(_class) \
NS_DECL_CYCLE_COLLECTION_SKIPPABLE_CLASS_AMBIGUOUS(_class, _class)
// Cycle collector helper for classes that don't want to unlink anything.
// Note: if this is used a lot it might make sense to have a base class that
// doesn't do anything in Root/Unlink/Unroot.
#define NS_DECL_CYCLE_COLLECTION_CLASS_NO_UNLINK(_class) \
class NS_CYCLE_COLLECTION_INNERCLASS \
: public nsXPCOMCycleCollectionParticipant \
{ \
NS_DECL_CYCLE_COLLECTION_CLASS_BODY_NO_UNLINK(_class, _class) \
- NS_IMETHOD Root(void *p) \
+ static NS_METHOD RootImpl(void *p) \
{ \
return NS_OK; \
} \
- NS_IMETHOD Unlink(void *p) \
+ static NS_METHOD UnlinkImpl(void *p) \
{ \
return NS_OK; \
} \
- NS_IMETHOD Unroot(void *p) \
+ static NS_METHOD UnrootImpl(void *p) \
{ \
return NS_OK; \
} \
}; \
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
#define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _base) \
class NS_CYCLE_COLLECTION_INNERCLASS \
: public nsXPCOMCycleCollectionParticipant \
{ \
NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base) \
- NS_IMETHOD_(void) Trace(void *p, TraceCallback cb, void *closure); \
+ static NS_METHOD_(void) TraceImpl(void *p, TraceCallback cb, void *closure); \
}; \
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
#define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _base) \
class NS_CYCLE_COLLECTION_INNERCLASS \
: public nsXPCOMCycleCollectionParticipant \
{ \
-public: \
- NS_CYCLE_COLLECTION_INNERCLASS () : nsXPCOMCycleCollectionParticipant(true) {} \
NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base) \
- NS_IMETHOD_(void) Trace(void *p, TraceCallback cb, void *closure); \
-protected: \
- NS_IMETHOD_(bool) CanSkipReal(void *p, bool aRemovingAllowed); \
- NS_IMETHOD_(bool) CanSkipInCCReal(void *p); \
- NS_IMETHOD_(bool) CanSkipThisReal(void *p); \
+ static const bool isSkippable = true; \
+ static NS_METHOD_(void) TraceImpl(void *p, TraceCallback cb, void *closure); \
+ static NS_METHOD_(bool) CanSkipImpl(void *p, bool aRemovingAllowed); \
+ static NS_METHOD_(bool) CanSkipInCCImpl(void *p); \
+ static NS_METHOD_(bool) CanSkipThisImpl(void *p); \
}; \
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
#define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(_class) \
NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _class)
#define NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_INHERITED(_class, \
_base_class) \
class NS_CYCLE_COLLECTION_INNERCLASS \
: public NS_CYCLE_COLLECTION_CLASSNAME(_base_class) \
{ \
-public: \
- NS_CYCLE_COLLECTION_INNERCLASS () \
- : NS_CYCLE_COLLECTION_CLASSNAME(_base_class)() \
- { \
- mMightSkip = true; \
- } \
- NS_IMETHOD_(void) Trace(void *p, TraceCallback cb, void *closure); \
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY(_class, _base_class) \
-protected: \
- NS_IMETHOD_(bool) CanSkipReal(void *p, bool aRemovingAllowed); \
- NS_IMETHOD_(bool) CanSkipInCCReal(void *p); \
- NS_IMETHOD_(bool) CanSkipThisReal(void *p); \
+ static const bool isSkippable = true; \
+ static NS_METHOD_(void) TraceImpl(void *p, TraceCallback cb, void *closure); \
+ static NS_METHOD_(bool) CanSkipImpl(void *p, bool aRemovingAllowed); \
+ static NS_METHOD_(bool) CanSkipInCCImpl(void *p); \
+ static NS_METHOD_(bool) CanSkipThisImpl(void *p); \
}; \
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
#define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(_class) \
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(_class, _class)
#define NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY_NO_UNLINK(_class, \
_base_class) \
public: \
- NS_IMETHOD Traverse(void *p, \
- nsCycleCollectionTraversalCallback &cb); \
+ static NS_METHOD TraverseImpl(NS_CYCLE_COLLECTION_CLASSNAME(_class) *that, \
+ void *p, nsCycleCollectionTraversalCallback &cb); \
static _class* Downcast(nsISupports* s) \
{ \
return static_cast<_class*>(static_cast<_base_class*>( \
NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Downcast(s))); \
}
#define NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY(_class, _base_class) \
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY_NO_UNLINK(_class, _base_class) \
- NS_IMETHOD Unlink(void *p);
+ static NS_METHOD UnlinkImpl(void *p);
#define NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(_class, _base_class) \
class NS_CYCLE_COLLECTION_INNERCLASS \
: public NS_CYCLE_COLLECTION_CLASSNAME(_base_class) \
{ \
public: \
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY(_class, _base_class) \
}; \
@@ -712,73 +816,127 @@ public:
}; \
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
#define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(_class, \
_base_class) \
class NS_CYCLE_COLLECTION_INNERCLASS \
: public NS_CYCLE_COLLECTION_CLASSNAME(_base_class) \
{ \
-public: \
- NS_IMETHOD_(void) Trace(void *p, TraceCallback cb, void *closure); \
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_BODY(_class, _base_class) \
+ static NS_METHOD_(void) TraceImpl(void *p, TraceCallback cb, void *closure); \
}; \
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
/**
* This implements a stub UnmarkIfPurple function for classes that want to be
* traversed but whose AddRef/Release functions don't add/remove them to/from
* the purple buffer. If you're just using NS_DECL_CYCLE_COLLECTING_ISUPPORTS
* then you don't need this.
*/
#define NS_DECL_CYCLE_COLLECTION_UNMARK_PURPLE_STUB(_class) \
NS_IMETHODIMP_(void) UnmarkIfPurple() \
{ \
} \
+/**
+ * Dummy class with a definition for CanSkip* function members, but no
+ * implementation.
+ * Implementation was added to please Win PGO. (See bug 765159)
+ */
+struct SkippableDummy
+{
+ static NS_METHOD_(bool) CanSkipImpl(void *p, bool aRemovingAllowed) { return false; }
+ static NS_METHOD_(bool) CanSkipInCCImpl(void *p) { return false; }
+ static NS_METHOD_(bool) CanSkipThisImpl(void *p) { return false; }
+};
+
+/**
+ * Skippable<T> defines a class that always has definitions for CanSkip*
+ * function members, so that T::isSkippable ? &Skippable<T>::CanSkip* : NULL
+ * can compile when T::isSkippable is false and T doesn't have CanSkip*
+ * definitions (which, as not being skippable, it's not supposed to have).
+ */
+template <class T>
+struct Skippable
+ : public mozilla::Conditional<T::isSkippable, T, SkippableDummy>::Type
+{ };
+
+#define NS_IMPL_CYCLE_COLLECTION_NATIVE_VTABLE(_class) \
+ { \
+ &_class::TraverseImpl, \
+ &_class::RootImpl, \
+ &_class::UnlinkImpl, \
+ &_class::UnrootImpl, \
+ _class::isSkippable ? &Skippable<_class>::CanSkipImpl : NULL, \
+ _class::isSkippable ? &Skippable<_class>::CanSkipInCCImpl : NULL, \
+ _class::isSkippable ? &Skippable<_class>::CanSkipThisImpl : NULL \
+ }
+
+#define NS_IMPL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_VTABLE(_class) \
+ NS_IMPL_CYCLE_COLLECTION_NATIVE_VTABLE(_class), \
+ { &_class::TraceImpl }
+
+#define NS_IMPL_CYCLE_COLLECTION_VTABLE(_class) \
+ NS_IMPL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_VTABLE(_class), \
+ { &_class::UnmarkIfPurpleImpl }
+
+#define NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(_class) \
+ CCParticipantVTable<NS_CYCLE_COLLECTION_CLASSNAME(_class)> \
+ ::Type _class::NS_CYCLE_COLLECTION_INNERNAME = \
+ { NS_IMPL_CYCLE_COLLECTION_NATIVE_VTABLE(NS_CYCLE_COLLECTION_CLASSNAME(_class)) };
+
+#define NS_IMPL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(_class) \
+ CCParticipantVTable<NS_CYCLE_COLLECTION_CLASSNAME(_class)> \
+ ::Type _class::NS_CYCLE_COLLECTION_INNERNAME = \
+ { NS_IMPL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_VTABLE(NS_CYCLE_COLLECTION_CLASSNAME(_class)) };
+
#define NS_IMPL_CYCLE_COLLECTION_CLASS(_class) \
- NS_CYCLE_COLLECTION_CLASSNAME(_class) NS_CYCLE_COLLECTION_NAME(_class);
+ CCParticipantVTable<NS_CYCLE_COLLECTION_CLASSNAME(_class)> \
+ ::Type _class::NS_CYCLE_COLLECTION_INNERNAME = \
+ { NS_IMPL_CYCLE_COLLECTION_VTABLE(NS_CYCLE_COLLECTION_CLASSNAME(_class)) };
-#define NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY \
+#define NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY(_class) \
public: \
- NS_IMETHOD Root(void *n); \
- NS_IMETHOD Unlink(void *n); \
- NS_IMETHOD Unroot(void *n); \
- NS_IMETHOD Traverse(void *n, \
- nsCycleCollectionTraversalCallback &cb);
+ static NS_METHOD RootImpl(void *n); \
+ static NS_METHOD UnlinkImpl(void *n); \
+ static NS_METHOD UnrootImpl(void *n); \
+ static NS_METHOD TraverseImpl(NS_CYCLE_COLLECTION_CLASSNAME(_class) *that, \
+ void *n, nsCycleCollectionTraversalCallback &cb);
#define NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(_class) \
class NS_CYCLE_COLLECTION_INNERCLASS \
: public nsCycleCollectionParticipant \
{ \
- NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY \
+ NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY(_class) \
}; \
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
#define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(_class) \
class NS_CYCLE_COLLECTION_INNERCLASS \
: public nsScriptObjectTracer \
{ \
- NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY \
- NS_IMETHOD_(void) Trace(void *p, TraceCallback cb, void *closure); \
+ NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY(_class) \
+ static NS_METHOD_(void) TraceImpl(void *p, TraceCallback cb, \
+ void *closure); \
}; \
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
#define NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(_class, _root_function) \
- NS_IMETHODIMP \
- NS_CYCLE_COLLECTION_CLASSNAME(_class)::Root(void *p) \
+ NS_METHOD \
+ NS_CYCLE_COLLECTION_CLASSNAME(_class)::RootImpl(void *p) \
{ \
_class *tmp = static_cast<_class*>(p); \
tmp->_root_function(); \
return NS_OK; \
}
#define NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(_class, _unroot_function) \
- NS_IMETHODIMP \
- NS_CYCLE_COLLECTION_CLASSNAME(_class)::Unroot(void *p) \
+ NS_METHOD \
+ NS_CYCLE_COLLECTION_CLASSNAME(_class)::UnrootImpl(void *p) \
{ \
_class *tmp = static_cast<_class*>(p); \
tmp->_unroot_function(); \
return NS_OK; \
}
#define NS_IMPL_CYCLE_COLLECTION_0(_class) \
NS_IMPL_CYCLE_COLLECTION_CLASS(_class) \