Fix for bug 475737 (Windows stay alive too long because nsJSContext doesn't unlink correctly). r=bent, sr=jst.

--HG--
extra : rebase_source : 459f24ea980bf4cab29bc88115138f6ed5144e49
This commit is contained in:
Peter Van der Beken 2009-05-07 11:19:36 -07:00
Родитель 4f0529e739
Коммит 0c43ed75e7
6 изменённых файлов: 45 добавлений и 21 удалений

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

@ -1286,7 +1286,9 @@ nsJSContext::~nsJSContext()
#endif
NS_PRECONDITION(!mTerminations, "Shouldn't have termination funcs by now");
Unlink();
mGlobalWrapperRef = nsnull;
DestroyJSContext();
--sContextCount;
@ -1303,7 +1305,7 @@ nsJSContext::~nsJSContext()
}
void
nsJSContext::Unlink()
nsJSContext::DestroyJSContext()
{
if (!mContext)
return;
@ -1316,30 +1318,37 @@ nsJSContext::Unlink()
JSOptionChangedCallback,
this);
// Release mGlobalWrapperRef before the context is destroyed
mGlobalWrapperRef = nsnull;
PRBool do_gc = mGCOnDestruction && !sGCTimer && sReadyForGC;
// Let xpconnect destroy the JSContext when it thinks the time is right.
nsIXPConnect *xpc = nsContentUtils::XPConnect();
if (xpc) {
PRBool do_gc = mGCOnDestruction && !sGCTimer && sReadyForGC;
xpc->ReleaseJSContext(mContext, !do_gc);
} else {
} else if (do_gc) {
::JS_DestroyContext(mContext);
} else {
::JS_DestroyContextNoGC(mContext);
}
mContext = nsnull;
}
// QueryInterface implementation for nsJSContext
NS_IMPL_CYCLE_COLLECTION_CLASS(nsJSContext)
NS_IMPL_CYCLE_COLLECTION_ROOT_BEGIN(nsJSContext)
NS_ASSERTION(!tmp->mContext || tmp->mContext->outstandingRequests == 0,
"Trying to unlink a context with outstanding requests.");
tmp->mIsInitialized = PR_FALSE;
tmp->mGCOnDestruction = PR_FALSE;
tmp->DestroyJSContext();
NS_IMPL_CYCLE_COLLECTION_ROOT_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsJSContext)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsJSContext)
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mGlobalWrapperRef)
tmp->Unlink();
tmp->mIsInitialized = PR_FALSE;
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsJSContext)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_REFCNT(nsJSContext, tmp->GetCCRefcnt())
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mGlobalWrapperRef)
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mContext");
nsContentUtils::XPConnect()->NoteJSContext(tmp->mContext, cb);
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@ -1353,6 +1362,12 @@ NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsJSContext, nsIScriptContext)
NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsJSContext, nsIScriptContext)
nsrefcnt
nsJSContext::GetCCRefcnt()
{
return mRefCnt.get() + mContext->outstandingRequests;
}
nsresult
nsJSContext::EvaluateStringWithValue(const nsAString& aScript,
void *aScopeObject,

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

@ -57,7 +57,8 @@ public:
virtual ~nsJSContext();
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsJSContext, nsIScriptContext)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsJSContext,
nsIScriptContext)
virtual PRUint32 GetScriptTypeID()
{ return nsIProgrammingLanguage::JAVASCRIPT; }
@ -218,7 +219,9 @@ protected:
// related to our exception.
void ReportPendingException(PRBool aSetAsideFrameChain);
private:
void Unlink();
void DestroyJSContext();
nsrefcnt GetCCRefcnt();
JSContext *mContext;
PRUint32 mNumEvaluations;

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

@ -594,6 +594,8 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode)
#endif
rt = cx->runtime;
JS_ASSERT_IF(rt->gcRunning, cx->outstandingRequests == 0);
if (mode != JSDCM_NEW_FAILED) {
cxCallback = rt->cxCallback;
if (cxCallback) {
@ -629,6 +631,8 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode)
|| cx->requestDepth != 0
#endif
) {
JS_ASSERT(rt->gcLevel == 0);
JS_UNLOCK_GC(rt);
if (last) {

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

@ -371,7 +371,6 @@ void XPCJSRuntime::TraceXPConnectRoots(JSTracer *trc, JSBool rootGlobals)
}
}
}
NS_ASSERTION(!rootGlobals || mUnrootedGlobalCount == 0, "bad state");
}
XPCWrappedNativeScope::TraceJS(trc, this);

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

@ -309,7 +309,7 @@ _class::AggregatedQueryInterface(REFNSIID aIID, void** aInstancePtr) \
"not the nsISupports pointer we expect"); \
_class *tmp = static_cast<_class*>(Downcast(s)); \
if (!tmp->IsPartOfAggregated()) \
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class)
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class, tmp->mRefCnt.get())
#define NS_GENERIC_AGGREGATED_CONSTRUCTOR(_InstanceClass) \
static NS_METHOD \

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

@ -322,14 +322,14 @@ public:
///////////////////////////////////////////////////////////////////////////////
#ifdef DEBUG_CC
#define NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class) \
cb.DescribeNode(RefCounted, tmp->mRefCnt.get(), sizeof(_class), #_class);
#define NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class, _refcnt) \
cb.DescribeNode(RefCounted, _refcnt, sizeof(_class), #_class);
#else
#define NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class) \
cb.DescribeNode(RefCounted, tmp->mRefCnt.get());
#define NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class, _refcnt) \
cb.DescribeNode(RefCounted, _refcnt);
#endif
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class) \
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_REFCNT(_class, _refcnt) \
NS_IMETHODIMP \
NS_CYCLE_COLLECTION_CLASSNAME(_class)::Traverse \
(void *p, \
@ -339,7 +339,10 @@ public:
NS_ASSERTION(CheckForRightISupports(s), \
"not the nsISupports pointer we expect"); \
_class *tmp = Downcast(s); \
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class)
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class, _refcnt)
#define NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(_class) \
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_REFCNT(_class, tmp->mRefCnt.get())
// Base class' CC participant should return NS_SUCCESS_INTERRUPTED_TRAVERSE
// from Traverse if it wants derived classes to not traverse anything from
@ -369,7 +372,7 @@ public:
nsCycleCollectionTraversalCallback &cb) \
{ \
_class *tmp = static_cast<_class*>(p); \
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class)
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(_class, tmp->mRefCnt.get())
#ifdef DEBUG_CC
#define NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(_cb, _name) \