Backing out once more to fix orange.

This commit is contained in:
peterv@propagandism.org 2007-10-28 05:49:30 -07:00
Родитель abb09e26b6
Коммит 8aff563c48
35 изменённых файлов: 327 добавлений и 685 удалений

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

@ -752,6 +752,42 @@ public:
*/ */
static nsIContentPolicy *GetContentPolicy(); static nsIContentPolicy *GetContentPolicy();
/**
* Make sure that whatever value *aPtr contains at any given moment is
* protected from JS GC until we remove the GC root. A call to this that
* succeeds MUST be matched by a call to RemoveJSGCRoot to avoid leaking.
*/
static nsresult AddJSGCRoot(jsval* aPtr, const char* aName) {
return AddJSGCRoot((void*)aPtr, aName);
}
/**
* Make sure that whatever object *aPtr is pointing to at any given moment is
* protected from JS GC until we remove the GC root. A call to this that
* succeeds MUST be matched by a call to RemoveJSGCRoot to avoid leaking.
*/
static nsresult AddJSGCRoot(JSObject** aPtr, const char* aName) {
return AddJSGCRoot((void*)aPtr, aName);
}
/**
* Make sure that whatever object *aPtr is pointing to at any given moment is
* protected from JS GC until we remove the GC root. A call to this that
* succeeds MUST be matched by a call to RemoveJSGCRoot to avoid leaking.
*/
static nsresult AddJSGCRoot(void* aPtr, const char* aName);
/**
* Remove aPtr as a JS GC root
*/
static nsresult RemoveJSGCRoot(jsval* aPtr) {
return RemoveJSGCRoot((void*)aPtr);
}
static nsresult RemoveJSGCRoot(JSObject** aPtr) {
return RemoveJSGCRoot((void*)aPtr);
}
static nsresult RemoveJSGCRoot(void* aPtr);
/** /**
* Quick helper to determine whether there are any mutation listeners * Quick helper to determine whether there are any mutation listeners
* of a given type that apply to this content or any of its ancestors. * of a given type that apply to this content or any of its ancestors.
@ -966,73 +1002,40 @@ public:
*/ */
static void DestroyAnonymousContent(nsCOMPtr<nsIContent>* aContent); static void DestroyAnonymousContent(nsCOMPtr<nsIContent>* aContent);
/** static nsresult HoldScriptObject(PRUint32 aLangID, void *aObject);
* Keep script object aNewObject, held by aScriptObjectHolder, alive. static nsresult DropScriptObject(PRUint32 aLangID, void *aObject);
*
* NOTE: This currently only supports objects that hold script objects of one class ScriptObjectHolder
* scripting language.
*
* @param aLangID script language ID of aNewObject
* @param aScriptObjectHolder the object that holds aNewObject
* @param aTracer the tracer for aScriptObject
* @param aNewObject the script object to hold
* @param aWasHoldingObjects whether aScriptObjectHolder was already holding
* script objects (ie. HoldScriptObject was called
* on it before, without a corresponding call to
* DropScriptObjects)
*/
static nsresult HoldScriptObject(PRUint32 aLangID, void* aScriptObjectHolder,
nsScriptObjectTracer* aTracer,
void* aNewObject, PRBool aWasHoldingObjects)
{ {
if (aLangID == nsIProgrammingLanguage::JAVASCRIPT) { public:
return aWasHoldingObjects ? NS_OK : ScriptObjectHolder(PRUint32 aLangID) : mLangID(aLangID),
HoldJSObjects(aScriptObjectHolder, aTracer); mObject(nsnull)
{
MOZ_COUNT_CTOR(ScriptObjectHolder);
} }
~ScriptObjectHolder()
return HoldScriptObject(aLangID, aNewObject); {
} MOZ_COUNT_DTOR(ScriptObjectHolder);
if (mObject)
/** DropScriptObject(mLangID, mObject);
* Drop any script objects that aScriptObjectHolder is holding.
*
* NOTE: This currently only supports objects that hold script objects of one
* scripting language.
*
* @param aLangID script language ID of the objects that
* @param aScriptObjectHolder the object that holds script object that we want
* to drop
* @param aTracer the tracer for aScriptObject
*/
static nsresult DropScriptObjects(PRUint32 aLangID, void* aScriptObjectHolder,
nsScriptObjectTracer* aTracer)
{
if (aLangID == nsIProgrammingLanguage::JAVASCRIPT) {
return DropJSObjects(aScriptObjectHolder);
} }
nsresult set(void *aObject)
aTracer->Trace(aScriptObjectHolder, DropScriptObject, nsnull); {
NS_ASSERTION(aObject, "unexpected null object");
return NS_OK; NS_ASSERTION(!mObject, "already have an object");
} nsresult rv = HoldScriptObject(mLangID, aObject);
if (NS_SUCCEEDED(rv)) {
/** mObject = aObject;
* Keep the JS objects held by aScriptObjectHolder alive. }
* return rv;
* @param aScriptObjectHolder the object that holds JS objects that we want to }
* keep alive void traverse(nsCycleCollectionTraversalCallback &cb)
* @param aTracer the tracer for aScriptObject {
*/ cb.NoteScriptChild(mLangID, mObject);
static nsresult HoldJSObjects(void* aScriptObjectHolder, }
nsScriptObjectTracer* aTracer); PRUint32 mLangID;
void *mObject;
/** };
* Drop the JS objects held by aScriptObjectHolder.
*
* @param aScriptObjectHolder the object that holds JS objects that we want to
* drop
*/
static nsresult DropJSObjects(void* aScriptObjectHolder);
/** /**
* Convert nsIContent::IME_STATUS_* to nsIKBStateControll::IME_STATUS_* * Convert nsIContent::IME_STATUS_* to nsIKBStateControll::IME_STATUS_*
@ -1119,10 +1122,6 @@ private:
static nsIDOMScriptObjectFactory *GetDOMScriptObjectFactory(); static nsIDOMScriptObjectFactory *GetDOMScriptObjectFactory();
static nsresult HoldScriptObject(PRUint32 aLangID, void* aObject);
PR_STATIC_CALLBACK(void) DropScriptObject(PRUint32 aLangID, void *aObject,
void *aClosure);
static nsIDOMScriptObjectFactory *sDOMScriptObjectFactory; static nsIDOMScriptObjectFactory *sDOMScriptObjectFactory;
static nsIXPConnect *sXPConnect; static nsIXPConnect *sXPConnect;
@ -1164,9 +1163,14 @@ private:
// Holds pointers to nsISupports* that should be released at shutdown // Holds pointers to nsISupports* that should be released at shutdown
static nsVoidArray* sPtrsToPtrsToRelease; static nsVoidArray* sPtrsToPtrsToRelease;
// For now, we don't want to automatically clean this up in Shutdown(), since
// consumers might unfortunately end up wanting to use it after that
static nsIJSRuntimeService* sJSRuntimeService;
static JSRuntime* sJSScriptRuntime;
static PRInt32 sJSScriptRootCount;
static nsIScriptRuntime* sScriptRuntimes[NS_STID_ARRAY_UBOUND]; static nsIScriptRuntime* sScriptRuntimes[NS_STID_ARRAY_UBOUND];
static PRInt32 sScriptRootCount[NS_STID_ARRAY_UBOUND]; static PRInt32 sScriptRootCount[NS_STID_ARRAY_UBOUND];
static PRUint32 sJSGCThingRootCount;
#ifdef IBMBIDI #ifdef IBMBIDI
static nsIBidiKeyboard* sBidiKeyboard; static nsIBidiKeyboard* sBidiKeyboard;
@ -1176,14 +1180,6 @@ private:
}; };
#define NS_HOLD_JS_OBJECTS(obj, clazz) \
nsContentUtils::HoldJSObjects(NS_CYCLE_COLLECTION_UPCAST(obj, clazz), \
&NS_CYCLE_COLLECTION_NAME(clazz))
#define NS_DROP_JS_OBJECTS(obj, clazz) \
nsContentUtils::DropJSObjects(NS_CYCLE_COLLECTION_UPCAST(obj, clazz))
class nsCxPusher class nsCxPusher
{ {
public: public:
@ -1206,38 +1202,33 @@ public:
nsAutoGCRoot(jsval* aPtr, nsresult* aResult) : nsAutoGCRoot(jsval* aPtr, nsresult* aResult) :
mPtr(aPtr) mPtr(aPtr)
{ {
mResult = *aResult = AddJSGCRoot(aPtr, "nsAutoGCRoot"); mResult = *aResult =
nsContentUtils::AddJSGCRoot(aPtr, "nsAutoGCRoot");
} }
// aPtr should be the pointer to the JSObject* we want to protect // aPtr should be the pointer to the JSObject* we want to protect
nsAutoGCRoot(JSObject** aPtr, nsresult* aResult) : nsAutoGCRoot(JSObject** aPtr, nsresult* aResult) :
mPtr(aPtr) mPtr(aPtr)
{ {
mResult = *aResult = AddJSGCRoot(aPtr, "nsAutoGCRoot"); mResult = *aResult =
nsContentUtils::AddJSGCRoot(aPtr, "nsAutoGCRoot");
} }
// aPtr should be the pointer to the thing we want to protect // aPtr should be the pointer to the thing we want to protect
nsAutoGCRoot(void* aPtr, nsresult* aResult) : nsAutoGCRoot(void* aPtr, nsresult* aResult) :
mPtr(aPtr) mPtr(aPtr)
{ {
mResult = *aResult = AddJSGCRoot(aPtr, "nsAutoGCRoot"); mResult = *aResult =
nsContentUtils::AddJSGCRoot(aPtr, "nsAutoGCRoot");
} }
~nsAutoGCRoot() { ~nsAutoGCRoot() {
if (NS_SUCCEEDED(mResult)) { if (NS_SUCCEEDED(mResult)) {
RemoveJSGCRoot(mPtr); nsContentUtils::RemoveJSGCRoot(mPtr);
} }
} }
static void Shutdown();
private: private:
static nsresult AddJSGCRoot(void *aPtr, const char* aName);
static nsresult RemoveJSGCRoot(void *aPtr);
static nsIJSRuntimeService* sJSRuntimeService;
static JSRuntime* sJSScriptRuntime;
void* mPtr; void* mPtr;
nsresult mResult; nsresult mResult;
}; };

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

@ -180,15 +180,15 @@ nsILineBreaker *nsContentUtils::sLineBreaker;
nsIWordBreaker *nsContentUtils::sWordBreaker; nsIWordBreaker *nsContentUtils::sWordBreaker;
nsICaseConversion *nsContentUtils::sCaseConv; nsICaseConversion *nsContentUtils::sCaseConv;
nsVoidArray *nsContentUtils::sPtrsToPtrsToRelease; nsVoidArray *nsContentUtils::sPtrsToPtrsToRelease;
nsIJSRuntimeService *nsContentUtils::sJSRuntimeService;
JSRuntime *nsContentUtils::sJSScriptRuntime;
PRInt32 nsContentUtils::sJSScriptRootCount = 0;
nsIScriptRuntime *nsContentUtils::sScriptRuntimes[NS_STID_ARRAY_UBOUND]; nsIScriptRuntime *nsContentUtils::sScriptRuntimes[NS_STID_ARRAY_UBOUND];
PRInt32 nsContentUtils::sScriptRootCount[NS_STID_ARRAY_UBOUND]; PRInt32 nsContentUtils::sScriptRootCount[NS_STID_ARRAY_UBOUND];
PRUint32 nsContentUtils::sJSGCThingRootCount;
#ifdef IBMBIDI #ifdef IBMBIDI
nsIBidiKeyboard *nsContentUtils::sBidiKeyboard = nsnull; nsIBidiKeyboard *nsContentUtils::sBidiKeyboard = nsnull;
#endif #endif
nsIJSRuntimeService *nsAutoGCRoot::sJSRuntimeService;
JSRuntime *nsAutoGCRoot::sJSScriptRuntime;
PRBool nsContentUtils::sInitialized = PR_FALSE; PRBool nsContentUtils::sInitialized = PR_FALSE;
@ -671,8 +671,7 @@ nsContentUtils::Shutdown()
NS_IF_RELEASE(sStringBundleService); NS_IF_RELEASE(sStringBundleService);
NS_IF_RELEASE(sConsoleService); NS_IF_RELEASE(sConsoleService);
NS_IF_RELEASE(sDOMScriptObjectFactory); NS_IF_RELEASE(sDOMScriptObjectFactory);
if (sJSGCThingRootCount == 0 && sXPConnect) NS_IF_RELEASE(sXPConnect);
NS_RELEASE(sXPConnect);
NS_IF_RELEASE(sSecurityManager); NS_IF_RELEASE(sSecurityManager);
NS_IF_RELEASE(sThreadJSContextStack); NS_IF_RELEASE(sThreadJSContextStack);
NS_IF_RELEASE(sNameSpaceManager); NS_IF_RELEASE(sNameSpaceManager);
@ -722,8 +721,6 @@ nsContentUtils::Shutdown()
sEventListenerManagersHash.ops = nsnull; sEventListenerManagersHash.ops = nsnull;
} }
} }
nsAutoGCRoot::Shutdown();
} }
static PRBool IsCallerTrustedForCapability(const char* aCapability) static PRBool IsCallerTrustedForCapability(const char* aCapability)
@ -2675,7 +2672,7 @@ nsContentUtils::GetContentPolicy()
// static // static
nsresult nsresult
nsAutoGCRoot::AddJSGCRoot(void* aPtr, const char* aName) nsContentUtils::AddJSGCRoot(void* aPtr, const char* aName)
{ {
if (!sJSScriptRuntime) { if (!sJSScriptRuntime) {
nsresult rv = CallGetService("@mozilla.org/js/xpc/RuntimeService;1", nsresult rv = CallGetService("@mozilla.org/js/xpc/RuntimeService;1",
@ -2693,16 +2690,25 @@ nsAutoGCRoot::AddJSGCRoot(void* aPtr, const char* aName)
PRBool ok; PRBool ok;
ok = ::JS_AddNamedRootRT(sJSScriptRuntime, aPtr, aName); ok = ::JS_AddNamedRootRT(sJSScriptRuntime, aPtr, aName);
if (!ok) { if (!ok) {
if (sJSScriptRootCount == 0) {
// We just got the runtime... Just null things out, since no
// one's expecting us to have a runtime yet
NS_RELEASE(sJSRuntimeService);
sJSScriptRuntime = nsnull;
}
NS_WARNING("JS_AddNamedRootRT failed"); NS_WARNING("JS_AddNamedRootRT failed");
return NS_ERROR_OUT_OF_MEMORY; return NS_ERROR_OUT_OF_MEMORY;
} }
// We now have one more root we added to the runtime
++sJSScriptRootCount;
return NS_OK; return NS_OK;
} }
/* static */ /* static */
nsresult nsresult
nsAutoGCRoot::RemoveJSGCRoot(void* aPtr) nsContentUtils::RemoveJSGCRoot(void* aPtr)
{ {
if (!sJSScriptRuntime) { if (!sJSScriptRuntime) {
NS_NOTREACHED("Trying to remove a JS GC root when none were added"); NS_NOTREACHED("Trying to remove a JS GC root when none were added");
@ -2711,6 +2717,11 @@ nsAutoGCRoot::RemoveJSGCRoot(void* aPtr)
::JS_RemoveRootRT(sJSScriptRuntime, aPtr); ::JS_RemoveRootRT(sJSScriptRuntime, aPtr);
if (--sJSScriptRootCount == 0) {
NS_RELEASE(sJSRuntimeService);
sJSScriptRuntime = nsnull;
}
return NS_OK; return NS_OK;
} }
@ -3514,8 +3525,6 @@ nsresult
nsContentUtils::HoldScriptObject(PRUint32 aLangID, void *aObject) nsContentUtils::HoldScriptObject(PRUint32 aLangID, void *aObject)
{ {
NS_ASSERTION(aObject, "unexpected null object"); NS_ASSERTION(aObject, "unexpected null object");
NS_ASSERTION(aLangID != nsIProgrammingLanguage::JAVASCRIPT,
"Should use HoldJSObjects.");
nsresult rv; nsresult rv;
PRUint32 langIndex = NS_STID_INDEX(aLangID); PRUint32 langIndex = NS_STID_INDEX(aLangID);
@ -3542,47 +3551,17 @@ nsContentUtils::HoldScriptObject(PRUint32 aLangID, void *aObject)
} }
/* static */ /* static */
void nsresult
nsContentUtils::DropScriptObject(PRUint32 aLangID, void *aObject, nsContentUtils::DropScriptObject(PRUint32 aLangID, void *aObject)
void *aClosure)
{ {
NS_ASSERTION(aObject, "unexpected null object"); NS_ASSERTION(aObject, "unexpected null object");
NS_ASSERTION(aLangID != nsIProgrammingLanguage::JAVASCRIPT,
"Should use DropJSObjects.");
PRUint32 langIndex = NS_STID_INDEX(aLangID); PRUint32 langIndex = NS_STID_INDEX(aLangID);
NS_LOG_RELEASE(sScriptRuntimes[langIndex], sScriptRootCount[langIndex] - 1, NS_LOG_RELEASE(sScriptRuntimes[langIndex], sScriptRootCount[langIndex] - 1,
"HoldScriptObject"); "HoldScriptObject");
sScriptRuntimes[langIndex]->DropScriptObject(aObject); nsresult rv = sScriptRuntimes[langIndex]->DropScriptObject(aObject);
if (--sScriptRootCount[langIndex] == 0) { if (--sScriptRootCount[langIndex] == 0) {
NS_RELEASE(sScriptRuntimes[langIndex]); NS_RELEASE(sScriptRuntimes[langIndex]);
} }
}
/* static */
nsresult
nsContentUtils::HoldJSObjects(void* aScriptObjectHolder,
nsScriptObjectTracer* aTracer)
{
PRBool newHolder;
nsresult rv = sXPConnect->AddJSHolder(aScriptObjectHolder, aTracer);
NS_ENSURE_SUCCESS(rv, rv);
++sJSGCThingRootCount;
NS_LOG_ADDREF(sXPConnect, sJSGCThingRootCount, "HoldJSObjects",
sizeof(void*));
return NS_OK;
}
/* static */
nsresult
nsContentUtils::DropJSObjects(void* aScriptObjectHolder)
{
NS_LOG_RELEASE(sXPConnect, sJSGCThingRootCount - 1, "HoldJSObjects");
nsresult rv = sXPConnect->RemoveJSHolder(aScriptObjectHolder);
if (--sJSGCThingRootCount == 0 && !sInitialized) {
NS_RELEASE(sXPConnect);
}
return rv; return rv;
} }
@ -3738,10 +3717,3 @@ nsContentUtils::IsNativeAnonymous(nsIContent* aContent)
return PR_FALSE; return PR_FALSE;
} }
/* static */
void
nsAutoGCRoot::Shutdown()
{
NS_IF_RELEASE(sJSRuntimeService);
}

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

@ -306,7 +306,7 @@ TraverseKey(nsISupports* aKey, nsInsertionPointList* aData, void* aClosure)
return PL_DHASH_NEXT; 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) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_NATIVE(nsXBLBinding)
// XXX Probably can't unlink mPrototypeBinding->XBLDocumentInfo(), because // XXX Probably can't unlink mPrototypeBinding->XBLDocumentInfo(), because
// mPrototypeBinding is weak. // mPrototypeBinding is weak.

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

@ -452,21 +452,6 @@ UnlinkProtos(nsHashKey *aKey, void *aData, void* aClosure)
return kHashEnumerateNext; return kHashEnumerateNext;
} }
struct ProtoTracer
{
TraceCallback mCallback;
void *mClosure;
};
static PRIntn PR_CALLBACK
TraceProtos(nsHashKey *aKey, void *aData, void* aClosure)
{
ProtoTracer* closure = static_cast<ProtoTracer*>(aClosure);
nsXBLPrototypeBinding *proto = static_cast<nsXBLPrototypeBinding*>(aData);
proto->Trace(closure->mCallback, closure->mClosure);
return kHashEnumerateNext;
}
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLDocumentInfo) NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLDocumentInfo)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXBLDocumentInfo) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXBLDocumentInfo)
if (tmp->mBindingTable) { if (tmp->mBindingTable) {
@ -481,14 +466,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXBLDocumentInfo)
tmp->mBindingTable->Enumerate(TraverseProtos, &cb); tmp->mBindingTable->Enumerate(TraverseProtos, &cb);
} }
cb.NoteXPCOMChild(static_cast<nsIScriptGlobalObject*>(tmp->mGlobalObject)); cb.NoteXPCOMChild(static_cast<nsIScriptGlobalObject*>(tmp->mGlobalObject));
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsXBLDocumentInfo)
if (tmp->mBindingTable) {
ProtoTracer closure = { aCallback, aClosure };
tmp->mBindingTable->Enumerate(TraceProtos, &closure);
}
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXBLDocumentInfo) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsXBLDocumentInfo)
NS_INTERFACE_MAP_ENTRY(nsIXBLDocumentInfo) NS_INTERFACE_MAP_ENTRY(nsIXBLDocumentInfo)
@ -529,10 +507,7 @@ nsXBLDocumentInfo::~nsXBLDocumentInfo()
mGlobalObject->SetScriptContext(nsIProgrammingLanguage::JAVASCRIPT, nsnull); mGlobalObject->SetScriptContext(nsIProgrammingLanguage::JAVASCRIPT, nsnull);
mGlobalObject->ClearGlobalObjectOwner(); // just in case mGlobalObject->ClearGlobalObjectOwner(); // just in case
} }
if (mBindingTable) { delete mBindingTable;
NS_DROP_JS_OBJECTS(this, nsXBLDocumentInfo);
delete mBindingTable;
}
} }
NS_IMETHODIMP NS_IMETHODIMP
@ -566,13 +541,8 @@ DeletePrototypeBinding(nsHashKey* aKey, void* aData, void* aClosure)
NS_IMETHODIMP NS_IMETHODIMP
nsXBLDocumentInfo::SetPrototypeBinding(const nsACString& aRef, nsXBLPrototypeBinding* aBinding) nsXBLDocumentInfo::SetPrototypeBinding(const nsACString& aRef, nsXBLPrototypeBinding* aBinding)
{ {
if (!mBindingTable) { if (!mBindingTable)
mBindingTable = new nsObjectHashtable(nsnull, nsnull, DeletePrototypeBinding, nsnull); mBindingTable = new nsObjectHashtable(nsnull, nsnull, DeletePrototypeBinding, nsnull);
if (!mBindingTable)
return NS_ERROR_OUT_OF_MEMORY;
NS_HOLD_JS_OBJECTS(this, nsXBLDocumentInfo);
}
const nsPromiseFlatCString& flat = PromiseFlatCString(aRef); const nsPromiseFlatCString& flat = PromiseFlatCString(aRef);
nsCStringKey key(flat.get()); nsCStringKey key(flat.get());

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

@ -72,8 +72,8 @@ public:
// nsIScriptGlobalObjectOwner methods // nsIScriptGlobalObjectOwner methods
virtual nsIScriptGlobalObject* GetScriptGlobalObject(); virtual nsIScriptGlobalObject* GetScriptGlobalObject();
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsXBLDocumentInfo, NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsXBLDocumentInfo,
nsIXBLDocumentInfo) nsIXBLDocumentInfo)
private: private:
nsCOMPtr<nsIDocument> mDocument; nsCOMPtr<nsIDocument> mDocument;

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

@ -64,7 +64,7 @@ nsXBLInsertionPoint::Release()
return mRefCnt; return mRefCnt;
} }
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_BEGIN_NATIVE(nsXBLInsertionPoint)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mElements) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mElements)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDefaultContentTemplate) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDefaultContentTemplate)

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

@ -200,7 +200,7 @@ nsXBLProtoImpl::CompilePrototypeMembers(nsXBLPrototypeBinding* aBinding)
} }
void void
nsXBLProtoImpl::Trace(TraceCallback aCallback, void *aClosure) const nsXBLProtoImpl::Traverse(nsCycleCollectionTraversalCallback &cb) const
{ {
// If we don't have a class object then we either didn't compile members // If we don't have a class object then we either didn't compile members
// or we only have fields, in both cases there are no cycles through our // or we only have fields, in both cases there are no cycles through our
@ -211,7 +211,7 @@ nsXBLProtoImpl::Trace(TraceCallback aCallback, void *aClosure) const
nsXBLProtoImplMember *member; nsXBLProtoImplMember *member;
for (member = mMembers; member; member = member->GetNext()) { for (member = mMembers; member; member = member->GetNext()) {
member->Trace(aCallback, aClosure); member->Traverse(cb);
} }
} }

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

@ -90,7 +90,7 @@ public:
mFields = aFieldList; mFields = aFieldList;
} }
void Trace(TraceCallback aCallback, void *aClosure) const; void Traverse(nsCycleCollectionTraversalCallback &cb) const;
void Unlink(); void Unlink();
nsXBLProtoImplField* FindField(const nsString& aFieldName) const; nsXBLProtoImplField* FindField(const nsString& aFieldName) const;

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

@ -47,11 +47,11 @@
#include "nsIJSRuntimeService.h" #include "nsIJSRuntimeService.h"
#include "nsIServiceManager.h" #include "nsIServiceManager.h"
#include "nsReadableUtils.h" #include "nsReadableUtils.h"
#include "nsCycleCollectionParticipant.h"
class nsIScriptContext; class nsIScriptContext;
struct JSRuntime; struct JSRuntime;
class nsIJSRuntimeService; class nsIJSRuntimeService;
class nsCycleCollectionTraversalCallback;
struct nsXBLTextWithLineNumber struct nsXBLTextWithLineNumber
{ {
@ -114,7 +114,7 @@ public:
const nsCString& aClassStr, const nsCString& aClassStr,
void* aClassObject)=0; void* aClassObject)=0;
virtual void Trace(TraceCallback aCallback, void *aClosure) const = 0; virtual void Traverse(nsCycleCollectionTraversalCallback &cb) const = 0;
protected: protected:
friend class nsAutoGCRoot; friend class nsAutoGCRoot;

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

@ -72,6 +72,8 @@ nsXBLProtoImplMethod::Destroy(PRBool aIsCompiled)
NS_PRECONDITION(aIsCompiled == mIsCompiled, NS_PRECONDITION(aIsCompiled == mIsCompiled,
"Incorrect aIsCompiled in nsXBLProtoImplMethod::Destroy"); "Incorrect aIsCompiled in nsXBLProtoImplMethod::Destroy");
if (aIsCompiled) { if (aIsCompiled) {
if (mJSMethodObject)
nsContentUtils::RemoveJSGCRoot(&mJSMethodObject);
mJSMethodObject = nsnull; mJSMethodObject = nsnull;
} }
else { else {
@ -261,6 +263,8 @@ nsXBLProtoImplMethod::CompileMember(nsIScriptContext* aContext, const nsCString&
if (methodObject) { if (methodObject) {
// Root the compiled prototype script object. // Root the compiled prototype script object.
rv = nsContentUtils::AddJSGCRoot(&mJSMethodObject,
"nsXBLProtoImplMethod::mJSMethodObject");
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
mJSMethodObject = nsnull; mJSMethodObject = nsnull;
} }
@ -273,13 +277,11 @@ nsXBLProtoImplMethod::CompileMember(nsIScriptContext* aContext, const nsCString&
} }
void void
nsXBLProtoImplMethod::Trace(TraceCallback aCallback, void *aClosure) const nsXBLProtoImplMethod::Traverse(nsCycleCollectionTraversalCallback &cb) const
{ {
NS_ASSERTION(mIsCompiled, "Shouldn't traverse uncompiled method"); NS_ASSERTION(mIsCompiled, "Shouldn't traverse uncompiled method");
if (mJSMethodObject) { cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, mJSMethodObject);
aCallback(nsIProgrammingLanguage::JAVASCRIPT, mJSMethodObject, aClosure);
}
} }
nsresult nsresult

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

@ -129,7 +129,7 @@ public:
const nsCString& aClassStr, const nsCString& aClassStr,
void* aClassObject); void* aClassObject);
virtual void Trace(TraceCallback aCallback, void *aClosure) const; virtual void Traverse(nsCycleCollectionTraversalCallback &cb) const;
protected: protected:
union { union {

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

@ -87,14 +87,14 @@ nsXBLProtoImplProperty::Destroy(PRBool aIsCompiled)
"Incorrect aIsCompiled in nsXBLProtoImplProperty::Destroy"); "Incorrect aIsCompiled in nsXBLProtoImplProperty::Destroy");
if ((mJSAttributes & JSPROP_GETTER) && mJSGetterObject) { if ((mJSAttributes & JSPROP_GETTER) && mJSGetterObject) {
mJSGetterObject = nsnull; nsContentUtils::RemoveJSGCRoot(&mJSGetterObject);
} }
else { else {
delete mGetterText; delete mGetterText;
} }
if ((mJSAttributes & JSPROP_SETTER) && mJSSetterObject) { if ((mJSAttributes & JSPROP_SETTER) && mJSSetterObject) {
mJSSetterObject = nsnull; nsContentUtils::RemoveJSGCRoot(&mJSSetterObject);
} }
else { else {
delete mSetterText; delete mSetterText;
@ -268,6 +268,9 @@ nsXBLProtoImplProperty::CompileMember(nsIScriptContext* aContext, const nsCStrin
if (mJSGetterObject && NS_SUCCEEDED(rv)) { if (mJSGetterObject && NS_SUCCEEDED(rv)) {
mJSAttributes |= JSPROP_GETTER | JSPROP_SHARED; mJSAttributes |= JSPROP_GETTER | JSPROP_SHARED;
// Root the compiled prototype script object.
rv = nsContentUtils::AddJSGCRoot(&mJSGetterObject,
"nsXBLProtoImplProperty::mJSGetterObject");
} }
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
mJSGetterObject = nsnull; mJSGetterObject = nsnull;
@ -317,6 +320,9 @@ nsXBLProtoImplProperty::CompileMember(nsIScriptContext* aContext, const nsCStrin
if (mJSSetterObject && NS_SUCCEEDED(rv)) { if (mJSSetterObject && NS_SUCCEEDED(rv)) {
mJSAttributes |= JSPROP_SETTER | JSPROP_SHARED; mJSAttributes |= JSPROP_SETTER | JSPROP_SHARED;
// Root the compiled prototype script object.
rv = nsContentUtils::AddJSGCRoot(&mJSSetterObject,
"nsXBLProtoImplProperty::mJSSetterObject");
} }
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
mJSSetterObject = nsnull; mJSSetterObject = nsnull;
@ -339,15 +345,15 @@ nsXBLProtoImplProperty::CompileMember(nsIScriptContext* aContext, const nsCStrin
} }
void void
nsXBLProtoImplProperty::Trace(TraceCallback aCallback, void *aClosure) const nsXBLProtoImplProperty::Traverse(nsCycleCollectionTraversalCallback &cb) const
{ {
NS_ASSERTION(mIsCompiled, "Shouldn't traverse uncompiled method"); NS_ASSERTION(mIsCompiled, "Shouldn't traverse uncompiled method");
if ((mJSAttributes & JSPROP_GETTER) && mJSGetterObject) { if (mJSAttributes & JSPROP_GETTER) {
aCallback(nsIProgrammingLanguage::JAVASCRIPT, mJSGetterObject, aClosure); cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, mJSGetterObject);
} }
if ((mJSAttributes & JSPROP_SETTER) && mJSSetterObject) { if (mJSAttributes & JSPROP_SETTER) {
aCallback(nsIProgrammingLanguage::JAVASCRIPT, mJSSetterObject, aClosure); cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, mJSSetterObject);
} }
} }

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

@ -72,7 +72,7 @@ public:
const nsCString& aClassStr, const nsCString& aClassStr,
void* aClassObject); void* aClassObject);
virtual void Trace(TraceCallback aCallback, void *aClosure) const; virtual void Traverse(nsCycleCollectionTraversalCallback &cb) const;
protected: protected:
union { union {

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

@ -244,7 +244,7 @@ private:
PRUint32 nsXBLInsertionPointEntry::gRefCnt = 0; PRUint32 nsXBLInsertionPointEntry::gRefCnt = 0;
nsFixedSizeAllocator* nsXBLInsertionPointEntry::kPool; 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_BEGIN_NATIVE(nsXBLInsertionPointEntry)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mInsertionParent) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mInsertionParent)
if (tmp->mDefaultContent) { if (tmp->mDefaultContent) {
@ -355,6 +355,8 @@ void
nsXBLPrototypeBinding::Traverse(nsCycleCollectionTraversalCallback &cb) const nsXBLPrototypeBinding::Traverse(nsCycleCollectionTraversalCallback &cb) const
{ {
cb.NoteXPCOMChild(mBinding); cb.NoteXPCOMChild(mBinding);
if (mImplementation)
mImplementation->Traverse(cb);
if (mResources) if (mResources)
cb.NoteXPCOMChild(mResources->mLoader); cb.NoteXPCOMChild(mResources->mLoader);
if (mInsertionPointTable) if (mInsertionPointTable)
@ -370,13 +372,6 @@ nsXBLPrototypeBinding::Unlink()
mImplementation->Unlink(); mImplementation->Unlink();
} }
void
nsXBLPrototypeBinding::Trace(TraceCallback aCallback, void *aClosure) const
{
if (mImplementation)
mImplementation->Trace(aCallback, aClosure);
}
void void
nsXBLPrototypeBinding::Initialize() nsXBLPrototypeBinding::Initialize()
{ {

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

@ -198,7 +198,6 @@ public:
void Traverse(nsCycleCollectionTraversalCallback &cb) const; void Traverse(nsCycleCollectionTraversalCallback &cb) const;
void Unlink(); void Unlink();
void Trace(TraceCallback aCallback, void *aClosure) const;
// Static members // Static members
static PRUint32 gRefCnt; static PRUint32 gRefCnt;

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

@ -55,6 +55,7 @@
* use in OS2 * use in OS2
*/ */
#include "jsapi.h" // for JS_AddNamedRoot and JS_RemoveRootRT
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsDOMCID.h" #include "nsDOMCID.h"
#include "nsDOMError.h" #include "nsDOMError.h"
@ -701,8 +702,7 @@ nsScriptEventHandlerOwnerTearoff::CompileEventHandler(
nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(mElement->GetOwnerDoc()); nsCOMPtr<nsIXULDocument> xuldoc = do_QueryInterface(mElement->GetOwnerDoc());
nsIScriptContext *context; nsIScriptContext *context;
nsXULPrototypeElement *elem = mElement->mPrototype; if (mElement->mPrototype && xuldoc) {
if (elem && xuldoc) {
// It'll be shared among the instances of the prototype. // It'll be shared among the instances of the prototype.
// Use the prototype document's special context. Because // Use the prototype document's special context. Because
@ -755,16 +755,9 @@ nsScriptEventHandlerOwnerTearoff::CompileEventHandler(
XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheFills); XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheFills);
// take a copy of the event handler, and tell the language about it. // take a copy of the event handler, and tell the language about it.
if (aHandler) { if (aHandler) {
NS_ASSERTION(!attr->mEventHandler, "Leaking handler.");
rv = nsContentUtils::HoldScriptObject(aContext->GetScriptTypeID(), rv = nsContentUtils::HoldScriptObject(aContext->GetScriptTypeID(),
elem, aHandler);
&NS_CYCLE_COLLECTION_NAME(nsXULPrototypeNode),
aHandler,
elem->mHoldsScriptObject);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
elem->mHoldsScriptObject = PR_TRUE;
} }
attr->mEventHandler = (void *)aHandler; attr->mEventHandler = (void *)aHandler;
} }
@ -2358,40 +2351,26 @@ nsXULElement::RecompileScriptEventListeners()
} }
} }
NS_IMPL_CYCLE_COLLECTION_CLASS(nsXULPrototypeNode) NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(nsXULPrototypeNode)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NATIVE_0(nsXULPrototypeNode) NS_IMPL_CYCLE_COLLECTION_UNLINK_NATIVE_0(nsXULPrototypeNode)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(nsXULPrototypeNode) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(nsXULPrototypeNode)
if (tmp->mType == nsXULPrototypeNode::eType_Element) { if (tmp->mType == nsXULPrototypeNode::eType_Element) {
nsXULPrototypeElement *elem = nsXULPrototypeElement *elem =
static_cast<nsXULPrototypeElement*>(tmp); static_cast<nsXULPrototypeElement*>(tmp);
PRUint32 i; PRUint32 i;
for (i = 0; i < elem->mNumAttributes; ++i) {
cb.NoteScriptChild(elem->mScriptTypeID,
elem->mAttributes[i].mEventHandler);
}
for (i = 0; i < elem->mNumChildren; ++i) { for (i = 0; i < elem->mNumChildren; ++i) {
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR(elem->mChildren[i], NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR(elem->mChildren[i],
nsXULPrototypeNode) nsXULPrototypeNode)
} }
} }
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_NATIVE_BEGIN(nsXULPrototypeNode)
if (tmp->mType == nsXULPrototypeNode::eType_Element) {
nsXULPrototypeElement *elem =
static_cast<nsXULPrototypeElement*>(tmp);
if (elem->mHoldsScriptObject) {
PRUint32 i;
for (i = 0; i < elem->mNumAttributes; ++i) {
void *handler = elem->mAttributes[i].mEventHandler;
NS_IMPL_CYCLE_COLLECTION_TRACE_CALLBACK(elem->mScriptTypeID,
handler)
}
}
}
else if (tmp->mType == nsXULPrototypeNode::eType_Script) { else if (tmp->mType == nsXULPrototypeNode::eType_Script) {
nsXULPrototypeScript *script = static_cast<nsXULPrototypeScript*>(tmp)->mScriptObject.traverse(cb);
static_cast<nsXULPrototypeScript*>(tmp);
NS_IMPL_CYCLE_COLLECTION_TRACE_CALLBACK(script->mScriptObject.mLangID,
script->mScriptObject.mObject)
} }
NS_IMPL_CYCLE_COLLECTION_TRACE_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsXULPrototypeNode, AddRef) NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsXULPrototypeNode, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsXULPrototypeNode, Release) NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsXULPrototypeNode, Release)
@ -2403,6 +2382,17 @@ NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsXULPrototypeNode, Release)
nsXULPrototypeAttribute::~nsXULPrototypeAttribute() nsXULPrototypeAttribute::~nsXULPrototypeAttribute()
{ {
MOZ_COUNT_DTOR(nsXULPrototypeAttribute); MOZ_COUNT_DTOR(nsXULPrototypeAttribute);
NS_ASSERTION(!mEventHandler, "Finalize not called - language object leak!");
}
void
nsXULPrototypeAttribute::Finalize(PRUint32 aLangID)
{
if (mEventHandler) {
if (NS_FAILED(nsContentUtils::DropScriptObject(aLangID, mEventHandler)))
NS_ERROR("Failed to drop script object");
mEventHandler = nsnull;
}
} }
@ -2689,19 +2679,6 @@ nsXULPrototypeElement::SetAttrAt(PRUint32 aPos, const nsAString& aValue,
return NS_OK; return NS_OK;
} }
void
nsXULPrototypeElement::Unlink()
{
if (mHoldsScriptObject) {
nsContentUtils::DropScriptObjects(mScriptTypeID, this,
&NS_CYCLE_COLLECTION_NAME(nsXULPrototypeNode));
mHoldsScriptObject = PR_FALSE;
}
mNumAttributes = 0;
delete[] mAttributes;
mAttributes = nsnull;
}
//---------------------------------------------------------------------- //----------------------------------------------------------------------
// //
// nsXULPrototypeScript // nsXULPrototypeScript
@ -2724,7 +2701,6 @@ nsXULPrototypeScript::nsXULPrototypeScript(PRUint32 aLangID, PRUint32 aLineNo, P
nsXULPrototypeScript::~nsXULPrototypeScript() nsXULPrototypeScript::~nsXULPrototypeScript()
{ {
Unlink();
} }
nsresult nsresult
@ -2842,7 +2818,7 @@ nsXULPrototypeScript::Deserialize(nsIObjectInputStream* aStream,
NS_WARNING("Language deseralization failed"); NS_WARNING("Language deseralization failed");
return rv; return rv;
} }
Set(newScriptObject); mScriptObject.set(newScriptObject);
return NS_OK; return NS_OK;
} }
@ -2895,7 +2871,7 @@ nsXULPrototypeScript::DeserializeOutOfLine(nsIObjectInputStream* aInput,
NS_ERROR("XUL cache gave different language?"); NS_ERROR("XUL cache gave different language?");
return NS_ERROR_UNEXPECTED; return NS_ERROR_UNEXPECTED;
} }
Set(newScriptObject); mScriptObject.set(newScriptObject);
} }
} }
} }
@ -3021,7 +2997,7 @@ nsXULPrototypeScript::Compile(const PRUnichar* aText,
if (NS_FAILED(rv)) if (NS_FAILED(rv))
return rv; return rv;
Set(newScriptObject); mScriptObject.set(newScriptObject);
return rv; return rv;
} }

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

@ -124,6 +124,9 @@ public:
// nsScriptObjectHolder, but want to avoid the extra lang ID. // nsScriptObjectHolder, but want to avoid the extra lang ID.
void* mEventHandler; void* mEventHandler;
// Containing element must tell us the langID so we can cleanup.
void Finalize(PRUint32 aLangID);
#ifdef XUL_PROTOTYPE_ATTRIBUTE_METERING #ifdef XUL_PROTOTYPE_ATTRIBUTE_METERING
/** /**
If enough attributes, on average, are event handlers, it pays to keep If enough attributes, on average, are event handlers, it pays to keep
@ -227,7 +230,7 @@ public:
*/ */
virtual void ReleaseSubtree() { Release(); } virtual void ReleaseSubtree() { Release(); }
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(nsXULPrototypeNode) NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(nsXULPrototypeNode)
protected: protected:
nsXULPrototypeNode(Type aType) nsXULPrototypeNode(Type aType)
@ -246,7 +249,6 @@ public:
mHasIdAttribute(PR_FALSE), mHasIdAttribute(PR_FALSE),
mHasClassAttribute(PR_FALSE), mHasClassAttribute(PR_FALSE),
mHasStyleAttribute(PR_FALSE), mHasStyleAttribute(PR_FALSE),
mHoldsScriptObject(PR_FALSE),
mScriptTypeID(nsIProgrammingLanguage::UNKNOWN) mScriptTypeID(nsIProgrammingLanguage::UNKNOWN)
{ {
NS_LOG_ADDREF(this, 1, ClassName(), ClassSize()); NS_LOG_ADDREF(this, 1, ClassName(), ClassSize());
@ -254,7 +256,10 @@ public:
virtual ~nsXULPrototypeElement() virtual ~nsXULPrototypeElement()
{ {
Unlink(); PRUint32 i;
for (i = 0; i < mNumAttributes; i++)
mAttributes[i].Finalize(mScriptTypeID);
delete[] mAttributes;
NS_ASSERTION(!mChildren && mNumChildren == 0, NS_ASSERTION(!mChildren && mNumChildren == 0,
"ReleaseSubtree not called"); "ReleaseSubtree not called");
} }
@ -289,8 +294,6 @@ public:
nsresult SetAttrAt(PRUint32 aPos, const nsAString& aValue, nsIURI* aDocumentURI); nsresult SetAttrAt(PRUint32 aPos, const nsAString& aValue, nsIURI* aDocumentURI);
void Unlink();
PRUint32 mNumChildren; PRUint32 mNumChildren;
nsXULPrototypeNode** mChildren; // [OWNER] nsXULPrototypeNode** mChildren; // [OWNER]
@ -302,7 +305,6 @@ public:
PRPackedBool mHasIdAttribute:1; PRPackedBool mHasIdAttribute:1;
PRPackedBool mHasClassAttribute:1; PRPackedBool mHasClassAttribute:1;
PRPackedBool mHasStyleAttribute:1; PRPackedBool mHasStyleAttribute:1;
PRPackedBool mHoldsScriptObject:1;
// The language ID can not be set on a per-node basis, but is tracked // The language ID can not be set on a per-node basis, but is tracked
// so that the language ID from the originating root can be used // so that the language ID from the originating root can be used
@ -359,52 +361,13 @@ public:
nsIDocument* aDocument, nsIDocument* aDocument,
nsIScriptGlobalObjectOwner* aGlobalOwner); nsIScriptGlobalObjectOwner* aGlobalOwner);
void Unlink()
{
if (mScriptObject.mObject) {
nsContentUtils::DropScriptObjects(mScriptObject.mLangID, this,
&NS_CYCLE_COLLECTION_NAME(nsXULPrototypeNode));
mScriptObject.mObject = nsnull;
}
}
void Set(nsScriptObjectHolder &aHolder)
{
NS_ASSERTION(mScriptObject.mLangID == aHolder.getScriptTypeID(),
"Wrong language, this will leak the previous object.");
mScriptObject.mLangID = aHolder.getScriptTypeID();
Set((void*)aHolder);
}
void Set(void *aObject)
{
NS_ASSERTION(!mScriptObject.mObject, "Leaking script object.");
nsresult rv = nsContentUtils::HoldScriptObject(mScriptObject.mLangID,
this,
&NS_CYCLE_COLLECTION_NAME(nsXULPrototypeNode),
aObject, PR_FALSE);
if (NS_SUCCEEDED(rv)) {
mScriptObject.mObject = aObject;
}
}
struct ScriptObjectHolder
{
ScriptObjectHolder(PRUint32 aLangID) : mLangID(aLangID),
mObject(nsnull)
{
}
PRUint32 mLangID;
void* mObject;
};
nsCOMPtr<nsIURI> mSrcURI; nsCOMPtr<nsIURI> mSrcURI;
PRUint32 mLineNo; PRUint32 mLineNo;
PRPackedBool mSrcLoading; PRPackedBool mSrcLoading;
PRPackedBool mOutOfLine; PRPackedBool mOutOfLine;
nsXULDocument* mSrcLoadWaiters; // [OWNER] but not COMPtr nsXULDocument* mSrcLoadWaiters; // [OWNER] but not COMPtr
PRUint32 mLangVersion; PRUint32 mLangVersion;
ScriptObjectHolder mScriptObject; nsContentUtils::ScriptObjectHolder mScriptObject;
}; };
class nsXULPrototypeText : public nsXULPrototypeNode class nsXULPrototypeText : public nsXULPrototypeNode

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

@ -3209,7 +3209,7 @@ nsXULDocument::LoadScript(nsXULPrototypeScript* aScriptProto, PRBool* aBlock)
NS_ERROR("XUL cache gave me an incorrect script language"); NS_ERROR("XUL cache gave me an incorrect script language");
return NS_ERROR_UNEXPECTED; return NS_ERROR_UNEXPECTED;
} }
aScriptProto->Set(newScriptObject); aScriptProto->mScriptObject.set(newScriptObject);
} }
if (aScriptProto->mScriptObject.mObject) { if (aScriptProto->mScriptObject.mObject) {

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

@ -3729,8 +3729,7 @@ public:
~nsJSArgArray(); ~nsJSArgArray();
// nsISupports // nsISupports
NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsJSArgArray, NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsJSArgArray, nsIJSArgArray)
nsIJSArgArray)
// nsIArray // nsIArray
NS_DECL_NSIARRAY NS_DECL_NSIARRAY
@ -3760,14 +3759,16 @@ nsJSArgArray::nsJSArgArray(JSContext *aContext, PRUint32 argc, jsval *argv,
return; return;
} }
// Callers are allowed to pass in a null argv even for argc > 0. They can JSAutoRequest ar(aContext);
// then use GetArgs to initialize the values. for (PRUint32 i = 0; i < argc; ++i) {
if (argv) { if (argv)
for (PRUint32 i = 0; i < argc; ++i)
mArgv[i] = argv[i]; mArgv[i] = argv[i];
if (!::JS_AddNamedRoot(aContext, &mArgv[i], "nsJSArgArray.mArgv[i]")) {
*prv = NS_ERROR_UNEXPECTED;
return;
}
} }
if (argc > 0) *prv = NS_OK;
*prv = NS_HOLD_JS_OBJECTS(this, nsJSArgArray);
} }
nsJSArgArray::~nsJSArgArray() nsJSArgArray::~nsJSArgArray()
@ -3778,9 +3779,13 @@ nsJSArgArray::~nsJSArgArray()
void void
nsJSArgArray::ReleaseJSObjects() nsJSArgArray::ReleaseJSObjects()
{ {
if (mArgc > 0)
NS_DROP_JS_OBJECTS(this, nsJSArgArray);
if (mArgv) { if (mArgv) {
NS_ASSERTION(nsJSRuntime::sRuntime, "Where's the runtime gone?");
if (nsJSRuntime::sRuntime) {
for (PRUint32 i = 0; i < mArgc; ++i) {
::JS_RemoveRootRT(nsJSRuntime::sRuntime, &mArgv[i]);
}
}
PR_DELETE(mArgv); PR_DELETE(mArgv);
} }
mArgc = 0; mArgc = 0;
@ -3792,20 +3797,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSArgArray)
tmp->ReleaseJSObjects(); tmp->ReleaseJSObjects();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsJSArgArray) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsJSArgArray)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS {
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END jsval *argv = tmp->mArgv;
if (argv) {
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsJSArgArray) jsval *end;
jsval *argv = tmp->mArgv; for (end = argv + tmp->mArgc; argv < end; ++argv) {
if (argv) { if (JSVAL_IS_OBJECT(*argv))
jsval *end; cb.NoteScriptChild(JAVASCRIPT, JSVAL_TO_OBJECT(*argv));
for (end = argv + tmp->mArgc; argv < end; ++argv) { }
if (JSVAL_IS_GCTHING(*argv))
NS_IMPL_CYCLE_COLLECTION_TRACE_CALLBACK(JAVASCRIPT,
JSVAL_TO_GCTHING(*argv))
} }
} }
NS_IMPL_CYCLE_COLLECTION_TRACE_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsJSArgArray) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsJSArgArray)
NS_INTERFACE_MAP_ENTRY(nsIArray) NS_INTERFACE_MAP_ENTRY(nsIArray)

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

@ -59,7 +59,7 @@ class nsJSScriptTimeoutHandler: public nsIScriptTimeoutHandler
public: public:
// nsISupports // nsISupports
NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsJSScriptTimeoutHandler) NS_DECL_CYCLE_COLLECTION_CLASS(nsJSScriptTimeoutHandler)
nsJSScriptTimeoutHandler(); nsJSScriptTimeoutHandler();
~nsJSScriptTimeoutHandler(); ~nsJSScriptTimeoutHandler();
@ -118,14 +118,9 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsJSScriptTimeoutHandler) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsJSScriptTimeoutHandler)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContext) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContext)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mArgv) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mArgv)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, tmp->mFunObj);
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsJSScriptTimeoutHandler)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mExpr)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mFunObj)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsJSScriptTimeoutHandler) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsJSScriptTimeoutHandler)
NS_INTERFACE_MAP_ENTRY(nsIScriptTimeoutHandler) NS_INTERFACE_MAP_ENTRY(nsIScriptTimeoutHandler)
NS_INTERFACE_MAP_ENTRY(nsISupports) NS_INTERFACE_MAP_ENTRY(nsISupports)
@ -151,11 +146,49 @@ void
nsJSScriptTimeoutHandler::ReleaseJSObjects() nsJSScriptTimeoutHandler::ReleaseJSObjects()
{ {
if (mExpr || mFunObj) { if (mExpr || mFunObj) {
nsCOMPtr<nsIScriptContext> scx = mContext;
JSRuntime *rt = nsnull;
if (scx) {
JSContext *cx;
cx = (JSContext *)scx->GetNativeContext();
rt = ::JS_GetRuntime(cx);
mContext = nsnull;
} else {
// XXX The timeout *must* be unrooted, even if !scx. This can be
// done without a JS context using the JSRuntime. This is safe
// enough, but it would be better to drop all a window's
// timeouts before its context is cleared. Bug 50705 describes a
// situation where we're not. In that case, at the time the
// context is cleared, a timeout (actually an Interval) is still
// active, but temporarily removed from the window's list of
// timers (placed instead on the timer manager's list). This
// makes the nearly handy ClearAllTimeouts routine useless, so
// we settled on using the JSRuntime rather than relying on the
// window having a context. It would be good to remedy this
// workable but clumsy situation someday.
nsCOMPtr<nsIJSRuntimeService> rtsvc =
do_GetService("@mozilla.org/js/xpc/RuntimeService;1");
if (rtsvc) {
rtsvc->GetRuntime(&rt);
}
}
if (!rt) {
// most unexpected. not much choice but to bail.
NS_ERROR("nsTimeout::Release() with no JSRuntime. eek!");
return;
}
if (mExpr) { if (mExpr) {
NS_DROP_JS_OBJECTS(this, nsJSScriptTimeoutHandler); ::JS_RemoveRootRT(rt, &mExpr);
mExpr = nsnull; mExpr = nsnull;
} else if (mFunObj) { } else if (mFunObj) {
NS_DROP_JS_OBJECTS(this, nsJSScriptTimeoutHandler); ::JS_RemoveRootRT(rt, &mFunObj);
mFunObj = nsnull; mFunObj = nsnull;
} else { } else {
NS_WARNING("No func and no expr - roots may not have been removed"); NS_WARNING("No func and no expr - roots may not have been removed");
@ -247,8 +280,9 @@ nsJSScriptTimeoutHandler::Init(nsIScriptContext *aContext, PRBool *aIsInterval,
} }
if (expr) { if (expr) {
rv = NS_HOLD_JS_OBJECTS(this, nsJSScriptTimeoutHandler); if (!::JS_AddNamedRoot(cx, &mExpr, "timeout.mExpr")) {
NS_ENSURE_SUCCESS(rv, rv); return NS_ERROR_OUT_OF_MEMORY;
}
mExpr = expr; mExpr = expr;
@ -258,8 +292,9 @@ nsJSScriptTimeoutHandler::Init(nsIScriptContext *aContext, PRBool *aIsInterval,
mFileName.Assign(filename); mFileName.Assign(filename);
} }
} else if (funobj) { } else if (funobj) {
rv = NS_HOLD_JS_OBJECTS(this, nsJSScriptTimeoutHandler); if (!::JS_AddNamedRoot(cx, &mFunObj, "timeout.mFunObj")) {
NS_ENSURE_SUCCESS(rv, rv); return NS_ERROR_OUT_OF_MEMORY;
}
mFunObj = funobj; mFunObj = funobj;

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

@ -81,13 +81,12 @@ nsJSEventListener::nsJSEventListener(nsIScriptContext *aContext,
// until we are done with it. // until we are done with it.
NS_ASSERTION(aScopeObject && aContext, NS_ASSERTION(aScopeObject && aContext,
"EventListener with no context or scope?"); "EventListener with no context or scope?");
NS_HOLD_JS_OBJECTS(this, nsJSEventListener); aContext->HoldScriptObject(aScopeObject);
} }
nsJSEventListener::~nsJSEventListener() nsJSEventListener::~nsJSEventListener()
{ {
if (mContext) mContext->DropScriptObject(mScopeObject);
NS_DROP_JS_OBJECTS(this, nsJSEventListener);
} }
NS_IMPL_CYCLE_COLLECTION_CLASS(nsJSEventListener) NS_IMPL_CYCLE_COLLECTION_CLASS(nsJSEventListener)
@ -97,14 +96,9 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsJSEventListener) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsJSEventListener)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTarget) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTarget)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContext) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContext)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, tmp->mScopeObject);
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsJSEventListener)
NS_IMPL_CYCLE_COLLECTION_TRACE_MEMBER_CALLBACK(tmp->mContext->GetScriptTypeID(),
mScopeObject)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsJSEventListener) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsJSEventListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener) NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
NS_INTERFACE_MAP_ENTRY(nsIJSEventListener) NS_INTERFACE_MAP_ENTRY(nsIJSEventListener)

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

@ -65,8 +65,8 @@ public:
// nsIJSEventListener interface // nsIJSEventListener interface
virtual void SetEventName(nsIAtom* aName); virtual void SetEventName(nsIAtom* aName);
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsJSEventListener, NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsJSEventListener,
nsIDOMEventListener) nsIDOMEventListener)
protected: protected:
nsCOMPtr<nsIAtom> mEventName; nsCOMPtr<nsIAtom> mEventName;

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

@ -766,47 +766,6 @@ GC(JSContext *cx, uintN argc, jsval *vp)
return JS_TRUE; return JS_TRUE;
} }
static JSBool
GCParameter(JSContext *cx, uintN argc, jsval *vp)
{
jsval *argv;
JSString *str;
const char *paramName;
JSGCParamKey param;
uint32 value;
argv = JS_ARGV(cx, vp);
str = JS_ValueToString(cx, argv[0]);
if (!str)
return JS_FALSE;
argv[0] = STRING_TO_JSVAL(str);
paramName = JS_GetStringBytes(str);
if (!paramName)
return JS_FALSE;
if (strcmp(paramName, "maxBytes") == 0) {
param = JSGC_MAX_BYTES;
} else if (strcmp(paramName, "maxMallocBytes") == 0) {
param = JSGC_MAX_MALLOC_BYTES;
} else {
JS_ReportError(cx,
"the first argument argument must be either maxBytes "
"or maxMallocBytes");
return JS_FALSE;
}
if (!JS_ValueToECMAUint32(cx, argv[1], &value))
return JS_FALSE;
if (value == 0) {
JS_ReportError(cx,
"the second argument must be convertable to uint32 with "
"non-zero value");
return JS_FALSE;
}
JS_SetGCParameter(cx->runtime, param, value);
*vp = JSVAL_VOID;
return JS_TRUE;
}
#ifdef JS_GC_ZEAL #ifdef JS_GC_ZEAL
static JSBool static JSBool
GCZeal(JSContext *cx, uintN argc, jsval *vp) GCZeal(JSContext *cx, uintN argc, jsval *vp)
@ -913,9 +872,9 @@ CountHeap(JSContext *cx, uintN argc, jsval *vp)
startThing = JSVAL_TO_TRACEABLE(v); startThing = JSVAL_TO_TRACEABLE(v);
startTraceKind = JSVAL_TRACE_KIND(v); startTraceKind = JSVAL_TRACE_KIND(v);
} else if (v != JSVAL_NULL) { } else if (v != JSVAL_NULL) {
JS_ReportError(cx, fprintf(gErrFile,
"the first argument is not null or a heap-allocated " "countHeap: argument 1 is not null or a heap-allocated "
"thing"); "thing\n");
return JS_FALSE; return JS_FALSE;
} }
} }
@ -934,7 +893,9 @@ CountHeap(JSContext *cx, uintN argc, jsval *vp)
break; break;
} }
if (++i == JS_ARRAY_LENGTH(traceKindNames)) { if (++i == JS_ARRAY_LENGTH(traceKindNames)) {
JS_ReportError(cx, "trace kind name '%s' is unknown", bytes); fprintf(gErrFile,
"countHeap: trace kind name '%s' is unknown\n",
bytes);
return JS_FALSE; return JS_FALSE;
} }
} }
@ -1651,7 +1612,8 @@ DumpHeap(JSContext *cx, uintN argc, jsval *vp)
} else { } else {
dumpFile = fopen(fileName, "w"); dumpFile = fopen(fileName, "w");
if (!dumpFile) { if (!dumpFile) {
JS_ReportError(cx, "can't open %s: %s", fileName, strerror(errno)); fprintf(gErrFile, "dumpHeap: can't open %s: %s\n",
fileName, strerror(errno));
return JS_FALSE; return JS_FALSE;
} }
} }
@ -1663,8 +1625,9 @@ DumpHeap(JSContext *cx, uintN argc, jsval *vp)
return ok; return ok;
not_traceable_arg: not_traceable_arg:
JS_ReportError(cx, "argument '%s' is not null or a heap-allocated thing", fprintf(gErrFile,
badTraceArg); "dumpHeap: argument '%s' is not null or a heap-allocated thing\n",
badTraceArg);
return JS_FALSE; return JS_FALSE;
} }
@ -2470,7 +2433,6 @@ static JSFunctionSpec shell_functions[] = {
JS_FS("help", Help, 0,0,0), JS_FS("help", Help, 0,0,0),
JS_FS("quit", Quit, 0,0,0), JS_FS("quit", Quit, 0,0,0),
JS_FN("gc", GC, 0,0,0), JS_FN("gc", GC, 0,0,0),
JS_FN("gcparam", GCParameter, 2,2,0),
JS_FN("countHeap", CountHeap, 0,0,0), JS_FN("countHeap", CountHeap, 0,0,0),
#ifdef JS_GC_ZEAL #ifdef JS_GC_ZEAL
JS_FN("gczeal", GCZeal, 1,1,0), JS_FN("gczeal", GCZeal, 1,1,0),
@ -2522,9 +2484,6 @@ static const char *const shell_help_messages[] = {
"help([name ...]) Display usage and help messages", "help([name ...]) Display usage and help messages",
"quit() Quit the shell", "quit() Quit the shell",
"gc() Run the garbage collector", "gc() Run the garbage collector",
"gcparam(name, value)\n"
" Wrapper for JS_SetGCParameter. The name must be either 'maxBytes' or\n"
" 'maxMallocBytes' and the value must be convertable to a positive uint32",
"countHeap([start[, kind]])\n" "countHeap([start[, kind]])\n"
" Count the number of live GC things in the heap or things reachable from\n" " Count the number of live GC things in the heap or things reachable from\n"
" start when it is given and is not null. kind is either 'all' (default) to\n" " start when it is given and is not null. kind is either 'all' (default) to\n"

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

@ -41,8 +41,6 @@
#include "nsISupports.idl" #include "nsISupports.idl"
#include "nsIXPConnect.idl" #include "nsIXPConnect.idl"
[ptr] native JSTracerPtr(JSTracer);
%{ C++ %{ C++
#define NS_SUCCESS_I_DID_SOMETHING \ #define NS_SUCCESS_I_DID_SOMETHING \
(NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_XPCONNECT,1)) (NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_XPCONNECT,1))

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

@ -64,7 +64,7 @@
native JSVal(jsval); native JSVal(jsval);
native JSID(jsid); native JSID(jsid);
[ptr] native voidPtrPtr(void*); [ptr] native voidPtrPtr(void*);
[ptr] native nsScriptObjectTracerPtr(nsScriptObjectTracer); [ptr] native JSTracerPtr(JSTracer);
/***************************************************************************/ /***************************************************************************/
@ -150,7 +150,7 @@ interface nsIXPCSecurityManager;
interface nsIPrincipal; interface nsIPrincipal;
%{C++ %{C++
class nsScriptObjectTracer; class nsCycleCollectionTraversalCallback;
%} %}
/***************************************************************************/ /***************************************************************************/
@ -443,7 +443,7 @@ interface nsIXPCFunctionThisTranslator : nsISupports
{ 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } } { 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
%} %}
[uuid(3eb7f5fc-1325-43af-aead-6033162e04af)] [uuid(52fc2ff3-c0ea-46c1-9105-655283c361ff)]
interface nsIXPConnect : nsISupports interface nsIXPConnect : nsISupports
{ {
%{ C++ %{ C++
@ -727,18 +727,4 @@ interface nsIXPConnect : nsISupports
[noscript] JSVal getCrossOriginWrapperForObject(in JSContextPtr aJSContext, [noscript] JSVal getCrossOriginWrapperForObject(in JSContextPtr aJSContext,
in JSObjectPtr aParent, in JSObjectPtr aParent,
in JSObjectPtr aWrappedObj); in JSObjectPtr aWrappedObj);
/**
* Root JS objects held by aHolder.
* @param aHolder The object that hold the JS objects that should be rooted.
* @param aTrace The tracer for aHolder.
*/
[noscript] void addJSHolder(in voidPtr aHolder,
in nsScriptObjectTracerPtr aTracer);
/**
* Stop rooting the JS objects held by aHolder.
* @param aHolder The object that hold the rooted JS objects.
*/
[noscript] void removeJSHolder(in voidPtr aHolder);
}; };

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

@ -695,31 +695,16 @@ NoteJSChild(JSTracer *trc, void *thing, uint32 kind)
static uint8 GCTypeToTraceKindMap[GCX_NTYPES] = { static uint8 GCTypeToTraceKindMap[GCX_NTYPES] = {
JSTRACE_OBJECT, /* GCX_OBJECT */ JSTRACE_OBJECT, /* GCX_OBJECT */
JSTRACE_STRING, /* GCX_STRING */ JSTRACE_STRING, /* GCX_STRING (unused) */
JSTRACE_DOUBLE, /* GCX_DOUBLE */ JSTRACE_DOUBLE, /* GCX_DOUBLE (unused) */
JSTRACE_FUNCTION, /* GCX_FUNCTION */ JSTRACE_STRING, /* GCX_MUTABLE_STRING (unused) */
JSTRACE_FUNCTION, /* GCX_FUNCTION (unused) */
JSTRACE_NAMESPACE, /* GCX_NAMESPACE */ JSTRACE_NAMESPACE, /* GCX_NAMESPACE */
JSTRACE_QNAME, /* GCX_QNAME */ JSTRACE_QNAME, /* GCX_QNAME */
JSTRACE_XML, /* GCX_XML */ JSTRACE_XML /* GCX_XML */
(uint8)-1, /* unused */ // We don't care about JSTRACE_STRING, so stop here
JSTRACE_STRING, /* GCX_EXTERNAL_STRING + 0 */
JSTRACE_STRING, /* GCX_EXTERNAL_STRING + 1 */
JSTRACE_STRING, /* GCX_EXTERNAL_STRING + 2 */
JSTRACE_STRING, /* GCX_EXTERNAL_STRING + 3 */
JSTRACE_STRING, /* GCX_EXTERNAL_STRING + 4 */
JSTRACE_STRING, /* GCX_EXTERNAL_STRING + 5 */
JSTRACE_STRING, /* GCX_EXTERNAL_STRING + 6 */
JSTRACE_STRING, /* GCX_EXTERNAL_STRING + 7 */
}; };
// static
uint8
nsXPConnect::GetTraceKind(void *thing)
{
uint8 type = *js_GetGCThingFlags(thing) & GCF_TYPEMASK;
return GCTypeToTraceKindMap[type];
}
NS_IMETHODIMP NS_IMETHODIMP
nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb) nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
{ {
@ -731,7 +716,7 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
PRUint32 refcount = mObjRefcounts->Get(p); PRUint32 refcount = mObjRefcounts->Get(p);
NS_ASSERTION(refcount > 0, "JS object but unknown to the JS GC?"); NS_ASSERTION(refcount > 0, "JS object but unknown to the JS GC?");
uint8 ty = GetTraceKind(p); uint8 ty = *js_GetGCThingFlags(p) & GCF_TYPEMASK;
if(ty != GCX_OBJECT && ty != GCX_NAMESPACE && ty != GCX_QNAME && if(ty != GCX_OBJECT && ty != GCX_NAMESPACE && ty != GCX_QNAME &&
ty != GCX_XML) ty != GCX_XML)
return NS_OK; return NS_OK;
@ -2112,18 +2097,6 @@ nsXPConnect::OnDispatchedEvent(nsIThreadInternal* aThread)
return NS_ERROR_UNEXPECTED; return NS_ERROR_UNEXPECTED;
} }
NS_IMETHODIMP
nsXPConnect::AddJSHolder(void* aHolder, nsScriptObjectTracer* aTracer)
{
return mRuntime->AddJSHolder(aHolder, aTracer);
}
NS_IMETHODIMP
nsXPConnect::RemoveJSHolder(void* aHolder)
{
return mRuntime->RemoveJSHolder(aHolder);
}
#ifdef DEBUG #ifdef DEBUG
/* These are here to be callable from a debugger */ /* These are here to be callable from a debugger */
JS_BEGIN_EXTERN_C JS_BEGIN_EXTERN_C

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

@ -251,42 +251,6 @@ ContextCallback(JSContext *cx, uintN operation)
: JS_TRUE; : JS_TRUE;
} }
struct ObjectHolder : public JSDHashEntryHdr
{
void *holder;
nsScriptObjectTracer* tracer;
};
nsresult
XPCJSRuntime::AddJSHolder(void* aHolder, nsScriptObjectTracer* aTracer)
{
if(!mJSHolders.ops)
return NS_ERROR_OUT_OF_MEMORY;
ObjectHolder *entry =
reinterpret_cast<ObjectHolder*>(JS_DHashTableOperate(&mJSHolders,
aHolder,
JS_DHASH_ADD));
if(!entry)
return NS_ERROR_OUT_OF_MEMORY;
entry->holder = aHolder;
entry->tracer = aTracer;
return NS_OK;
}
nsresult
XPCJSRuntime::RemoveJSHolder(void* aHolder)
{
if(!mJSHolders.ops)
return NS_ERROR_OUT_OF_MEMORY;
JS_DHashTableOperate(&mJSHolders, aHolder, JS_DHASH_REMOVE);
return NS_OK;
}
// static // static
void XPCJSRuntime::TraceJS(JSTracer* trc, void* data) void XPCJSRuntime::TraceJS(JSTracer* trc, void* data)
{ {
@ -313,48 +277,16 @@ void XPCJSRuntime::TraceJS(JSTracer* trc, void* data)
} }
} }
// XPCJSObjectHolders don't participate in cycle collection, so always trace XPCWrappedNativeScope::TraceJS(trc, self);
// them here.
for(XPCRootSetElem *e = self->mObjectHolderRoots; e ; e = e->GetNextRoot())
static_cast<XPCJSObjectHolder*>(e)->TraceJS(trc);
self->TraceXPConnectRoots(trc); for (XPCRootSetElem *e = self->mVariantRoots; e ; e = e->GetNextRoot())
}
PR_STATIC_CALLBACK(void)
TraceJSObject(PRUint32 aLangID, void *aScriptThing, void *aClosure)
{
if(aLangID == nsIProgrammingLanguage::JAVASCRIPT)
{
JS_CALL_TRACER(static_cast<JSTracer*>(aClosure), aScriptThing,
nsXPConnect::GetXPConnect()->GetTraceKind(aScriptThing),
"JSObjectHolder");
}
}
JS_STATIC_DLL_CALLBACK(JSDHashOperator)
TraceJSHolder(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number,
void *arg)
{
ObjectHolder* entry = reinterpret_cast<ObjectHolder*>(hdr);
entry->tracer->Trace(entry->holder, TraceJSObject, arg);
return JS_DHASH_NEXT;
}
void XPCJSRuntime::TraceXPConnectRoots(JSTracer *trc)
{
XPCWrappedNativeScope::TraceJS(trc, this);
for(XPCRootSetElem *e = mVariantRoots; e ; e = e->GetNextRoot())
static_cast<XPCTraceableVariant*>(e)->TraceJS(trc); static_cast<XPCTraceableVariant*>(e)->TraceJS(trc);
for(XPCRootSetElem *e = mWrappedJSRoots; e ; e = e->GetNextRoot()) for (XPCRootSetElem *e = self->mWrappedJSRoots; e ; e = e->GetNextRoot())
static_cast<nsXPCWrappedJS*>(e)->TraceJS(trc); static_cast<nsXPCWrappedJS*>(e)->TraceJS(trc);
if(mJSHolders.ops) for (XPCRootSetElem *e = self->mObjectHolderRoots; e ; e = e->GetNextRoot())
JS_DHashTableEnumerate(&mJSHolders, TraceJSHolder, trc); static_cast<XPCJSObjectHolder*>(e)->TraceJS(trc);
} }
// static // static
@ -877,12 +809,6 @@ XPCJSRuntime::~XPCJSRuntime()
gOldJSGCCallback = NULL; gOldJSGCCallback = NULL;
gOldJSContextCallback = NULL; gOldJSContextCallback = NULL;
if(mJSHolders.ops)
{
JS_DHashTableFinish(&mJSHolders);
mJSHolders.ops = nsnull;
}
} }
XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect, XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect,
@ -936,10 +862,6 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect,
JS_SetExtraGCRoots(mJSRuntime, TraceJS, this); JS_SetExtraGCRoots(mJSRuntime, TraceJS, this);
} }
if(!JS_DHashTableInit(&mJSHolders, JS_DHashGetStubOps(), nsnull,
sizeof(ObjectHolder), 512))
mJSHolders.ops = nsnull;
// Install a JavaScript 'debugger' keyword handler in debug builds only // Install a JavaScript 'debugger' keyword handler in debug builds only
#ifdef DEBUG #ifdef DEBUG
if(mJSRuntime && !JS_GetGlobalDebugHooks(mJSRuntime)->debuggerHandler) if(mJSRuntime && !JS_GetGlobalDebugHooks(mJSRuntime)->debuggerHandler)

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

@ -498,9 +498,6 @@ public:
#endif #endif
JSObjectRefcounts* GetJSObjectRefcounts() {return mObjRefcounts;} JSObjectRefcounts* GetJSObjectRefcounts() {return mObjRefcounts;}
static uint8 GetTraceKind(void *thing);
#ifndef XPCONNECT_STANDALONE #ifndef XPCONNECT_STANDALONE
void RecordTraversal(void *p, nsISupports *s); void RecordTraversal(void *p, nsISupports *s);
#endif #endif
@ -679,9 +676,6 @@ public:
} }
static void JS_DLL_CALLBACK TraceJS(JSTracer* trc, void* data); static void JS_DLL_CALLBACK TraceJS(JSTracer* trc, void* data);
void TraceXPConnectRoots(JSTracer *trc);
void AddXPConnectRoots(JSContext* cx,
nsCycleCollectionTraversalCallback& cb);
static JSBool JS_DLL_CALLBACK GCCallback(JSContext *cx, JSGCStatus status); static JSBool JS_DLL_CALLBACK GCCallback(JSContext *cx, JSGCStatus status);
@ -689,9 +683,6 @@ public:
inline void AddWrappedJSRoot(nsXPCWrappedJS* wrappedJS); inline void AddWrappedJSRoot(nsXPCWrappedJS* wrappedJS);
inline void AddObjectHolderRoot(XPCJSObjectHolder* holder); inline void AddObjectHolderRoot(XPCJSObjectHolder* holder);
nsresult AddJSHolder(void* aHolder, nsScriptObjectTracer* aTracer);
nsresult RemoveJSHolder(void* aHolder);
void DebugDump(PRInt16 depth); void DebugDump(PRInt16 depth);
void SystemIsBeingShutDown(JSContext* cx); void SystemIsBeingShutDown(JSContext* cx);
@ -755,7 +746,6 @@ private:
XPCRootSetElem *mVariantRoots; XPCRootSetElem *mVariantRoots;
XPCRootSetElem *mWrappedJSRoots; XPCRootSetElem *mWrappedJSRoots;
XPCRootSetElem *mObjectHolderRoots; XPCRootSetElem *mObjectHolderRoots;
JSDHashTable mJSHolders;
}; };
/***************************************************************************/ /***************************************************************************/
@ -1201,6 +1191,8 @@ public:
static void InitStatics() { gScopes = nsnull; gDyingScopes = nsnull; } static void InitStatics() { gScopes = nsnull; gDyingScopes = nsnull; }
void Traverse(nsCycleCollectionTraversalCallback &cb);
#ifndef XPCONNECT_STANDALONE #ifndef XPCONNECT_STANDALONE
/** /**
* Fills the hash mapping global object to principal. * Fills the hash mapping global object to principal.
@ -1939,11 +1931,10 @@ private:
class XPCWrappedNative : public nsIXPConnectWrappedNative class XPCWrappedNative : public nsIXPConnectWrappedNative
{ {
public: public:
NS_DECL_ISUPPORTS NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_NSIXPCONNECTJSOBJECTHOLDER NS_DECL_NSIXPCONNECTJSOBJECTHOLDER
NS_DECL_NSIXPCONNECTWRAPPEDNATIVE NS_DECL_NSIXPCONNECTWRAPPEDNATIVE
NS_DECL_CYCLE_COLLECTION_CLASS(XPCWrappedNative) NS_DECL_CYCLE_COLLECTION_CLASS(XPCWrappedNative)
NS_DECL_CYCLE_COLLECTION_UNMARK_PURPLE_STUB(XPCWrappedNative)
#ifndef XPCONNECT_STANDALONE #ifndef XPCONNECT_STANDALONE
virtual nsIPrincipal* GetObjectPrincipal() const; virtual nsIPrincipal* GetObjectPrincipal() const;
@ -2053,7 +2044,7 @@ public:
nsISupports* aCOMObj, nsISupports* aCOMObj,
XPCWrappedNative** aWrapper); XPCWrappedNative** aWrapper);
void FlatJSObjectFinalized(JSContext *cx); void FlatJSObjectFinalized(JSContext *cx, JSObject *obj);
void SystemIsBeingShutDown(JSContext* cx); void SystemIsBeingShutDown(JSContext* cx);
@ -2205,10 +2196,8 @@ private:
XPCWrappedNativeTearOffChunk mFirstChunk; XPCWrappedNativeTearOffChunk mFirstChunk;
JSObject* mWrapper; JSObject* mWrapper;
#ifdef XPC_CHECK_WRAPPER_THREADSAFETY
public: public:
nsCOMPtr<nsIThread> mThread; // Don't want to overload _mOwningThread nsCOMPtr<nsIThread> mThread; // Don't want to overload _mOwningThread
#endif
}; };
/*************************************************************************** /***************************************************************************
@ -3039,6 +3028,7 @@ private:
JSUint32 mWrappedNativeThreadsafetyReportDepth; JSUint32 mWrappedNativeThreadsafetyReportDepth;
#endif #endif
PRThread* mThread; PRThread* mThread;
nsVoidArray mNativesToReleaseArray;
static PRLock* gLock; static PRLock* gLock;
static XPCPerThreadData* gThreads; static XPCPerThreadData* gThreads;

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

@ -589,6 +589,10 @@ nsXPCWrappedJS::SystemIsBeingShutDown(JSRuntime* rt)
// work (and avoid crashing some platforms). // work (and avoid crashing some platforms).
mJSObj = nsnull; mJSObj = nsnull;
// There is no reason to keep this root any longer. Since we've cleared
// mJSObj our dtor will not remove the root later. So, we do it now.
JS_RemoveRootRT(rt, &mJSObj);
// Notify other wrappers in the chain. // Notify other wrappers in the chain.
if(mNext) if(mNext)
mNext->SystemIsBeingShutDown(rt); mNext->SystemIsBeingShutDown(rt);

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

@ -961,7 +961,7 @@ NS_IMPL_THREADSAFE_RELEASE(XPCWrappedNative)
*/ */
void void
XPCWrappedNative::FlatJSObjectFinalized(JSContext *cx) XPCWrappedNative::FlatJSObjectFinalized(JSContext *cx, JSObject *obj)
{ {
if(!IsValid()) if(!IsValid())
return; return;

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

@ -647,7 +647,7 @@ XPC_WN_NoHelper_Finalize(JSContext *cx, JSObject *obj)
XPCWrappedNative* p = (XPCWrappedNative*) JS_GetPrivate(cx, obj); XPCWrappedNative* p = (XPCWrappedNative*) JS_GetPrivate(cx, obj);
if(!p) if(!p)
return; return;
p->FlatJSObjectFinalized(cx); p->FlatJSObjectFinalized(cx, obj);
} }
static void static void
@ -658,7 +658,7 @@ TraceScopeJSObjects(JSTracer *trc, XPCWrappedNativeScope* scope)
JSObject* obj; JSObject* obj;
obj = scope->GetGlobalJSObject(); obj = scope->GetGlobalJSObject();
NS_ASSERTION(obj, "bad scope JSObject"); NS_ASSERTION(scope, "bad scope JSObject");
JS_CALL_OBJECT_TRACER(trc, obj, "XPCWrappedNativeScope::mGlobalJSObject"); JS_CALL_OBJECT_TRACER(trc, obj, "XPCWrappedNativeScope::mGlobalJSObject");
obj = scope->GetPrototypeJSObject(); obj = scope->GetPrototypeJSObject();
@ -1035,7 +1035,7 @@ XPC_WN_Helper_Finalize(JSContext *cx, JSObject *obj)
if(!wrapper) if(!wrapper)
return; return;
wrapper->GetScriptableCallback()->Finalize(wrapper, cx, obj); wrapper->GetScriptableCallback()->Finalize(wrapper, cx, obj);
wrapper->FlatJSObjectFinalized(cx); wrapper->FlatJSObjectFinalized(cx, obj);
} }
JS_STATIC_DLL_CALLBACK(void) JS_STATIC_DLL_CALLBACK(void)

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

@ -851,6 +851,16 @@ XPCWrappedNativeScope::DebugDump(PRInt16 depth)
#endif #endif
} }
void
XPCWrappedNativeScope::Traverse(nsCycleCollectionTraversalCallback &cb)
{
// See TraceScopeJSObjects.
cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, mGlobalJSObject);
cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT, mPrototypeJSObject);
cb.NoteScriptChild(nsIProgrammingLanguage::JAVASCRIPT,
mPrototypeJSFunction);
}
#ifndef XPCONNECT_STANDALONE #ifndef XPCONNECT_STANDALONE
// static // static
void void

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

@ -118,8 +118,7 @@ public: \
{ \ { \
return p->InnerObject(); \ return p->InnerObject(); \
} \ } \
}; \ };
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
// Put this in your class's constructor: // Put this in your class's constructor:
#define NS_INIT_AGGREGATED(outer) \ #define NS_INIT_AGGREGATED(outer) \

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

@ -38,21 +38,6 @@
#include "nsCycleCollectionParticipant.h" #include "nsCycleCollectionParticipant.h"
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
PR_STATIC_CALLBACK(void)
NoteChild(PRUint32 aLangID, void *aScriptThing, void *aClosure)
{
nsCycleCollectionTraversalCallback *cb =
static_cast<nsCycleCollectionTraversalCallback*>(aClosure);
cb->NoteScriptChild(aLangID, aScriptThing);
}
void
nsScriptObjectTracer::TraverseScriptObjects(void *p,
nsCycleCollectionTraversalCallback &cb)
{
Trace(p, NoteChild, &cb);
}
nsresult nsresult
nsXPCOMCycleCollectionParticipant::Root(void *p) nsXPCOMCycleCollectionParticipant::Root(void *p)
{ {
@ -87,12 +72,6 @@ nsXPCOMCycleCollectionParticipant::UnmarkPurple(nsISupports *n)
{ {
} }
NS_IMETHODIMP_(void)
nsXPCOMCycleCollectionParticipant::Trace(void *p, TraceCallback cb,
void *closure)
{
}
PRBool PRBool
nsXPCOMCycleCollectionParticipant::CheckForRightISupports(nsISupports *s) nsXPCOMCycleCollectionParticipant::CheckForRightISupports(nsISupports *s)
{ {

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

@ -125,19 +125,8 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsCycleCollectionParticipant,
#undef IMETHOD_VISIBILITY #undef IMETHOD_VISIBILITY
#define IMETHOD_VISIBILITY NS_COM_GLUE #define IMETHOD_VISIBILITY NS_COM_GLUE
typedef void
(* PR_CALLBACK TraceCallback)(PRUint32 langID, void *p, void *closure);
class NS_NO_VTABLE nsScriptObjectTracer : public nsCycleCollectionParticipant
{
public:
NS_IMETHOD_(void) Trace(void *p, TraceCallback cb, void *closure) = 0;
void NS_COM_GLUE TraverseScriptObjects(void *p,
nsCycleCollectionTraversalCallback &cb);
};
class NS_COM_GLUE nsXPCOMCycleCollectionParticipant class NS_COM_GLUE nsXPCOMCycleCollectionParticipant
: public nsScriptObjectTracer : public nsCycleCollectionParticipant
{ {
public: public:
NS_IMETHOD Traverse(void *p, nsCycleCollectionTraversalCallback &cb); NS_IMETHOD Traverse(void *p, nsCycleCollectionTraversalCallback &cb);
@ -146,8 +135,6 @@ public:
NS_IMETHOD Unlink(void *p); NS_IMETHOD Unlink(void *p);
NS_IMETHOD Unroot(void *p); NS_IMETHOD Unroot(void *p);
NS_IMETHOD_(void) Trace(void *p, TraceCallback cb, void *closure);
NS_IMETHOD_(void) UnmarkPurple(nsISupports *p); NS_IMETHOD_(void) UnmarkPurple(nsISupports *p);
PRBool CheckForRightISupports(nsISupports *s); PRBool CheckForRightISupports(nsISupports *s);
@ -166,11 +153,8 @@ public:
#define NS_CYCLE_COLLECTION_CLASSNAME(_class) \ #define NS_CYCLE_COLLECTION_CLASSNAME(_class) \
_class::NS_CYCLE_COLLECTION_INNERCLASS _class::NS_CYCLE_COLLECTION_INNERCLASS
#define NS_CYCLE_COLLECTION_INNERNAME \
_cycleCollectorGlobal
#define NS_CYCLE_COLLECTION_NAME(_class) \ #define NS_CYCLE_COLLECTION_NAME(_class) \
_class::NS_CYCLE_COLLECTION_INNERNAME _class##_cycleCollectorGlobal
#define NS_IMPL_QUERY_CYCLE_COLLECTION(_class) \ #define NS_IMPL_QUERY_CYCLE_COLLECTION(_class) \
if ( aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant)) ) { \ if ( aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant)) ) { \
@ -217,8 +201,6 @@ public:
} \ } \
nsresult rv; nsresult rv;
#define NS_CYCLE_COLLECTION_UPCAST(obj, clazz) \
NS_CYCLE_COLLECTION_CLASSNAME(clazz)::Upcast(obj)
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Helpers for implementing nsCycleCollectionParticipant::Unlink // Helpers for implementing nsCycleCollectionParticipant::Unlink
@ -341,7 +323,7 @@ public:
} }
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR(_ptr, _ptr_class) \ #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR(_ptr, _ptr_class) \
cb.NoteNativeChild(_ptr, &NS_CYCLE_COLLECTION_NAME(_ptr_class)); cb.NoteNativeChild(_ptr, &NS_CYCLE_COLLECTION_NATIVE_NAME(_ptr_class));
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(_field, _field_class) \ #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(_field, _field_class) \
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR(tmp->_field, _field_class) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_PTR(tmp->_field, _field_class)
@ -358,61 +340,18 @@ public:
_element_class) \ _element_class) \
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY(tmp->_field, _element_class) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSTARRAY(tmp->_field, _element_class)
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS \
TraverseScriptObjects(tmp, cb);
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END \ #define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END \
return NS_OK; \ 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) \
{ \
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_NATIVE_BEGIN(_class) \
void \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::Trace(void *p, \
TraceCallback aCallback, \
void *aClosure) \
{ \
_class *tmp = static_cast<_class*>(p);
#define NS_IMPL_CYCLE_COLLECTION_TRACE_CALLBACK(_langID, _object) \
if (_object) \
aCallback(_langID, _object, aClosure);
#define NS_IMPL_CYCLE_COLLECTION_TRACE_MEMBER_CALLBACK(_langID, _field) \
NS_IMPL_CYCLE_COLLECTION_TRACE_CALLBACK(_langID, tmp->_field)
#define NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(_object) \
NS_IMPL_CYCLE_COLLECTION_TRACE_CALLBACK(nsIProgrammingLanguage::JAVASCRIPT, \
_object)
#define NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(_field) \
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_CALLBACK(tmp->_field)
#define NS_IMPL_CYCLE_COLLECTION_TRACE_END \
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Helpers for implementing a concrete nsCycleCollectionParticipant // Helpers for implementing a concrete nsCycleCollectionParticipant
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE \ #define NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(_class, _base) \
static NS_CYCLE_COLLECTION_INNERCLASS NS_CYCLE_COLLECTION_INNERNAME; class NS_CYCLE_COLLECTION_INNERCLASS \
: public nsXPCOMCycleCollectionParticipant \
#define NS_DECL_CYCLE_COLLECTION_CLASS_BODY(_class, _base) \ { \
public: \ public: \
NS_IMETHOD Unlink(void *p); \ NS_IMETHOD Unlink(void *p); \
NS_IMETHOD Traverse(void *p, \ NS_IMETHOD Traverse(void *p, \
@ -428,31 +367,12 @@ public: \
static nsISupports* Upcast(_class *p) \ static nsISupports* Upcast(_class *p) \
{ \ { \
return NS_ISUPPORTS_CAST(_base*, p); \ return NS_ISUPPORTS_CAST(_base*, 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
#define NS_DECL_CYCLE_COLLECTION_CLASS(_class) \ #define NS_DECL_CYCLE_COLLECTION_CLASS(_class) \
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(_class, _class) NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(_class, _class)
#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); \
}; \
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(_class, _base_class) \ #define NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(_class, _base_class) \
class NS_CYCLE_COLLECTION_INNERCLASS \ class NS_CYCLE_COLLECTION_INNERCLASS \
: public NS_CYCLE_COLLECTION_CLASSNAME(_base_class) \ : public NS_CYCLE_COLLECTION_CLASSNAME(_base_class) \
@ -466,8 +386,7 @@ public: \
return static_cast<_class*>(static_cast<_base_class*>( \ return static_cast<_class*>(static_cast<_base_class*>( \
NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Downcast(s))); \ NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Downcast(s))); \
} \ } \
}; \ };
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
#define NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(_class, \ #define NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(_class, \
_base_class) \ _base_class) \
@ -482,8 +401,7 @@ public: \
return static_cast<_class*>(static_cast<_base_class*>( \ return static_cast<_class*>(static_cast<_base_class*>( \
NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Downcast(s))); \ NS_CYCLE_COLLECTION_CLASSNAME(_base_class)::Downcast(s))); \
} \ } \
}; \ };
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
/** /**
* This implements a stub UnmarkPurple function for classes that want to be * This implements a stub UnmarkPurple function for classes that want to be
@ -497,32 +415,31 @@ NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
} \ } \
#define NS_IMPL_CYCLE_COLLECTION_CLASS(_class) \ #define NS_IMPL_CYCLE_COLLECTION_CLASS(_class) \
NS_CYCLE_COLLECTION_CLASSNAME(_class) NS_CYCLE_COLLECTION_NAME(_class); static NS_CYCLE_COLLECTION_CLASSNAME(_class) \
NS_CYCLE_COLLECTION_NAME(_class);
#define NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY \ #define NS_CYCLE_COLLECTION_NATIVE_INNERNAME \
public: \ _cycleCollectorGlobal
NS_IMETHOD Root(void *n); \
NS_IMETHOD Unlink(void *n); \ #define NS_CYCLE_COLLECTION_NATIVE_NAME(_class) \
NS_IMETHOD Unroot(void *n); \ _class::NS_CYCLE_COLLECTION_NATIVE_INNERNAME
NS_IMETHOD Traverse(void *n, \
nsCycleCollectionTraversalCallback &cb);
#define NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(_class) \ #define NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(_class) \
class NS_CYCLE_COLLECTION_INNERCLASS \ class NS_CYCLE_COLLECTION_INNERCLASS \
: public nsCycleCollectionParticipant \ : public nsCycleCollectionParticipant \
{ \ { \
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY \ public: \
NS_IMETHOD Root(void *n); \
NS_IMETHOD Unlink(void *n); \
NS_IMETHOD Unroot(void *n); \
NS_IMETHOD Traverse(void *n, \
nsCycleCollectionTraversalCallback &cb); \
}; \ }; \
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE static NS_CYCLE_COLLECTION_INNERCLASS \
NS_CYCLE_COLLECTION_NATIVE_INNERNAME;
#define NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(_class) \ #define NS_IMPL_CYCLE_COLLECTION_NATIVE_CLASS(_class) \
class NS_CYCLE_COLLECTION_INNERCLASS \ NS_CYCLE_COLLECTION_CLASSNAME(_class) NS_CYCLE_COLLECTION_NATIVE_NAME(_class);
: public nsScriptObjectTracer \
{ \
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS_BODY \
NS_IMETHOD_(void) Trace(void *p, TraceCallback cb, void *closure); \
}; \
NS_CYCLE_COLLECTION_PARTICIPANT_INSTANCE
#define NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(_class, _root_function) \ #define NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(_class, _root_function) \
NS_IMETHODIMP \ NS_IMETHODIMP \