Bug 1354273 - GC during OOMTest if we create too many compartments r=sfink
authorJon Coppeard <jcoppeard@mozilla.com>
Mon, 24 Apr 2017 10:58:36 +0100
changeset 402725 6f40efd60fcb2eee79fa8495538f494a5aa3652c
parent 402724 11fa5271d39828a37777b80b95345f29689d3013
child 402726 f1a900c8483dcb53d4bcb7c948d30b6ed6816ae0
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink
bugs1354273
milestone55.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 1354273 - GC during OOMTest if we create too many compartments r=sfink
js/src/builtin/TestingFunctions.cpp
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -1436,16 +1436,26 @@ static bool
 ResetOOMFailure(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     args.rval().setBoolean(js::oom::HadSimulatedOOM());
     js::oom::ResetSimulatedOOM();
     return true;
 }
 
+static size_t
+CountCompartments(JSContext* cx)
+{
+    size_t count = 0;
+    ZoneGroup* group = cx->compartment()->zone()->group();
+    for (auto zone : group->zones())
+        count += zone->compartments().length();
+    return count;
+}
+
 static bool
 OOMTest(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
 
     if (args.length() < 1 || args.length() > 2) {
         JS_ReportErrorASCII(cx, "oomTest() takes between 1 and 2 arguments.");
         return false;
@@ -1498,16 +1508,18 @@ OOMTest(JSContext* cx, unsigned argc, Va
         JS_ReportErrorASCII(cx, "Nested call to oomTest() is not allowed.");
         return false;
     }
     cx->runningOOMTest = true;
 
     MOZ_ASSERT(!cx->isExceptionPending());
     cx->runtime()->hadOutOfMemory = false;
 
+    size_t compartmentCount = CountCompartments(cx);
+
     JS_SetGCZeal(cx, 0, JS_DEFAULT_ZEAL_FREQ);
 
     for (unsigned thread = threadStart; thread < threadEnd; thread++) {
         if (verbose)
             fprintf(stderr, "thread %d\n", thread);
 
         HelperThreadState().waitForAllThreads();
         js::oom::targetThread = thread;
@@ -1545,16 +1557,26 @@ OOMTest(JSContext* cx, unsigned argc, Va
             // Note that it is possible that the function throws an exception
             // unconnected to OOM, in which case we ignore it. More correct
             // would be to have the caller pass some kind of exception
             // specification and to check the exception against it.
 
             cx->clearPendingException();
             cx->runtime()->hadOutOfMemory = false;
 
+            // Some tests create a new compartment or zone on every
+            // iteration. Our GC is triggered by GC allocations and not by
+            // number of copmartments or zones, so these won't normally get
+            // cleaned up. The check here stops some tests running out of
+            // memory.
+            if (CountCompartments(cx) > compartmentCount + 100) {
+                JS_GC(cx);
+                compartmentCount = CountCompartments(cx);
+            }
+
 #ifdef JS_TRACE_LOGGING
             // Reset the TraceLogger state if enabled.
             TraceLoggerThread* logger = TraceLoggerForCurrentThread(cx);
             if (logger->enabled()) {
                 while (logger->enabled())
                     logger->disable();
                 logger->enable(cx);
             }