diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index e97fff18751..d50299ccccb 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -195,30 +195,23 @@ static const AllocKind FinalizePhaseIonCode[] = { FINALIZE_IONCODE }; -static const AllocKind FinalizePhaseShapes[] = { - FINALIZE_TYPE_OBJECT -}; - static const AllocKind* FinalizePhases[] = { FinalizePhaseStrings, FinalizePhaseScripts, - FinalizePhaseIonCode, - FinalizePhaseShapes + FinalizePhaseIonCode }; static const int FinalizePhaseCount = sizeof(FinalizePhases) / sizeof(AllocKind*); static const int FinalizePhaseLength[] = { sizeof(FinalizePhaseStrings) / sizeof(AllocKind), sizeof(FinalizePhaseScripts) / sizeof(AllocKind), - sizeof(FinalizePhaseIonCode) / sizeof(AllocKind), - sizeof(FinalizePhaseShapes) / sizeof(AllocKind) + sizeof(FinalizePhaseIonCode) / sizeof(AllocKind) }; static const gcstats::Phase FinalizePhaseStatsPhase[] = { gcstats::PHASE_SWEEP_STRING, gcstats::PHASE_SWEEP_SCRIPT, - gcstats::PHASE_SWEEP_IONCODE, - gcstats::PHASE_SWEEP_SHAPE + gcstats::PHASE_SWEEP_IONCODE }; /* @@ -241,7 +234,8 @@ static const AllocKind BackgroundPhaseStrings[] = { static const AllocKind BackgroundPhaseShapes[] = { FINALIZE_SHAPE, - FINALIZE_BASE_SHAPE + FINALIZE_BASE_SHAPE, + FINALIZE_TYPE_OBJECT }; static const AllocKind* BackgroundPhases[] = { @@ -1480,10 +1474,9 @@ ArenaLists::queueShapesForSweep(FreeOp *fop) { gcstats::AutoPhase ap(fop->runtime()->gcStats, gcstats::PHASE_SWEEP_SHAPE); - queueForForegroundSweep(fop, FINALIZE_TYPE_OBJECT); - queueForBackgroundSweep(fop, FINALIZE_SHAPE); queueForBackgroundSweep(fop, FINALIZE_BASE_SHAPE); + queueForBackgroundSweep(fop, FINALIZE_TYPE_OBJECT); } static void * @@ -4588,6 +4581,12 @@ JS::ShrinkGCBuffers(JSRuntime *rt) rt->gcHelperThread.startBackgroundShrink(); } +void +js::gc::FinishBackgroundFinalize(JSRuntime *rt) +{ + rt->gcHelperThread.waitBackgroundSweepEnd(); +} + AutoFinishGC::AutoFinishGC(JSRuntime *rt) { if (IsIncrementalGCInProgress(rt)) { @@ -4595,7 +4594,7 @@ AutoFinishGC::AutoFinishGC(JSRuntime *rt) FinishIncrementalGC(rt, gcreason::API); } - rt->gcHelperThread.waitBackgroundSweepEnd(); + gc::FinishBackgroundFinalize(rt); } AutoPrepareForTracing::AutoPrepareForTracing(JSRuntime *rt) diff --git a/js/src/jsgc.h b/js/src/jsgc.h index ded7db545af..38323c148d3 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -168,8 +168,8 @@ IsBackgroundFinalized(AllocKind kind) true, /* FINALIZE_OBJECT16_BACKGROUND */ false, /* FINALIZE_SCRIPT */ true, /* FINALIZE_SHAPE */ - true, /* FINALIZE_BASE_SHAPE */ - false, /* FINALIZE_TYPE_OBJECT */ + true, /* FINALIZE_BASE_SHAPE */ + true, /* FINALIZE_TYPE_OBJECT */ true, /* FINALIZE_SHORT_STRING */ true, /* FINALIZE_STRING */ false, /* FINALIZE_EXTERNAL_STRING */ @@ -334,6 +334,10 @@ struct ArenaLists { backgroundFinalizeState[kind] == BFS_JUST_FINISHED; } + bool needBackgroundFinalizeWait(AllocKind kind) const { + return backgroundFinalizeState[kind] != BFS_DONE; + } + /* * Return the free list back to the arena so the GC finalization will not * run the finalizers over unitialized bytes from free things. @@ -1185,6 +1189,10 @@ SetDeterministicGC(JSContext *cx, bool enabled); void SetValidateGC(JSContext *cx, bool enabled); +/* Wait for the background thread to finish sweeping if it is running. */ +void +FinishBackgroundFinalize(JSRuntime *rt); + const int ZealPokeValue = 1; const int ZealAllocValue = 2; const int ZealFrameGCValue = 3; diff --git a/js/src/jsgcinlines.h b/js/src/jsgcinlines.h index 802ffea24f1..dbaceacfe54 100644 --- a/js/src/jsgcinlines.h +++ b/js/src/jsgcinlines.h @@ -357,13 +357,18 @@ class CellIter : public CellIterImpl : lists(&comp->zone()->allocator.arenas), kind(kind) { + /* * We have a single-threaded runtime, so there's no need to protect * against other threads iterating or allocating. However, we do have - * background finalization; make sure people aren't using CellIter to - * walk such allocation kinds. + * background finalization; we have to wait for this to finish if it's + * currently active. */ - JS_ASSERT(!IsBackgroundFinalized(kind)); + if (IsBackgroundFinalized(kind) && + comp->zone()->allocator.arenas.needBackgroundFinalizeWait(kind)) + { + gc::FinishBackgroundFinalize(comp->rt); + } if (lists->isSynchronizedFreeList(kind)) { lists = NULL; } else {