diff --git a/js/src/gc/RootMarking.cpp b/js/src/gc/RootMarking.cpp index 87ea63c3611..54110fc9137 100644 --- a/js/src/gc/RootMarking.cpp +++ b/js/src/gc/RootMarking.cpp @@ -731,9 +731,13 @@ js::gc::MarkRuntime(JSTracer *trc, bool useSavedRoots) if (IS_GC_MARKING_TRACER(trc) && !c->isCollecting()) continue; - if (IS_GC_MARKING_TRACER(trc) && (c->activeAnalysis || c->isPreservingCode())) { - gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_MARK_TYPES); - c->markTypes(trc); + if (IS_GC_MARKING_TRACER(trc)) { + if ((c->activeAnalysis || c->isPreservingCode())) { + gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_MARK_TYPES); + c->markTypes(trc); + } else { + c->gcTypesMarked = false; + } } /* During a GC, these are treated as weak pointers. */ diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index c1efe24bd37..356db90ea5a 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -808,7 +808,6 @@ JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads) gcSweepPhase(0), gcSweepCompartment(NULL), gcSweepKindIndex(0), - gcAbortSweepAfterCurrentGroup(false), gcArenasAllocatedDuringSweep(NULL), #ifdef DEBUG gcMarkingValidator(NULL), diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index c0e592ef514..e78324bf3d8 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -730,7 +730,6 @@ struct JSRuntime : js::RuntimeFriendFields int gcSweepPhase; JSCompartment *gcSweepCompartment; int gcSweepKindIndex; - bool gcAbortSweepAfterCurrentGroup; /* * List head of arenas allocated during the sweep phase. diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index 449886f98c5..756b11463e9 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -573,6 +573,8 @@ JSCompartment::markTypes(JSTracer *trc) MarkTypeObjectRoot(trc, &type, "mark_types_scan"); JS_ASSERT(type == i.get()); } + + gcTypesMarked = true; } void diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index a0a21b5084e..39f75b983e7 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -379,6 +379,12 @@ struct JSCompartment : private JS::shadow::Compartment, public js::gc::GraphNode /* This compartment's gray roots. */ js::Vector gcGrayRoots; + /* + * Whether type objects have been marked by markTypes(). This is used to + * determine whether they need to be swept. + */ + bool gcTypesMarked; + private: /* * Malloc counter to measure memory pressure for GC scheduling. It runs from diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 1e8e5a266f2..490b6978f4a 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -3098,9 +3098,6 @@ FindCompartmentGroups(JSRuntime *rt) rt->gcCompartmentGroupIndex = 0; } -static void -ResetGrayList(JSCompartment* comp); - static void GetNextCompartmentGroup(JSRuntime *rt) { @@ -3109,26 +3106,6 @@ GetNextCompartmentGroup(JSRuntime *rt) if (!rt->gcIsIncremental) ComponentFinder::mergeCompartmentGroups(rt->gcCurrentCompartmentGroup); - - if (rt->gcAbortSweepAfterCurrentGroup) { - /* - * Iterate over all compartments that haven't been swept yet and reset - * their state such that ther are no longer being collected. - */ - JS_ASSERT(!rt->gcIsIncremental); - for (GCCompartmentGroupIter c(rt); !c.done(); c.next()) { - JS_ASSERT(!c->gcNextGraphComponent); - JS_ASSERT(c->isGCMarking()); - c->setNeedsBarrier(false, JSCompartment::UpdateIon); - c->setGCState(JSCompartment::NoGC); - ArrayBufferObject::resetArrayBufferList(c); - ResetGrayList(c); - c->gcGrayRoots.clearAndFree(); - } - - rt->gcAbortSweepAfterCurrentGroup = false; - rt->gcCurrentCompartmentGroup = NULL; - } } /* @@ -3319,15 +3296,6 @@ RemoveFromGrayList(RawObject wrapper) return false; } -static void -ResetGrayList(JSCompartment* comp) -{ - RawObject src = comp->gcIncomingGrayPointers; - while (src) - src = NextIncomingCrossCompartmentPointer(src, true); - comp->gcIncomingGrayPointers = NULL; -} - void js::NotifyGCNukeWrapper(RawObject o) { @@ -3533,8 +3501,6 @@ BeginSweepPhase(JSRuntime *rt) * fail, rather than nest badly and leave the unmarked newborn to be swept. */ - JS_ASSERT(!rt->gcAbortSweepAfterCurrentGroup); - ComputeNonIncrementalMarkingForValidation(rt); gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP); @@ -3631,9 +3597,8 @@ EndSweepPhase(JSRuntime *rt, JSGCInvocationKind gckind, bool lastGC) /* * If we found any black->gray edges during marking, we completely clear the - * mark bits of all uncollected compartments, or if a reset has occured, - * compartments that will no longer be collected. This is safe, although it - * may prevent the cycle collector from collecting some dead objects. + * mark bits of all uncollected compartments. This is safe, although it may + * prevent the cycle collector from collecting some dead objects. */ if (rt->gcFoundBlackGrayEdges) { for (CompartmentsIter c(rt); !c.done(); c.next()) { @@ -3841,11 +3806,11 @@ ResetIncrementalGC(JSRuntime *rt, const char *reason) rt->gcMarker.stop(); for (GCCompartmentsIter c(rt); !c.done(); c.next()) { - JS_ASSERT(c->isGCMarking()); - c->setNeedsBarrier(false, JSCompartment::UpdateIon); - c->setGCState(JSCompartment::NoGC); - ArrayBufferObject::resetArrayBufferList(c); - ResetGrayList(c); + if (c->isGCMarking()) { + c->setNeedsBarrier(false, JSCompartment::UpdateIon); + c->setGCState(JSCompartment::NoGC); + ArrayBufferObject::resetArrayBufferList(c); + } } rt->gcIncrementalState = NO_INCREMENTAL; @@ -3856,13 +3821,21 @@ ResetIncrementalGC(JSRuntime *rt, const char *reason) } case SWEEP: - rt->gcMarker.reset(); - - for (CompartmentsIter c(rt); !c.done(); c.next()) + for (CompartmentsIter c(rt); !c.done(); c.next()) { c->scheduledForDestruction = false; - /* Finish sweeping the current compartment group, then abort. */ - rt->gcAbortSweepAfterCurrentGroup = true; + if (c->isGCMarking() && c->activeAnalysis && !c->gcTypesMarked) { + AutoCopyFreeListToArenas copy(rt); + gcstats::AutoPhase ap1(rt->gcStats, gcstats::PHASE_SWEEP); + gcstats::AutoPhase ap2(rt->gcStats, gcstats::PHASE_SWEEP_MARK); + gcstats::AutoPhase ap3(rt->gcStats, gcstats::PHASE_SWEEP_MARK_TYPES); + rt->gcIncrementalState = MARK_ROOTS; + c->markTypes(&rt->gcMarker); + rt->gcIncrementalState = SWEEP; + } + } + + /* If we had started sweeping then sweep to completion here. */ IncrementalCollectSlice(rt, SliceBudget::Unlimited, gcreason::RESET, GC_NORMAL); {