Bug 1282113 - When we're shutting down the runtime, only allow shutdown GCs. r=terrence
authorJan de Mooij <jdemooij@mozilla.com>
Tue, 28 Jun 2016 11:56:08 +0200
changeset 302853 bc6e009a06d2683fbee66e8806eb8c993aabfe96
parent 302852 cbf85303aeb2cea6326574a39db03dad860b578f
child 302854 22dded92077567a244d017b412ab2cdd9aa682a1
push id30376
push usercbook@mozilla.com
push dateTue, 28 Jun 2016 14:09:36 +0000
treeherdermozilla-central@e45890951ce7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence
bugs1282113
milestone50.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
Bug 1282113 - When we're shutting down the runtime, only allow shutdown GCs. r=terrence
devtools/client/locales/en-US/markers.properties
js/public/GCAPI.h
js/src/doc/Debugger/Debugger.Memory.md
js/src/jit-test/tests/gc/bug1282113.js
js/src/jsgc.cpp
--- a/devtools/client/locales/en-US/markers.properties
+++ b/devtools/client/locales/en-US/markers.properties
@@ -98,17 +98,16 @@ marker.value.DOMEventTargetPhase=Target
 marker.value.DOMEventCapturingPhase=Capture
 marker.value.DOMEventBubblingPhase=Bubbling
 
 # LOCALIZATION NOTE (marker.gcreason.label.*):
 # These strings are used to give a concise but readable description of a GC reason.
 marker.gcreason.label.API=API Call
 marker.gcreason.label.EAGER_ALLOC_TRIGGER=Eager Allocation Trigger
 marker.gcreason.label.DESTROY_RUNTIME=Shutdown
-marker.gcreason.label.DESTROY_CONTEXT=Shutdown
 marker.gcreason.label.LAST_DITCH=Out of Memory
 marker.gcreason.label.TOO_MUCH_MALLOC=Too Many Bytes Allocated
 marker.gcreason.label.ALLOC_TRIGGER=Too Many Allocations
 marker.gcreason.label.DEBUG_GC=Debug GC
 marker.gcreason.label.COMPARTMENT_REVIVED=Dead Global Revived
 marker.gcreason.label.RESET=Finish Incremental Cycle
 marker.gcreason.label.OUT_OF_NURSERY=Nursery is Full
 marker.gcreason.label.EVICT_NURSERY=Nursery Eviction
@@ -138,17 +137,16 @@ marker.gcreason.label.USER_INACTIVE=User
 # The name of a nursery collection.
 marker.nurseryCollection=Nursery Collection
 
 # LOCALIZATION NOTE (marker.gcreason.description.*):
 # These strings are used to give an expanded description of why a GC occurred.
 marker.gcreason.description.API=There was an API call to force garbage collection.
 marker.gcreason.description.EAGER_ALLOC_TRIGGER=JavaScript returned to the event loop and there were enough bytes allocated since the last GC that a new GC cycle was triggered.
 marker.gcreason.description.DESTROY_RUNTIME=Firefox destroyed a JavaScript runtime or context, and this was the final garbage collection before shutting down.
-marker.gcreason.description.DESTROY_CONTEXT=Firefox destroyed a JavaScript runtime or context, and this was the final garbage collection before shutting down.
 marker.gcreason.description.LAST_DITCH=JavaScript attempted to allocate, but there was no memory available. Doing a full compacting garbage collection as an attempt to free up memory for the allocation.
 marker.gcreason.description.TOO_MUCH_MALLOC=JavaScript allocated too many bytes, and forced a garbage collection.
 marker.gcreason.description.ALLOC_TRIGGER=JavaScript allocated too many times, and forced a garbage collection.
 marker.gcreason.description.DEBUG_GC=GC due to Zeal debug settings.
 marker.gcreason.description.COMPARTMENT_REVIVED=A global object that was thought to be dead at the start of the GC cycle was revived by the end of the GC cycle.
 marker.gcreason.description.RESET=The active incremental GC cycle was forced to finish immediately.
 marker.gcreason.description.OUT_OF_NURSERY=JavaScript allocated enough new objects in the nursery that it became full and triggered a minor GC.
 marker.gcreason.description.EVICT_NURSERY=Work needed to be done on the tenured heap, requiring the nursery to be empty.
--- a/js/public/GCAPI.h
+++ b/js/public/GCAPI.h
@@ -49,17 +49,17 @@ typedef enum JSGCInvocationKind {
 
 namespace JS {
 
 #define GCREASONS(D)                            \
     /* Reasons internal to the JS engine */     \
     D(API)                                      \
     D(EAGER_ALLOC_TRIGGER)                      \
     D(DESTROY_RUNTIME)                          \
-    D(DESTROY_CONTEXT)                          \
+    D(UNUSED0)                                  \
     D(LAST_DITCH)                               \
     D(TOO_MUCH_MALLOC)                          \
     D(ALLOC_TRIGGER)                            \
     D(DEBUG_GC)                                 \
     D(COMPARTMENT_REVIVED)                      \
     D(RESET)                                    \
     D(OUT_OF_NURSERY)                           \
     D(EVICT_NURSERY)                            \
--- a/js/src/doc/Debugger/Debugger.Memory.md
+++ b/js/src/doc/Debugger/Debugger.Memory.md
@@ -156,17 +156,16 @@ compartment.
 
     `reason`
     :   A very short string describing the reason why the collection was
         triggered. Known values include the following:
 
         * "API"
         * "EAGER_ALLOC_TRIGGER"
         * "DESTROY_RUNTIME"
-        * "DESTROY_CONTEXT"
         * "LAST_DITCH"
         * "TOO_MUCH_MALLOC"
         * "ALLOC_TRIGGER"
         * "DEBUG_GC"
         * "COMPARTMENT_REVIVED"
         * "RESET"
         * "OUT_OF_NURSERY"
         * "EVICT_NURSERY"
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/gc/bug1282113.js
@@ -0,0 +1,6 @@
+Object.getOwnPropertyNames(this);
+setGCCallback({
+    action: "majorGC",
+    phases: "begin"
+});
+selectforgc(this);
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -6275,16 +6275,21 @@ GCRuntime::checkCanCallAPI()
 }
 
 bool
 GCRuntime::checkIfGCAllowedInCurrentState(JS::gcreason::Reason reason)
 {
     if (rt->mainThread.suppressGC)
         return false;
 
+    // Only allow shutdown GCs when we're destroying the runtime. This keeps
+    // the GC callback from triggering a nested GC and resetting global state.
+    if (rt->isBeingDestroyed() && !IsShutdownGC(reason))
+        return false;
+
 #ifdef JS_GC_ZEAL
     if (deterministicOnly && !IsDeterministicGCReason(reason))
         return false;
 #endif
 
     return true;
 }