mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 690970, part 3: fix black-gray edges in weak containers at start of CC. r=billm
This commit is contained in:
parent
27baaa4757
commit
ecb75d0a95
@ -473,6 +473,72 @@ TraceWeakMapping(js::WeakMapTracer *trc, JSObject *m,
|
||||
}
|
||||
}
|
||||
|
||||
// This is based on the logic in TraceWeakMapping.
|
||||
struct FixWeakMappingGrayBitsTracer : public js::WeakMapTracer
|
||||
{
|
||||
FixWeakMappingGrayBitsTracer(JSRuntime *rt)
|
||||
: js::WeakMapTracer(rt, FixWeakMappingGrayBits)
|
||||
{}
|
||||
|
||||
void
|
||||
FixAll()
|
||||
{
|
||||
do {
|
||||
mAnyMarked = false;
|
||||
js::TraceWeakMaps(this);
|
||||
} while (mAnyMarked);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static void
|
||||
FixWeakMappingGrayBits(js::WeakMapTracer *trc, JSObject *m,
|
||||
void *k, JSGCTraceKind kkind,
|
||||
void *v, JSGCTraceKind vkind)
|
||||
{
|
||||
MOZ_ASSERT(!js::IsIncrementalBarrierNeeded(trc->runtime),
|
||||
"Don't call FixWeakMappingGrayBits during a GC.");
|
||||
|
||||
FixWeakMappingGrayBitsTracer *tracer = static_cast<FixWeakMappingGrayBitsTracer*>(trc);
|
||||
|
||||
// If nothing that could be held alive by this entry is marked gray, return.
|
||||
bool delegateMightNeedMarking = k && xpc_IsGrayGCThing(k);
|
||||
bool valueMightNeedMarking = v && xpc_IsGrayGCThing(v) && vkind != JSTRACE_STRING;
|
||||
if (!delegateMightNeedMarking && !valueMightNeedMarking)
|
||||
return;
|
||||
|
||||
if (!AddToCCKind(kkind))
|
||||
k = nullptr;
|
||||
|
||||
if (delegateMightNeedMarking && kkind == JSTRACE_OBJECT) {
|
||||
JSObject *kdelegate = js::GetWeakmapKeyDelegate((JSObject *)k);
|
||||
if (kdelegate && !xpc_IsGrayGCThing(kdelegate)) {
|
||||
js::UnmarkGrayGCThingRecursively(k, JSTRACE_OBJECT);
|
||||
tracer->mAnyMarked = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (v && xpc_IsGrayGCThing(v) &&
|
||||
(!k || !xpc_IsGrayGCThing(k)) &&
|
||||
(!m || !xpc_IsGrayGCThing(m)) &&
|
||||
vkind != JSTRACE_SHAPE)
|
||||
{
|
||||
js::UnmarkGrayGCThingRecursively(v, vkind);
|
||||
tracer->mAnyMarked = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool mAnyMarked;
|
||||
};
|
||||
|
||||
void
|
||||
nsXPConnect::FixWeakMappingGrayBits()
|
||||
{
|
||||
FixWeakMappingGrayBitsTracer fixer(GetRuntime()->GetJSRuntime());
|
||||
fixer.FixAll();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXPConnect::BeginCycleCollection(nsCycleCollectionTraversalCallback &cb)
|
||||
{
|
||||
|
@ -525,7 +525,7 @@ public:
|
||||
nsresult GetInfoForIID(const nsIID * aIID, nsIInterfaceInfo** info);
|
||||
nsresult GetInfoForName(const char * name, nsIInterfaceInfo** info);
|
||||
|
||||
// nsCycleCollectionLanguageRuntime
|
||||
// nsCycleCollectionJSRuntime
|
||||
virtual bool NotifyLeaveMainThread();
|
||||
virtual void NotifyEnterCycleCollectionThread();
|
||||
virtual void NotifyLeaveCycleCollectionThread();
|
||||
@ -533,6 +533,7 @@ public:
|
||||
virtual nsresult BeginCycleCollection(nsCycleCollectionTraversalCallback &cb);
|
||||
virtual nsresult FinishTraverse();
|
||||
virtual nsCycleCollectionParticipant *GetParticipant();
|
||||
virtual void FixWeakMappingGrayBits();
|
||||
virtual bool NeedCollect();
|
||||
virtual void Collect(uint32_t reason);
|
||||
|
||||
|
@ -1070,7 +1070,7 @@ struct nsCycleCollector
|
||||
// Prepare for and cleanup after one or more collection(s).
|
||||
bool PrepareForCollection(nsCycleCollectorResults *aResults,
|
||||
nsTArray<PtrInfo*> *aWhiteNodes);
|
||||
void GCIfNeeded(bool aForceGC);
|
||||
void FixGrayBits(bool aForceGC);
|
||||
void CleanupAfterCollection();
|
||||
|
||||
// Start and finish an individual collection.
|
||||
@ -2699,10 +2699,10 @@ nsCycleCollector::LogPurpleRemoval(void* aObject)
|
||||
// and also when UnmarkGray has run out of stack. We also force GCs on shut
|
||||
// down to collect cycles involving both DOM and JS.
|
||||
void
|
||||
nsCycleCollector::GCIfNeeded(bool aForceGC)
|
||||
nsCycleCollector::FixGrayBits(bool aForceGC)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(),
|
||||
"nsCycleCollector::GCIfNeeded() must be called on the main thread.");
|
||||
"nsCycleCollector::FixGrayBits() must be called on the main thread.");
|
||||
|
||||
if (mParams.mDoNothing)
|
||||
return;
|
||||
@ -2711,6 +2711,8 @@ nsCycleCollector::GCIfNeeded(bool aForceGC)
|
||||
return;
|
||||
|
||||
if (!aForceGC) {
|
||||
mJSRuntime->FixWeakMappingGrayBits();
|
||||
|
||||
bool needGC = mJSRuntime->NeedCollect();
|
||||
// Only do a telemetry ping for non-shutdown CCs.
|
||||
Telemetry::Accumulate(Telemetry::CYCLE_COLLECTOR_NEED_GC, needGC);
|
||||
@ -2811,7 +2813,7 @@ nsCycleCollector::Collect(bool aMergeCompartments,
|
||||
uint32_t totalCollections = 0;
|
||||
while (aTryCollections > totalCollections) {
|
||||
// Synchronous cycle collection. Always force a JS GC beforehand.
|
||||
GCIfNeeded(true);
|
||||
FixGrayBits(true);
|
||||
if (aListener && NS_FAILED(aListener->Begin()))
|
||||
aListener = nullptr;
|
||||
if (!(BeginCollection(aMergeCompartments, aListener) &&
|
||||
@ -3272,7 +3274,7 @@ public:
|
||||
if (aListener) {
|
||||
aListener->GetWantAllTraces(&wantAllTraces);
|
||||
}
|
||||
mCollector->GCIfNeeded(wantAllTraces);
|
||||
mCollector->FixGrayBits(wantAllTraces);
|
||||
|
||||
MutexAutoLock autoLock(mLock);
|
||||
|
||||
|
@ -67,6 +67,11 @@ struct nsCycleCollectionJSRuntime
|
||||
virtual void NotifyLeaveCycleCollectionThread() = 0;
|
||||
virtual void NotifyEnterMainThread() = 0;
|
||||
|
||||
/**
|
||||
* Unmark gray any weak map values, as needed.
|
||||
*/
|
||||
virtual void FixWeakMappingGrayBits() = 0;
|
||||
|
||||
/**
|
||||
* Should we force a JavaScript GC before a CC?
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user