mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1146213 - Finish ongoing GC before parse task zone becomes a non-exclusive zone again r=bhackett
This commit is contained in:
parent
1b29409dab
commit
361af94e04
@ -5519,7 +5519,6 @@ AutoTraceSession::AutoTraceSession(JSRuntime* rt, JS::HeapState heapState)
|
||||
runtime(rt),
|
||||
prevState(rt->heapState_)
|
||||
{
|
||||
MOZ_ASSERT(rt->gc.isAllocAllowed());
|
||||
MOZ_ASSERT(rt->heapState_ == JS::HeapState::Idle);
|
||||
MOZ_ASSERT(heapState != JS::HeapState::Idle);
|
||||
MOZ_ASSERT_IF(heapState == JS::HeapState::MajorCollecting, rt->gc.nursery.isEmpty());
|
||||
@ -6129,6 +6128,8 @@ GCRuntime::collect(bool incremental, SliceBudget budget, JS::gcreason::Reason re
|
||||
/* The engine never locks across anything that could GC. */
|
||||
MOZ_ASSERT(!rt->currentThreadHasExclusiveAccess());
|
||||
|
||||
MOZ_ASSERT(isAllocAllowed());
|
||||
|
||||
if (rt->mainThread.suppressGC)
|
||||
return;
|
||||
|
||||
|
@ -926,40 +926,8 @@ GlobalHelperThreadState::finishParseTask(JSContext* maybecx, JSRuntime* rt, void
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
LeaveParseTaskZone(rt, parseTask);
|
||||
mergeParseTaskCompartment(rt, parseTask, global, cx->compartment());
|
||||
|
||||
// Point the prototypes of any objects in the script's compartment to refer
|
||||
// to the corresponding prototype in the new compartment. This will briefly
|
||||
// create cross compartment pointers, which will be fixed by the
|
||||
// MergeCompartments call below. It's not safe for a GC to observe this
|
||||
// state, so finish any ongoing GC first and assert that we can't trigger
|
||||
// another one.
|
||||
gc::AutoFinishGC finishGC(rt);
|
||||
for (gc::ZoneCellIter iter(parseTask->cx->zone(), gc::AllocKind::OBJECT_GROUP);
|
||||
!iter.done();
|
||||
iter.next())
|
||||
{
|
||||
JS::AutoAssertNoAlloc noAlloc(rt);
|
||||
ObjectGroup* group = iter.get<ObjectGroup>();
|
||||
TaggedProto proto(group->proto());
|
||||
if (!proto.isObject())
|
||||
continue;
|
||||
|
||||
JSProtoKey key = JS::IdentifyStandardPrototype(proto.toObject());
|
||||
if (key == JSProto_Null)
|
||||
continue;
|
||||
MOZ_ASSERT(key == JSProto_Object || key == JSProto_Array ||
|
||||
key == JSProto_Function || key == JSProto_RegExp ||
|
||||
key == JSProto_Iterator);
|
||||
|
||||
JSObject* newProto = GetBuiltinPrototypePure(global, key);
|
||||
MOZ_ASSERT(newProto);
|
||||
|
||||
group->setProtoUnchecked(TaggedProto(newProto));
|
||||
}
|
||||
|
||||
// Move the parsed script and all its contents into the desired compartment.
|
||||
gc::MergeCompartments(parseTask->cx->compartment(), cx->compartment());
|
||||
if (!parseTask->finish(cx))
|
||||
return nullptr;
|
||||
|
||||
@ -988,6 +956,50 @@ GlobalHelperThreadState::finishParseTask(JSContext* maybecx, JSRuntime* rt, void
|
||||
return script;
|
||||
}
|
||||
|
||||
void
|
||||
GlobalHelperThreadState::mergeParseTaskCompartment(JSRuntime* rt, ParseTask* parseTask,
|
||||
Handle<GlobalObject*> global,
|
||||
JSCompartment* dest)
|
||||
{
|
||||
// After we call LeaveParseTaskZone() it's not safe to GC until we have
|
||||
// finished merging the contents of the parse task's compartment into the
|
||||
// destination compartment. Finish any ongoing incremental GC first and
|
||||
// assert that no allocation can occur.
|
||||
gc::AutoFinishGC finishGC(rt);
|
||||
JS::AutoAssertNoAlloc noAlloc(rt);
|
||||
|
||||
LeaveParseTaskZone(rt, parseTask);
|
||||
|
||||
// Point the prototypes of any objects in the script's compartment to refer
|
||||
// to the corresponding prototype in the new compartment. This will briefly
|
||||
// create cross compartment pointers, which will be fixed by the
|
||||
// MergeCompartments call below.
|
||||
for (gc::ZoneCellIter iter(parseTask->cx->zone(), gc::AllocKind::OBJECT_GROUP);
|
||||
!iter.done();
|
||||
iter.next())
|
||||
{
|
||||
ObjectGroup* group = iter.get<ObjectGroup>();
|
||||
TaggedProto proto(group->proto());
|
||||
if (!proto.isObject())
|
||||
continue;
|
||||
|
||||
JSProtoKey key = JS::IdentifyStandardPrototype(proto.toObject());
|
||||
if (key == JSProto_Null)
|
||||
continue;
|
||||
MOZ_ASSERT(key == JSProto_Object || key == JSProto_Array ||
|
||||
key == JSProto_Function || key == JSProto_RegExp ||
|
||||
key == JSProto_Iterator);
|
||||
|
||||
JSObject* newProto = GetBuiltinPrototypePure(global, key);
|
||||
MOZ_ASSERT(newProto);
|
||||
|
||||
group->setProtoUnchecked(TaggedProto(newProto));
|
||||
}
|
||||
|
||||
// Move the parsed script and all its contents into the desired compartment.
|
||||
gc::MergeCompartments(parseTask->cx->compartment(), dest);
|
||||
}
|
||||
|
||||
void
|
||||
HelperThread::destroy()
|
||||
{
|
||||
|
@ -228,6 +228,9 @@ class GlobalHelperThreadState
|
||||
}
|
||||
|
||||
JSScript* finishParseTask(JSContext* maybecx, JSRuntime* rt, void* token);
|
||||
void mergeParseTaskCompartment(JSRuntime* rt, ParseTask* parseTask,
|
||||
Handle<GlobalObject*> global,
|
||||
JSCompartment* dest);
|
||||
bool compressionInProgress(SourceCompressionTask* task);
|
||||
SourceCompressionTask* compressionTaskForSource(ScriptSource* ss);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user