Bug 1311702 - Fix potential deadlock resizing the nursery. r=sfink, a=gchang
authorJon Coppeard <jcoppeard@mozilla.com>
Thu, 20 Oct 2016 07:45:00 -0400
changeset 356232 903cce16fa75d4298dc9ab7e8ac9003617f011c1
parent 356231 ad173f0c74519558ac3265597f18f5f3f5547766
child 356233 8aea18a0b3df39fd34384ac09f30c4d006139820
push id6570
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:26:13 +0000
treeherdermozilla-beta@f455459b2ae5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink, gchang
bugs1311702
milestone51.0a2
Bug 1311702 - Fix potential deadlock resizing the nursery. r=sfink, a=gchang
js/src/gc/Nursery.cpp
js/src/gc/Nursery.h
--- a/js/src/gc/Nursery.cpp
+++ b/js/src/gc/Nursery.cpp
@@ -144,17 +144,18 @@ js::Nursery::init(uint32_t maxNurseryByt
 
     if (!cellsWithUid_.init())
         return false;
 
     freeMallocedBuffersTask = js_new<FreeMallocedBuffersTask>(runtime()->defaultFreeOp());
     if (!freeMallocedBuffersTask || !freeMallocedBuffersTask->init())
         return false;
 
-    updateNumChunksLocked(1, lock);
+    AutoMaybeStartBackgroundAllocation maybeBgAlloc;
+    updateNumChunksLocked(1, maybeBgAlloc, lock);
     if (numChunks() == 0)
         return false;
 
     setCurrentChunk(0);
     setStartPosition();
 
     char* env = getenv("JS_GC_PROFILE_NURSERY");
     if (env) {
@@ -918,32 +919,33 @@ js::Nursery::shrinkAllocableSpace()
 #endif
     updateNumChunks(Max(numChunks() - 1, 1u));
 }
 
 void
 js::Nursery::updateNumChunks(unsigned newCount)
 {
     if (numChunks() != newCount) {
+        AutoMaybeStartBackgroundAllocation maybeBgAlloc;
         AutoLockGC lock(runtime());
-        updateNumChunksLocked(newCount, lock);
+        updateNumChunksLocked(newCount, maybeBgAlloc, lock);
     }
 }
 
 void
-js::Nursery::updateNumChunksLocked(unsigned newCount, AutoLockGC& lock)
+js::Nursery::updateNumChunksLocked(unsigned newCount,
+                                   AutoMaybeStartBackgroundAllocation& maybeBgAlloc,
+                                   AutoLockGC& lock)
 {
     // The GC nursery is an optimization and so if we fail to allocate nursery
     // chunks we do not report an error.
 
     unsigned priorCount = numChunks();
     MOZ_ASSERT(priorCount != newCount);
 
-    AutoMaybeStartBackgroundAllocation maybeBgAlloc;
-
     if (newCount < priorCount) {
         // Shrink the nursery and free unused chunks.
         for (unsigned i = newCount; i < priorCount; i++)
             runtime()->gc.recycleChunk(chunk(i).toChunk(runtime()), lock);
         chunks_.shrinkTo(newCount);
         return;
     }
 
--- a/js/src/gc/Nursery.h
+++ b/js/src/gc/Nursery.h
@@ -56,16 +56,17 @@ namespace js {
 class ObjectElements;
 class NativeObject;
 class Nursery;
 class HeapSlot;
 
 void SetGCZeal(JSRuntime*, uint8_t, uint32_t);
 
 namespace gc {
+class AutoMaybeStartBackgroundAllocation;
 struct Cell;
 class MinorCollectionTracer;
 class RelocationOverlay;
 struct TenureCountCache;
 } /* namespace gc */
 
 namespace jit {
 class MacroAssembler;
@@ -383,17 +384,19 @@ class Nursery
     NurseryChunk& chunk(unsigned index) const {
         return *chunks_[index];
     }
 
     void setCurrentChunk(unsigned chunkno);
     void setStartPosition();
 
     void updateNumChunks(unsigned newCount);
-    void updateNumChunksLocked(unsigned newCount, AutoLockGC& lock);
+    void updateNumChunksLocked(unsigned newCount,
+                               gc::AutoMaybeStartBackgroundAllocation& maybeBgAlloc,
+                               AutoLockGC& lock);
 
     MOZ_ALWAYS_INLINE uintptr_t allocationEnd() const {
         MOZ_ASSERT(numChunks() > 0);
         return chunks_.back()->end();
     }
 
     MOZ_ALWAYS_INLINE uintptr_t currentEnd() const {
         MOZ_ASSERT(runtime_);