Bug 800063 - Make GC_ALLOCATION_THRESHOLD dynamic. r=billm
authorGregor Wagner <anygregor@gmail.com>
Fri, 26 Oct 2012 16:06:19 -0700
changeset 111712 a32865b52f011804c5bfdd07fe5d08063f2ae1e9
parent 111711 d699695265af7113e43a19c75ca0a5b35499a0b6
child 111713 9c064c78d86aeb5b37cbd595484475bc150ee9ff
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersbillm
bugs800063
milestone19.0a1
Bug 800063 - Make GC_ALLOCATION_THRESHOLD dynamic. r=billm
b2g/app/b2g.js
dom/base/nsJSEnvironment.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jscntxt.h
js/src/jsgc.cpp
mobile/android/app/mobile.js
modules/libpref/src/init/all.js
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -514,16 +514,17 @@ pref("javascript.options.mem.log", false
 pref("javascript.options.mem.gc_incremental_slice_ms", 30);
 
 pref("javascript.options.mem.gc_high_frequency_heap_growth_max", 120);
 pref("javascript.options.mem.gc_high_frequency_heap_growth_min", 101);
 pref("javascript.options.mem.gc_high_frequency_high_limit_mb", 40);
 pref("javascript.options.mem.gc_high_frequency_low_limit_mb", 10);
 pref("javascript.options.mem.gc_low_frequency_heap_growth", 105);
 pref("javascript.options.mem.high_water_mark", 6);
+pref("javascript.options.mem.gc_allocation_threshold_mb", 3);
 
 // Show/Hide scrollbars when active/inactive
 pref("ui.showHideScrollbars", 1);
 
 // Enable the ProcessPriorityManager, and give processes with no visible
 // documents a 1s grace period before they're eligible to be marked as
 // background.
 pref("dom.ipc.processPriorityManager.enabled", true);
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -3948,16 +3948,20 @@ nsJSRuntime::Init()
                                  (void *)JSGC_HIGH_FREQUENCY_HIGH_LIMIT);
 
   Preferences::RegisterCallback(SetMemoryGCPrefChangedCallback,
                                 "javascript.options.mem.analysis_purge_mb",
                                 (void *)JSGC_ANALYSIS_PURGE_TRIGGER);
   SetMemoryGCPrefChangedCallback("javascript.options.mem.analysis_purge_mb",
                                  (void *)JSGC_ANALYSIS_PURGE_TRIGGER);
 
+  Preferences::RegisterCallback(SetMemoryGCPrefChangedCallback,
+                               "javascript.options.mem.gc_allocation_threshold_mb");
+  SetMemoryGCPrefChangedCallback("javascript.options.mem.gc_allocation_threshold_mb",
+                                (void *)JSGC_ALLOCATION_THRESHOLD);
   nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
   if (!obs)
     return NS_ERROR_FAILURE;
 
   Preferences::AddBoolVarCache(&sGCOnMemoryPressure,
                                "javascript.options.gc_on_memory_pressure",
                                true);
 
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -752,16 +752,17 @@ JSRuntime::JSRuntime(JSUseHelperThreads 
     gcNumArenasFreeCommitted(0),
     gcVerifyPreData(NULL),
     gcVerifyPostData(NULL),
     gcChunkAllocationSinceLastGC(false),
     gcNextFullGCTime(0),
     gcLastGCTime(0),
     gcJitReleaseTime(0),
     gcMode(JSGC_MODE_GLOBAL),
+    gcAllocationThreshold(30),
     gcHighFrequencyGC(false),
     gcHighFrequencyTimeThreshold(1000),
     gcHighFrequencyLowLimitBytes(100 * 1024 * 1024),
     gcHighFrequencyHighLimitBytes(500 * 1024 * 1024),
     gcHighFrequencyHeapGrowthMax(3.0),
     gcHighFrequencyHeapGrowthMin(1.5),
     gcLowFrequencyHeapGrowth(1.5),
     gcDynamicHeapGrowth(false),
@@ -2974,16 +2975,19 @@ JS_SetGCParameter(JSRuntime *rt, JSGCPar
         rt->gcDynamicHeapGrowth = value;
         break;
       case JSGC_DYNAMIC_MARK_SLICE:
         rt->gcDynamicMarkSlice = value;
         break;
       case JSGC_ANALYSIS_PURGE_TRIGGER:
         rt->analysisPurgeTriggerBytes = value * 1024 * 1024;
         break;
+      case JSGC_ALLOCATION_THRESHOLD:
+        rt->gcAllocationThreshold = value * 1024 * 1024;
+        break;
       default:
         JS_ASSERT(key == JSGC_MODE);
         rt->gcMode = JSGCMode(value);
         JS_ASSERT(rt->gcMode == JSGC_MODE_GLOBAL ||
                   rt->gcMode == JSGC_MODE_COMPARTMENT ||
                   rt->gcMode == JSGC_MODE_INCREMENTAL);
         return;
     }
@@ -3022,16 +3026,18 @@ JS_GetGCParameter(JSRuntime *rt, JSGCPar
       case JSGC_LOW_FREQUENCY_HEAP_GROWTH:
         return uint32_t(rt->gcLowFrequencyHeapGrowth * 100);
       case JSGC_DYNAMIC_HEAP_GROWTH:
         return rt->gcDynamicHeapGrowth;
       case JSGC_DYNAMIC_MARK_SLICE:
         return rt->gcDynamicMarkSlice;
       case JSGC_ANALYSIS_PURGE_TRIGGER:
         return rt->analysisPurgeTriggerBytes / 1024 / 1024;
+      case JSGC_ALLOCATION_THRESHOLD:
+        return rt->gcAllocationThreshold / 1024 / 1024;
       default:
         JS_ASSERT(key == JSGC_NUMBER);
         return uint32_t(rt->gcNumber);
     }
 }
 
 JS_PUBLIC_API(void)
 JS_SetGCParameterForThread(JSContext *cx, JSGCParamKey key, uint32_t value)
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -3951,17 +3951,20 @@ typedef enum JSGCParamKey {
      * based on whether GCs are high- or low- frequency.
      */
     JSGC_DYNAMIC_HEAP_GROWTH = 17,
 
     /* If true, high-frequency GCs will use a longer mark slice. */
     JSGC_DYNAMIC_MARK_SLICE = 18,
 
     /* Number of megabytes of analysis data to allocate before purging. */
-    JSGC_ANALYSIS_PURGE_TRIGGER = 19
+    JSGC_ANALYSIS_PURGE_TRIGGER = 19,
+
+    /* Lower limit after which we limit the heap growth. */
+    JSGC_ALLOCATION_THRESHOLD = 20
 } JSGCParamKey;
 
 typedef enum JSGCMode {
     /* Perform only global GCs. */
     JSGC_MODE_GLOBAL = 0,
 
     /* Perform per-compartment GCs until too much garbage has accumulated. */
     JSGC_MODE_COMPARTMENT = 1,
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -547,16 +547,17 @@ struct JSRuntime : js::RuntimeFriendFiel
     js::GCMarker        gcMarker;
     void                *gcVerifyPreData;
     void                *gcVerifyPostData;
     bool                gcChunkAllocationSinceLastGC;
     int64_t             gcNextFullGCTime;
     int64_t             gcLastGCTime;
     int64_t             gcJitReleaseTime;
     JSGCMode            gcMode;
+    size_t              gcAllocationThreshold;
     bool                gcHighFrequencyGC;
     uint64_t            gcHighFrequencyTimeThreshold;
     uint64_t            gcHighFrequencyLowLimitBytes;
     uint64_t            gcHighFrequencyHighLimitBytes;
     double              gcHighFrequencyHeapGrowthMax;
     double              gcHighFrequencyHeapGrowthMin;
     double              gcLowFrequencyHeapGrowth;
     bool                gcDynamicHeapGrowth;
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -111,21 +111,16 @@
 using namespace mozilla;
 using namespace js;
 using namespace js::gc;
 
 namespace js {
 
 namespace gc {
 
-/*
- * Lower limit after which we limit the heap growth
- */
-const size_t GC_ALLOCATION_THRESHOLD = 30 * 1024 * 1024;
-
 /* Perform a Full GC every 20 seconds if MaybeGC is called */
 static const uint64_t GC_IDLE_FULL_SPAN = 20 * 1000 * 1000;
 
 /* Increase the IGC marking slice time if we are in highFrequencyGC mode. */
 const int IGC_MARK_SLICE_MULTIPLIER = 2;
 
 #ifdef JS_GC_ZEAL
 static void
@@ -1375,17 +1370,17 @@ js_RemoveRoot(JSRuntime *rt, void *rp)
 
 typedef RootedValueMap::Range RootRange;
 typedef RootedValueMap::Entry RootEntry;
 typedef RootedValueMap::Enum RootEnum;
 
 static size_t
 ComputeTriggerBytes(JSCompartment *comp, size_t lastBytes, size_t maxBytes, JSGCInvocationKind gckind)
 {
-    size_t base = gckind == GC_SHRINK ? lastBytes : Max(lastBytes, GC_ALLOCATION_THRESHOLD);
+    size_t base = gckind == GC_SHRINK ? lastBytes : Max(lastBytes, comp->rt->gcAllocationThreshold);
     float trigger = float(base) * comp->gcHeapGrowthFactor;
     return size_t(Min(float(maxBytes), trigger));
 }
 
 void
 JSCompartment::setGCLastBytes(size_t lastBytes, size_t lastMallocBytes, JSGCInvocationKind gckind)
 {
     /*
@@ -1427,17 +1422,17 @@ JSCompartment::setGCLastBytes(size_t las
     gcTriggerMallocAndFreeBytes = ComputeTriggerBytes(this, lastMallocBytes, SIZE_MAX, gckind);
 }
 
 void
 JSCompartment::reduceGCTriggerBytes(size_t amount)
 {
     JS_ASSERT(amount > 0);
     JS_ASSERT(gcTriggerBytes >= amount);
-    if (gcTriggerBytes - amount < GC_ALLOCATION_THRESHOLD * gcHeapGrowthFactor)
+    if (gcTriggerBytes - amount < rt->gcAllocationThreshold * gcHeapGrowthFactor)
         return;
     gcTriggerBytes -= amount;
 }
 
 namespace js {
 namespace gc {
 
 inline void
--- a/mobile/android/app/mobile.js
+++ b/mobile/android/app/mobile.js
@@ -394,16 +394,17 @@ pref("javascript.options.gc_on_memory_pr
 #ifdef MOZ_PKG_SPECIAL
 // low memory devices
 pref("javascript.options.mem.gc_high_frequency_heap_growth_max", 120);
 pref("javascript.options.mem.gc_high_frequency_heap_growth_min", 101);
 pref("javascript.options.mem.gc_high_frequency_high_limit_mb", 40);
 pref("javascript.options.mem.gc_high_frequency_low_limit_mb", 10);
 pref("javascript.options.mem.gc_low_frequency_heap_growth", 105);
 pref("javascript.options.mem.high_water_mark", 16);
+pref("javascript.options.mem.gc_allocation_threshold_mb", 3);
 #else
 pref("javascript.options.mem.high_water_mark", 32);
 #endif
 
 pref("dom.max_chrome_script_run_time", 0); // disable slow script dialog for chrome
 pref("dom.max_script_run_time", 20);
 
 // JS error console
--- a/modules/libpref/src/init/all.js
+++ b/modules/libpref/src/init/all.js
@@ -736,16 +736,17 @@ pref("javascript.options.gc_on_memory_pr
 pref("javascript.options.mem.gc_high_frequency_time_limit_ms", 1000);
 pref("javascript.options.mem.gc_high_frequency_low_limit_mb", 100);
 pref("javascript.options.mem.gc_high_frequency_high_limit_mb", 500);
 pref("javascript.options.mem.gc_high_frequency_heap_growth_max", 300);
 pref("javascript.options.mem.gc_high_frequency_heap_growth_min", 150);
 pref("javascript.options.mem.gc_low_frequency_heap_growth", 150);
 pref("javascript.options.mem.gc_dynamic_heap_growth", true);
 pref("javascript.options.mem.gc_dynamic_mark_slice", true);
+pref("javascript.options.mem.gc_allocation_threshold_mb", 30);
 
 pref("javascript.options.mem.analysis_purge_mb", 100);
 
 // advanced prefs
 pref("advanced.mailftp",                    false);
 pref("image.animation_mode",                "normal");
 
 // Same-origin policy for file URIs, "false" is traditional