author | Paul Bone <pbone@mozilla.com> |
Fri, 21 Jul 2017 14:34:46 +1000 | |
changeset 419559 | 974fd5c79451c5bd35ceafca95c2ef2563fd3bd1 |
parent 419558 | 30c0fb1d099700f028316ee30ce7285134dcd99c |
child 419560 | 3db31de3ac85339bca02e56c11cbe74c566f2340 |
push id | 7566 |
push user | mtabara@mozilla.com |
push date | Wed, 02 Aug 2017 08:25:16 +0000 |
treeherder | mozilla-beta@86913f512c3c [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | sfink |
bugs | 1380768 |
milestone | 56.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
|
--- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -2593,18 +2593,28 @@ SetMemoryHighWaterMarkPrefChangedCallbac highwatermark * 1024L * 1024L); } static void SetMemoryMaxPrefChangedCallback(const char* aPrefName, void* aClosure) { int32_t pref = Preferences::GetInt(aPrefName, -1); // handle overflow and negative pref values - uint32_t max = (pref <= 0 || pref >= 0x1000) ? -1 : (uint32_t)pref * 1024 * 1024; - SetGCParameter(JSGC_MAX_BYTES, max); + CheckedInt<uint32_t> max = CheckedInt<uint32_t>(pref) * 1024 * 1024; + SetGCParameter(JSGC_MAX_BYTES, max.isValid() ? max.value() : -1); +} + +static void +SetMemoryNurseryMaxPrefChangedCallback(const char* aPrefName, void* aClosure) +{ + int32_t pref = Preferences::GetInt(aPrefName, -1); + // handle overflow and negative pref values + CheckedInt<uint32_t> max = CheckedInt<uint32_t>(pref) * 1024; + SetGCParameter(JSGC_MAX_NURSERY_BYTES, + max.isValid() ? max.value() : JS::DefaultNurseryBytes); } static void SetMemoryGCModePrefChangedCallback(const char* aPrefName, void* aClosure) { bool enableZoneGC = Preferences::GetBool("javascript.options.mem.gc_per_zone"); bool enableIncrementalGC = Preferences::GetBool("javascript.options.mem.gc_incremental"); JSGCMode mode; @@ -2787,16 +2797,18 @@ nsJSContext::EnsureStatics() JS::SetAsyncTaskCallbacks(jsapi.cx(), StartAsyncTaskCallback, FinishAsyncTaskCallback); // Set these global xpconnect options... Preferences::RegisterCallbackAndCall(SetMemoryHighWaterMarkPrefChangedCallback, "javascript.options.mem.high_water_mark"); Preferences::RegisterCallbackAndCall(SetMemoryMaxPrefChangedCallback, "javascript.options.mem.max"); + Preferences::RegisterCallbackAndCall(SetMemoryNurseryMaxPrefChangedCallback, + "javascript.options.mem.nursery.max_kb"); Preferences::RegisterCallbackAndCall(SetMemoryGCModePrefChangedCallback, "javascript.options.mem.gc_per_zone"); Preferences::RegisterCallbackAndCall(SetMemoryGCModePrefChangedCallback, "javascript.options.mem.gc_incremental"); Preferences::RegisterCallbackAndCall(SetMemoryGCSliceTimePrefChangedCallback,
--- a/js/public/HeapAPI.h +++ b/js/public/HeapAPI.h @@ -96,17 +96,21 @@ AssertGCThingHasType(js::gc::Cell* cell, MOZ_ALWAYS_INLINE bool IsInsideNursery(const js::gc::Cell* cell); } /* namespace gc */ } /* namespace js */ namespace JS { struct Zone; -/* Default size for the generational nursery in bytes. */ +/* + * Default size for the generational nursery in bytes. + * This is the initial nursery size, when running in the browser this is + * updated by JS_SetGCParameter(). + */ const uint32_t DefaultNurseryBytes = 16 * js::gc::ChunkSize; /* Default maximum heap size in bytes to pass to JS_NewContext(). */ const uint32_t DefaultHeapMaxBytes = 32 * 1024 * 1024; namespace shadow { struct Zone
--- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -135,17 +135,21 @@ class GCSchedulingTunables /* * Soft limit on the number of bytes we are allowed to allocate in the GC * heap. Attempts to allocate gcthings over this limit will return null and * subsequently invoke the standard OOM machinery, independent of available * physical memory. */ UnprotectedData<size_t> gcMaxBytes_; - /* Maximum nursery size for each zone group. */ + /* + * Maximum nursery size for each zone group. + * Initially DefaultNurseryBytes and can be set by + * javascript.options.mem.nursery.max_kb + */ ActiveThreadData<size_t> gcMaxNurseryBytes_; /* * The base value used to compute zone->trigger.gcBytes(). When * usage.gcBytes() surpasses threshold.gcBytes() for a zone, the zone may * be scheduled for a GC, depending on the exact circumstances. */ ActiveThreadOrGCTaskData<size_t> gcZoneAllocThresholdBase_;
--- a/js/src/gc/Nursery.cpp +++ b/js/src/gc/Nursery.cpp @@ -641,16 +641,21 @@ js::Nursery::collect(JS::gcreason::Reaso } endProfile(ProfileKey::Pretenure); // We ignore gcMaxBytes when allocating for minor collection. However, if we // overflowed, we disable the nursery. The next time we allocate, we'll fail // because gcBytes >= gcMaxBytes. if (rt->gc.usage.gcBytes() >= rt->gc.tunables.gcMaxBytes()) disable(); + // Disable the nursery if the user changed the configuration setting. The + // nursery can only be re-enabled by resetting the configurationa and + // restarting firefox. + if (maxNurseryChunks_ == 0) + disable(); endProfile(ProfileKey::Total); minorGcCount_++; TimeDuration totalTime = profileDurations_[ProfileKey::Total]; rt->addTelemetry(JS_TELEMETRY_GC_MINOR_US, totalTime.ToMicroseconds()); rt->addTelemetry(JS_TELEMETRY_GC_MINOR_REASON, reason); if (totalTime.ToMilliseconds() > 1.0) @@ -919,46 +924,67 @@ js::Nursery::setStartPosition() currentStartPosition_ = position(); } void js::Nursery::maybeResizeNursery(JS::gcreason::Reason reason, double promotionRate) { static const double GrowThreshold = 0.05; static const double ShrinkThreshold = 0.01; + unsigned newMaxNurseryChunks; // Shrink the nursery to its minimum size of we ran out of memory or // received a memory pressure event. if (gc::IsOOMReason(reason)) { minimizeAllocableSpace(); return; } +#ifdef JS_GC_ZEAL + // This zeal mode disabled nursery resizing. + if (runtime()->hasZealMode(ZealMode::GenerationalGC)) + return; +#endif + + newMaxNurseryChunks = runtime()->gc.tunables.gcMaxNurseryBytes() >> ChunkShift; + if (newMaxNurseryChunks != maxNurseryChunks_) { + maxNurseryChunks_ = newMaxNurseryChunks; + /* The configured maximum nursery size is changing */ + int extraChunks = numChunks() - newMaxNurseryChunks; + if (extraChunks > 0) { + /* We need to shrink the nursery */ + shrinkAllocableSpace(extraChunks); + + previousPromotionRate_ = promotionRate; + return; + } + } + if (promotionRate > GrowThreshold) growAllocableSpace(); else if (promotionRate < ShrinkThreshold && previousPromotionRate_ < ShrinkThreshold) - shrinkAllocableSpace(); + shrinkAllocableSpace(1); previousPromotionRate_ = promotionRate; } void js::Nursery::growAllocableSpace() { updateNumChunks(Min(numChunks() * 2, maxNurseryChunks_)); } void -js::Nursery::shrinkAllocableSpace() +js::Nursery::shrinkAllocableSpace(unsigned removeNumChunks) { #ifdef JS_GC_ZEAL if (runtime()->hasZealMode(ZealMode::GenerationalGC)) return; #endif - updateNumChunks(Max(numChunks() - 1, 1u)); + updateNumChunks(Max(numChunks() - removeNumChunks, 1u)); } void js::Nursery::minimizeAllocableSpace() { #ifdef JS_GC_ZEAL if (runtime()->hasZealMode(ZealMode::GenerationalGC)) return;
--- a/js/src/gc/Nursery.h +++ b/js/src/gc/Nursery.h @@ -463,17 +463,17 @@ class Nursery */ void sweep(); void sweepDictionaryModeObjects(); /* Change the allocable space provided by the nursery. */ void maybeResizeNursery(JS::gcreason::Reason reason, double promotionRate); void growAllocableSpace(); - void shrinkAllocableSpace(); + void shrinkAllocableSpace(unsigned removeNumChunks); void minimizeAllocableSpace(); /* Profile recording and printing. */ void maybeClearProfileDurations(); void startProfile(ProfileKey key); void endProfile(ProfileKey key); static void printProfileDurations(const ProfileDurations& times);
--- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -1431,16 +1431,17 @@ pref("javascript.options.jit.full_debug_ // fail. pref("javascript.options.discardSystemSource", false); // This preference limits the memory usage of javascript. // If you want to change these values for your device, // please find Bug 417052 comment 17 and Bug 456721 // Comment 32 and Bug 613551. pref("javascript.options.mem.high_water_mark", 128); pref("javascript.options.mem.max", -1); +pref("javascript.options.mem.nursery.max_kb", -1); pref("javascript.options.mem.gc_per_zone", true); pref("javascript.options.mem.gc_incremental", true); pref("javascript.options.mem.gc_incremental_slice_ms", 5); pref("javascript.options.mem.gc_compacting", true); pref("javascript.options.mem.log", false); pref("javascript.options.mem.notify", false); pref("javascript.options.gc_on_memory_pressure", true); pref("javascript.options.compact_on_user_inactive", true);