diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index f7cacb7c2ff..3c1706f4657 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -321,9 +321,8 @@ class GCRuntime bool isGcNeeded() { return isNeeded; } - double computeHeapGrowthFactor(size_t lastBytes) const; - size_t computeTriggerBytes(double growthFactor, size_t lastBytes, - JSGCInvocationKind gckind) const; + double computeHeapGrowthFactor(size_t lastBytes); + size_t computeTriggerBytes(double growthFactor, size_t lastBytes, JSGCInvocationKind gckind); size_t allocationThreshold() { return allocThreshold; } JSGCMode gcMode() const { return mode; } @@ -394,7 +393,7 @@ class GCRuntime bool releaseObservedTypes(); void endSweepingZoneGroup(); bool sweepPhase(SliceBudget &sliceBudget); - void endSweepPhase(bool lastGC); + void endSweepPhase(JSGCInvocationKind gckind, bool lastGC); void sweepZones(FreeOp *fop, bool lastGC); void decommitArenasFromAvailableList(Chunk **availableListHeadp); void decommitArenas(); @@ -514,9 +513,6 @@ class GCRuntime /* Whether all compartments are being collected in first GC slice. */ bool isFull; - /* The kind of the last collection. */ - JSGCInvocationKind lastKind; - /* The reason that an interrupt-triggered GC should be called. */ JS::gcreason::Reason triggerReason; diff --git a/js/src/gc/Zone.cpp b/js/src/gc/Zone.cpp index 8581558447c..07c98e0542e 100644 --- a/js/src/gc/Zone.cpp +++ b/js/src/gc/Zone.cpp @@ -31,7 +31,6 @@ JS::Zone::Zone(JSRuntime *rt) gcMallocBytes(0), gcMallocGCTriggered(false), gcBytes(0), - gcBytesAfterGC(0), gcTriggerBytes(0), data(nullptr), isSystem(false), diff --git a/js/src/gc/Zone.h b/js/src/gc/Zone.h index 88a41af200d..648f3194a09 100644 --- a/js/src/gc/Zone.h +++ b/js/src/gc/Zone.h @@ -106,6 +106,7 @@ struct Zone : public JS::shadow::Zone, size_t *baselineStubsOptimized); void setGCLastBytes(size_t lastBytes, js::JSGCInvocationKind gckind); + void reduceGCTriggerBytes(size_t amount); void resetGCMallocBytes(); void setGCMaxMallocBytes(size_t value); @@ -247,12 +248,8 @@ struct Zone : public JS::shadow::Zone, // updated by both the main and GC helper threads. mozilla::Atomic gcBytes; - // The number of bytes allocated in the GC heap for this zone after the last GC. - size_t gcBytesAfterGC; - - // GC trigger threshold for allocations on the GC heap. It is updated by - // both the main and GC helper threads. - mozilla::Atomic gcTriggerBytes; + // GC trigger threshold for allocations on the GC heap. + size_t gcTriggerBytes; // Per-zone data for use by an embedder. void *data; diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 4cd6a90b2f7..2a352f95ac2 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -985,7 +985,7 @@ Chunk::releaseArena(ArenaHeader *aheader) JS_ASSERT(rt->gc.bytesAllocated() >= ArenaSize); JS_ASSERT(zone->gcBytes >= ArenaSize); if (rt->gc.isBackgroundSweeping()) - zone->gcBytesAfterGC -= ArenaSize; + zone->reduceGCTriggerBytes(zone->gcHeapGrowthFactor * ArenaSize); rt->gc.updateBytesAllocated(-ArenaSize); zone->gcBytes -= ArenaSize; @@ -1695,8 +1695,7 @@ GCRuntime::onTooMuchMalloc() } size_t -GCRuntime::computeTriggerBytes(double growthFactor, size_t lastBytes, - JSGCInvocationKind gckind) const +GCRuntime::computeTriggerBytes(double growthFactor, size_t lastBytes, JSGCInvocationKind gckind) { size_t base = gckind == GC_SHRINK ? lastBytes : Max(lastBytes, allocThreshold); double trigger = double(base) * growthFactor; @@ -1704,7 +1703,7 @@ GCRuntime::computeTriggerBytes(double growthFactor, size_t lastBytes, } double -GCRuntime::computeHeapGrowthFactor(size_t lastBytes) const +GCRuntime::computeHeapGrowthFactor(size_t lastBytes) { /* * The heap growth factor depends on the heap size after a GC and the GC frequency. @@ -1746,11 +1745,22 @@ GCRuntime::computeHeapGrowthFactor(size_t lastBytes) const void Zone::setGCLastBytes(size_t lastBytes, JSGCInvocationKind gckind) { - const GCRuntime &gc = runtimeFromAnyThread()->gc; + GCRuntime &gc = runtimeFromMainThread()->gc; gcHeapGrowthFactor = gc.computeHeapGrowthFactor(lastBytes); gcTriggerBytes = gc.computeTriggerBytes(gcHeapGrowthFactor, lastBytes, gckind); } +void +Zone::reduceGCTriggerBytes(size_t amount) +{ + JS_ASSERT(amount > 0); + JS_ASSERT(gcTriggerBytes >= amount); + GCRuntime &gc = runtimeFromAnyThread()->gc; + if (gcTriggerBytes - amount < gc.allocationThreshold() * gcHeapGrowthFactor) + return; + gcTriggerBytes -= amount; +} + Allocator::Allocator(Zone *zone) : zone_(zone) {} @@ -2580,15 +2590,6 @@ GCRuntime::sweepBackgroundThings(bool onBackgroundThread) } } - if (onBackgroundThread) { - /* - * Update zone triggers a second time now we have completely finished - * sweeping these zones. - */ - for (Zone *zone = sweepingZones; zone; zone = zone->gcNextGraphNode) - zone->setGCLastBytes(zone->gcBytesAfterGC, lastKind); - } - sweepingZones = nullptr; } @@ -4386,7 +4387,7 @@ GCRuntime::sweepPhase(SliceBudget &sliceBudget) } void -GCRuntime::endSweepPhase(bool lastGC) +GCRuntime::endSweepPhase(JSGCInvocationKind gckind, bool lastGC) { gcstats::AutoPhase ap(stats, gcstats::PHASE_SWEEP); FreeOp fop(rt, sweepOnBackgroundThread); @@ -4459,7 +4460,7 @@ GCRuntime::endSweepPhase(bool lastGC) * Expire needs to unlock it for other callers. */ AutoLockGC lock(rt); - expireChunksAndArenas(lastKind == GC_SHRINK); + expireChunksAndArenas(gckind == GC_SHRINK); } } @@ -4502,10 +4503,9 @@ GCRuntime::endSweepPhase(bool lastGC) lastGCTime + highFrequencyTimeThreshold * PRMJ_USEC_PER_MSEC > currentTime; for (ZonesIter zone(rt, WithAtoms); !zone.done(); zone.next()) { - zone->setGCLastBytes(zone->gcBytes, lastKind); + zone->setGCLastBytes(zone->gcBytes, gckind); if (zone->isCollecting()) { JS_ASSERT(zone->isGCFinished()); - zone->gcBytesAfterGC = zone->gcBytes; zone->setGCState(Zone::NoGC); } @@ -4787,8 +4787,6 @@ GCRuntime::incrementalCollectSlice(int64_t budget, JS_ASSERT_IF(incrementalState != NO_INCREMENTAL, isIncremental); isIncremental = budget != SliceBudget::Unlimited; - lastKind = gckind; - if (zeal == ZealIncrementalRootsThenFinish || zeal == ZealIncrementalMarkAllThenFinish) { /* * Yields between slices occurs at predetermined points in these modes; @@ -4876,7 +4874,7 @@ GCRuntime::incrementalCollectSlice(int64_t budget, if (!finished) break; - endSweepPhase(lastGC); + endSweepPhase(gckind, lastGC); if (sweepOnBackgroundThread) helperState.startBackgroundSweep(gckind == GC_SHRINK);