author | Jon Coppeard <jcoppeard@mozilla.com> |
Tue, 17 Apr 2018 08:44:56 +0200 | |
changeset 414071 | 12337456bdd9cefdc8663d0c1fc1c1040247c616 |
parent 414070 | 0f26c7b0aa7d9a4ef77bb4819e53c46d663e88b8 |
child 414072 | de5cfd97ac491f80740ccd4822d5bf5119573e46 |
push id | 33858 |
push user | ncsoregi@mozilla.com |
push date | Tue, 17 Apr 2018 21:55:44 +0000 |
treeherder | mozilla-central@d6eb5597d744 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | sfink |
bugs | 1453028 |
milestone | 61.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
js/src/gc/GC.cpp | file | annotate | diff | comparison | revisions | |
js/src/gc/GCEnum.h | file | annotate | diff | comparison | revisions | |
js/src/gc/GCRuntime.h | file | annotate | diff | comparison | revisions |
--- a/js/src/gc/GC.cpp +++ b/js/src/gc/GC.cpp @@ -1015,40 +1015,44 @@ GCRuntime::getZealBits(uint32_t* zealBit } const char* gc::ZealModeHelpText = " Specifies how zealous the garbage collector should be. Some of these modes can\n" " be set simultaneously, by passing multiple level options, e.g. \"2;4\" will activate\n" " both modes 2 and 4. Modes can be specified by name or number.\n" " \n" " Values:\n" - " 0: (None) Normal amount of collection (resets all modes)\n" - " 1: (RootsChange) Collect when roots are added or removed\n" - " 2: (Alloc) Collect when every N allocations (default: 100)\n" - " 4: (VerifierPre) Verify pre write barriers between instructions\n" - " 7: (GenerationalGC) Collect the nursery every N nursery allocations\n" - " 8: (IncrementalRootsThenFinish) Incremental GC in two slices: 1) mark roots 2) finish collection\n" - " 9: (IncrementalMarkAllThenFinish) Incremental GC in two slices: 1) mark all 2) new marking and finish\n" - " 10: (IncrementalMultipleSlices) Incremental GC in multiple slices\n" - " 11: (IncrementalMarkingValidator) Verify incremental marking\n" - " 12: (ElementsBarrier) Always use the individual element post-write barrier, regardless of elements size\n" - " 13: (CheckHashTablesOnMinorGC) Check internal hashtables on minor GC\n" - " 14: (Compact) Perform a shrinking collection every N allocations\n" - " 15: (CheckHeapAfterGC) Walk the heap to check its integrity after every GC\n" - " 16: (CheckNursery) Check nursery integrity on minor GC\n" - " 17: (IncrementalSweepThenFinish) Incremental GC in two slices: 1) start sweeping 2) finish collection\n" - " 18: (CheckGrayMarking) Check gray marking invariants after every GC\n"; + " 0: (None) Normal amount of collection (resets all modes)\n" + " 1: (RootsChange) Collect when roots are added or removed\n" + " 2: (Alloc) Collect when every N allocations (default: 100)\n" + " 4: (VerifierPre) Verify pre write barriers between instructions\n" + " 7: (GenerationalGC) Collect the nursery every N nursery allocations\n" + " 8: (YieldBeforeMarking) Incremental GC in two slices that yields between\n" + " the root marking and marking phases\n" + " 9: (YieldBeforeSweeping) Incremental GC in two slices that yields between\n" + " the marking and sweeping phases\n" + " 10: (IncrementalMultipleSlices) Incremental GC in many slices\n" + " 11: (IncrementalMarkingValidator) Verify incremental marking\n" + " 12: (ElementsBarrier) Use the individual element post-write barrier\n" + " regardless of elements size\n" + " 13: (CheckHashTablesOnMinorGC) Check internal hashtables on minor GC\n" + " 14: (Compact) Perform a shrinking collection every N allocations\n" + " 15: (CheckHeapAfterGC) Walk the heap to check its integrity after every GC\n" + " 16: (CheckNursery) Check nursery integrity on minor GC\n" + " 17: (YieldBeforeSweepingAtoms) Incremental GC in two slices that yields\n" + " before sweeping the atoms table\n" + " 18: (CheckGrayMarking) Check gray marking invariants after every GC\n"; // The set of zeal modes that control incremental slices. These modes are // mutually exclusive. static const mozilla::EnumSet<ZealMode> IncrementalSliceZealModes = { - ZealMode::IncrementalRootsThenFinish, - ZealMode::IncrementalMarkAllThenFinish, + ZealMode::YieldBeforeMarking, + ZealMode::YieldBeforeSweeping, ZealMode::IncrementalMultipleSlices, - ZealMode::IncrementalSweepThenFinish + ZealMode::YieldBeforeSweepingAtoms }; void GCRuntime::setZeal(uint8_t zeal, uint32_t frequency) { MOZ_ASSERT(zeal <= unsigned(ZealMode::Limit)); if (verifyPreData) @@ -4982,19 +4986,19 @@ GCRuntime::groupZonesForSweeping(JS::gcr JSContext* cx = rt->mainContextFromOwnThread(); Zone* maybeAtomsZone = atomsZone->wasGCStarted() ? atomsZone.ref() : nullptr; ZoneComponentFinder finder(cx->nativeStackLimit[JS::StackForSystemCode], maybeAtomsZone); if (!isIncremental || !findInterZoneEdges()) finder.useOneComponent(); #ifdef JS_GC_ZEAL - // Use one component for IncrementalSweepThenFinish zeal mode. + // Use one component for YieldBeforeSweepingAtoms zeal mode. if (isIncremental && reason == JS::gcreason::DEBUG_GC && - hasZealMode(ZealMode::IncrementalSweepThenFinish)) + hasZealMode(ZealMode::YieldBeforeSweepingAtoms)) { finder.useOneComponent(); } #endif for (GCZonesIter zone(rt); !zone.done(); zone.next()) { MOZ_ASSERT(zone->isGCMarking()); finder.addNode(zone); @@ -5736,17 +5740,17 @@ GCRuntime::maybeYieldForSweepingZeal(Fre { /* * Check whether we need to yield for GC zeal. We always yield when running * in incremental multi-slice zeal mode so RunDebugGC can reset the slice * budget. */ if (isIncremental && useZeal && initialState != State::Sweep && (hasZealMode(ZealMode::IncrementalMultipleSlices) || - hasZealMode(ZealMode::IncrementalSweepThenFinish))) + hasZealMode(ZealMode::YieldBeforeSweepingAtoms))) { return NotFinished; } return Finished; } #endif @@ -6982,20 +6986,17 @@ GCRuntime::incrementalCollectSlice(Slice #endif MOZ_ASSERT_IF(isIncrementalGCInProgress(), isIncremental); if (isIncrementalGCInProgress() && budget.isUnlimited()) changeToNonIncrementalGC(); isIncremental = !budget.isUnlimited(); - if (useZeal && (hasZealMode(ZealMode::IncrementalRootsThenFinish) || - hasZealMode(ZealMode::IncrementalMarkAllThenFinish) || - hasZealMode(ZealMode::IncrementalSweepThenFinish))) - { + if (useZeal && hasIncrementalTwoSliceZealMode()) { /* * Yields between slices occurs at predetermined points in these modes; * the budget is not used. */ budget.makeUnlimited(); } switch (incrementalState) { @@ -7016,17 +7017,17 @@ GCRuntime::incrementalCollectSlice(Slice return; } if (!destroyingRuntime) pushZealSelectedObjects(); incrementalState = State::Mark; - if (isIncremental && useZeal && hasZealMode(ZealMode::IncrementalRootsThenFinish)) + if (isIncremental && useZeal && hasZealMode(ZealMode::YieldBeforeMarking)) break; MOZ_FALLTHROUGH; case State::Mark: AutoGCRooter::traceAllWrappers(rt->mainContextFromOwnThread(), &marker); /* If we needed delayed marking for gray roots, then collect until done. */ @@ -7042,26 +7043,26 @@ GCRuntime::incrementalCollectSlice(Slice MOZ_ASSERT(marker.isDrained()); /* * In incremental GCs where we have already performed more than once * slice we yield after marking with the aim of starting the sweep in * the next slice, since the first slice of sweeping can be expensive. * * This is modified by the various zeal modes. We don't yield in - * IncrementalRootsThenFinish mode and we always yield in - * IncrementalMarkAllThenFinish mode. + * YieldBeforeMarking mode and we always yield in YieldBeforeSweeping + * mode. * * We will need to mark anything new on the stack when we resume, so * we stay in Mark state. */ if (!lastMarkSlice && isIncremental && ((initialState == State::Mark && - !(useZeal && hasZealMode(ZealMode::IncrementalRootsThenFinish))) || - (useZeal && hasZealMode(ZealMode::IncrementalMarkAllThenFinish)))) + !(useZeal && hasZealMode(ZealMode::YieldBeforeMarking))) || + (useZeal && hasZealMode(ZealMode::YieldBeforeSweeping)))) { lastMarkSlice = true; break; } incrementalState = State::Sweep; beginSweepPhase(reason, session); @@ -8062,53 +8063,47 @@ GCRuntime::runDebugGC() return; if (hasZealMode(ZealMode::GenerationalGC)) return minorGC(JS::gcreason::DEBUG_GC); PrepareForDebugGC(rt); auto budget = SliceBudget::unlimited(); - if (hasZealMode(ZealMode::IncrementalRootsThenFinish) || - hasZealMode(ZealMode::IncrementalMarkAllThenFinish) || - hasZealMode(ZealMode::IncrementalMultipleSlices) || - hasZealMode(ZealMode::IncrementalSweepThenFinish)) - { + if (hasZealMode(ZealMode::IncrementalMultipleSlices)) { + /* + * Start with a small slice limit and double it every slice. This + * ensure that we get multiple slices, and collection runs to + * completion. + */ + if (!isIncrementalGCInProgress()) + incrementalLimit = zealFrequency / 2; + else + incrementalLimit *= 2; + budget = SliceBudget(WorkBudget(incrementalLimit)); + js::gc::State initialState = incrementalState; - if (hasZealMode(ZealMode::IncrementalMultipleSlices)) { - /* - * Start with a small slice limit and double it every slice. This - * ensure that we get multiple slices, and collection runs to - * completion. - */ - if (!isIncrementalGCInProgress()) - incrementalLimit = zealFrequency / 2; - else - incrementalLimit *= 2; - budget = SliceBudget(WorkBudget(incrementalLimit)); - } else { - // This triggers incremental GC but is actually ignored by IncrementalMarkSlice. - budget = SliceBudget(WorkBudget(1)); - } - if (!isIncrementalGCInProgress()) invocationKind = GC_SHRINK; collect(false, budget, JS::gcreason::DEBUG_GC); - /* - * For multi-slice zeal, reset the slice size when we get to the sweep - * or compact phases. - */ - if (hasZealMode(ZealMode::IncrementalMultipleSlices)) { - if ((initialState == State::Mark && incrementalState == State::Sweep) || - (initialState == State::Sweep && incrementalState == State::Compact)) - { - incrementalLimit = zealFrequency / 2; - } + /* Reset the slice size when we get to the sweep or compact phases. */ + if ((initialState == State::Mark && incrementalState == State::Sweep) || + (initialState == State::Sweep && incrementalState == State::Compact)) + { + incrementalLimit = zealFrequency / 2; } + } else if (hasIncrementalTwoSliceZealMode()) { + // These modes trigger incremental GC that happens in two slices and the + // supplied budget is ignored by incrementalCollectSlice. + budget = SliceBudget(WorkBudget(1)); + + if (!isIncrementalGCInProgress()) + invocationKind = GC_NORMAL; + collect(false, budget, JS::gcreason::DEBUG_GC); } else if (hasZealMode(ZealMode::Compact)) { gc(GC_SHRINK, JS::gcreason::DEBUG_GC); } else { gc(GC_NORMAL, JS::gcreason::DEBUG_GC); } #endif }
--- a/js/src/gc/GCEnum.h +++ b/js/src/gc/GCEnum.h @@ -57,26 +57,26 @@ enum class AbortReason { #undef MAKE_REASON }; #define JS_FOR_EACH_ZEAL_MODE(D) \ D(RootsChange, 1) \ D(Alloc, 2) \ D(VerifierPre, 4) \ D(GenerationalGC, 7) \ - D(IncrementalRootsThenFinish, 8) \ - D(IncrementalMarkAllThenFinish, 9) \ + D(YieldBeforeMarking, 8) \ + D(YieldBeforeSweeping, 9) \ D(IncrementalMultipleSlices, 10) \ D(IncrementalMarkingValidator, 11) \ D(ElementsBarrier, 12) \ D(CheckHashTablesOnMinorGC, 13) \ D(Compact, 14) \ D(CheckHeapAfterGC, 15) \ D(CheckNursery, 16) \ - D(IncrementalSweepThenFinish, 17) \ + D(YieldBeforeSweepingAtoms, 17) \ D(CheckGrayMarking, 18) enum class ZealMode { #define ZEAL_MODE(name, value) name = value, JS_FOR_EACH_ZEAL_MODE(ZEAL_MODE) #undef ZEAL_MODE Count, Limit = Count - 1
--- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -225,16 +225,17 @@ class GCRuntime MOZ_MUST_USE bool init(uint32_t maxbytes, uint32_t maxNurseryBytes); void finishRoots(); void finish(); inline bool hasZealMode(ZealMode mode); inline void clearZealMode(ZealMode mode); inline bool upcomingZealousGC(); inline bool needZealousGC(); + inline bool hasIncrementalTwoSliceZealMode(); MOZ_MUST_USE bool addRoot(Value* vp, const char* name); void removeRoot(Value* vp); void setMarkStackLimit(size_t limit, AutoLockGC& lock); MOZ_MUST_USE bool setParameter(JSGCParamKey key, uint32_t value, AutoLockGC& lock); void resetParameter(JSGCParamKey key, AutoLockGC& lock); uint32_t getParameter(JSGCParamKey key, const AutoLockGC& lock); @@ -1021,31 +1022,40 @@ GCRuntime::upcomingZealousGC() { return nextScheduled == 1; } inline bool GCRuntime::needZealousGC() { if (nextScheduled > 0 && --nextScheduled == 0) { if (hasZealMode(ZealMode::Alloc) || hasZealMode(ZealMode::GenerationalGC) || - hasZealMode(ZealMode::IncrementalRootsThenFinish) || - hasZealMode(ZealMode::IncrementalMarkAllThenFinish) || + hasZealMode(ZealMode::YieldBeforeMarking) || + hasZealMode(ZealMode::YieldBeforeSweeping) || hasZealMode(ZealMode::IncrementalMultipleSlices) || hasZealMode(ZealMode::Compact) || - hasZealMode(ZealMode::IncrementalSweepThenFinish)) + hasZealMode(ZealMode::YieldBeforeSweepingAtoms)) { nextScheduled = zealFrequency; } return true; } return false; } + +inline bool +GCRuntime::hasIncrementalTwoSliceZealMode() { + return hasZealMode(ZealMode::YieldBeforeMarking) || + hasZealMode(ZealMode::YieldBeforeSweeping) || + hasZealMode(ZealMode::YieldBeforeSweepingAtoms); +} + #else inline bool GCRuntime::hasZealMode(ZealMode mode) { return false; } inline void GCRuntime::clearZealMode(ZealMode mode) { } inline bool GCRuntime::upcomingZealousGC() { return false; } inline bool GCRuntime::needZealousGC() { return false; } +inline bool GCRuntime::hasIncrementalTwoSliceZealMode() { return false; } #endif } /* namespace gc */ } /* namespace js */ #endif