Bug 1379146 - SpiderMonkey: Reserve space when enqueuing compression tasks, to avoid OOM on helper threads. r=shu
☠☠ backed out by 94944363e740 ☠ ☠
authorNicolas B. Pierron <nicolas.b.pierron@mozilla.com>
Fri, 21 Jul 2017 10:03:32 +0000
changeset 418908 217ad633fbf7ea7b334c1da31c96248424f1d1dd
parent 418907 07888792204bdac76dea9f16afd04613edc6633d
child 418909 1044cf0518e931651ea51b6b407838807972703c
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersshu
bugs1379146
milestone56.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 1379146 - SpiderMonkey: Reserve space when enqueuing compression tasks, to avoid OOM on helper threads. r=shu
js/src/vm/HelperThreads.cpp
--- a/js/src/vm/HelperThreads.cpp
+++ b/js/src/vm/HelperThreads.cpp
@@ -1228,19 +1228,17 @@ GlobalHelperThreadState::startHandlingCo
 void
 GlobalHelperThreadState::scheduleCompressionTasks(const AutoLockHelperThreadState& lock)
 {
     auto& pending = compressionPendingList(lock);
     auto& worklist = compressionWorklist(lock);
 
     for (size_t i = 0; i < pending.length(); i++) {
         if (pending[i]->shouldStart()) {
-            // OOMing during appending results in the task not being scheduled
-            // and deleted.
-            Unused << worklist.append(Move(pending[i]));
+            worklist.infallibleAppend(Move(pending[i]));
             remove(pending, &i);
         }
     }
 }
 
 bool
 GlobalHelperThreadState::canStartGCHelperTask(const AutoLockHelperThreadState& lock)
 {
@@ -1950,34 +1948,48 @@ HelperThread::handleCompressionWorkload(
         AutoUnlockHelperThreadState unlock(locked);
 
         TraceLoggerThread* logger = TraceLoggerForCurrentThread();
         AutoTraceLog logCompile(logger, TraceLogger_CompressSource);
 
         task->work();
     }
 
-    {
-        AutoEnterOOMUnsafeRegion oomUnsafe;
-        if (!HelperThreadState().compressionFinishedList(locked).append(Move(task)))
-            oomUnsafe.crash("handleCompressionWorkload");
-    }
-
+    HelperThreadState().compressionFinishedList(locked).infallibleAppend(Move(task));
     currentTask.reset();
 
     // Notify the active thread in case it is waiting for the compression to finish.
     HelperThreadState().notifyAll(GlobalHelperThreadState::CONSUMER, locked);
 }
 
 bool
 js::EnqueueOffThreadCompression(JSContext* cx, UniquePtr<SourceCompressionTask> task)
 {
     AutoLockHelperThreadState lock;
 
     auto& pending = HelperThreadState().compressionPendingList(lock);
+
+    // Ensure there is enough space in the vectors to move the task from one
+    // state to another without having OOM on the helper threads.
+    size_t transitionSpace = pending.length() + 1;
+    auto& worklist = HelperThreadState().compressionWorklist(lock);
+    if (!worklist.reserve(worklist.length() + transitionSpace)) {
+        if (!cx->helperThread())
+            ReportOutOfMemory(cx);
+        return false;
+    }
+
+    transitionSpace += worklist.length();
+    auto& finished = HelperThreadState().compressionFinishedList(lock);
+    if (!finished.reserve(finished.length() + transitionSpace)) {
+        if (!cx->helperThread())
+            ReportOutOfMemory(cx);
+        return false;
+    }
+
     if (!pending.append(Move(task))) {
         if (!cx->helperThread())
             ReportOutOfMemory(cx);
         return false;
     }
 
     return true;
 }