Bug 1489572 - Add LifoAlloc instrumentation for adding heuristics. r=tcampbell
☠☠ backed out by 58bcea5ede75 ☠ ☠
authorNicolas B. Pierron <nicolas.b.pierron@nbp.name>
Wed, 17 Oct 2018 18:09:35 +0200
changeset 490860 cbfcb4b2b5c93b1d7330c6869fa197be79ea37f4
parent 490859 683e3e0eaee15b22fc997ed6cfd61630ec9f73b4
child 490861 f3aa68c506e01055a7d7d20eb4fb672c511b9caf
push id247
push userfmarier@mozilla.com
push dateSat, 27 Oct 2018 01:06:44 +0000
reviewerstcampbell
bugs1489572
milestone65.0a1
Bug 1489572 - Add LifoAlloc instrumentation for adding heuristics. r=tcampbell
js/src/ds/LifoAlloc.cpp
js/src/ds/LifoAlloc.h
--- a/js/src/ds/LifoAlloc.cpp
+++ b/js/src/ds/LifoAlloc.cpp
@@ -118,49 +118,62 @@ LifoAlloc::reset(size_t defaultChunkSize
     }
     while (!unused_.empty()) {
         unused_.popFirst();
     }
     defaultChunkSize_ = defaultChunkSize;
     oversizeThreshold_ = defaultChunkSize;
     markCount = 0;
     curSize_ = 0;
+    oversizeSize_ = 0;
 }
 
 void
 LifoAlloc::freeAll()
 {
     while (!chunks_.empty()) {
         UniqueBumpChunk bc = chunks_.popFirst();
         decrementCurSize(bc->computedSizeOfIncludingThis());
     }
     while (!oversize_.empty()) {
         UniqueBumpChunk bc = oversize_.popFirst();
         decrementCurSize(bc->computedSizeOfIncludingThis());
+        oversizeSize_ -= bc->computedSizeOfIncludingThis();
     }
     while (!unused_.empty()) {
         UniqueBumpChunk bc = unused_.popFirst();
         decrementCurSize(bc->computedSizeOfIncludingThis());
     }
 
     // Nb: maintaining curSize_ correctly isn't easy.  Fortunately, this is an
     // excellent sanity check.
     MOZ_ASSERT(curSize_ == 0);
+    MOZ_ASSERT(oversizeSize_ == 0);
 }
 
+// Round at the same page granularity used by malloc.
 static size_t
 MallocGoodSize(size_t aSize)
 {
 # if defined(MOZ_MEMORY)
     return malloc_good_size(aSize);
 # else
     return aSize;
 # endif
 }
 
+// Heuristic to choose the size of the next BumpChunk for small allocations.
+// `start` is the size of the first chunk. `used` is the total size of all
+// BumpChunks in this LifoAlloc so far.
+static size_t
+NextSize(size_t start, size_t used)
+{
+    return start;
+}
+
 LifoAlloc::UniqueBumpChunk
 LifoAlloc::newChunkWithCapacity(size_t n, bool oversize)
 {
     MOZ_ASSERT(fallibleScope_, "[OOM] Cannot allocate a new chunk in an infallible scope.");
 
     // Compute the size which should be requested in order to be able to fit |n|
     // bytes in a newly allocated chunk, or default to |defaultChunkSize_|.
 
@@ -169,17 +182,17 @@ LifoAlloc::newChunkWithCapacity(size_t n
                      (minSize & (size_t(1) << (BitSize<size_t>::value - 1)))))
     {
         return nullptr;
     }
 
     MOZ_ASSERT(curSize_ >= oversizeSize_);
     const size_t chunkSize = (oversize || minSize > defaultChunkSize_)
                              ? MallocGoodSize(minSize)
-                             : defaultChunkSize_;
+                             : NextSize(defaultChunkSize_, curSize_ - oversizeSize_);
 
     // Create a new BumpChunk, and allocate space for it.
     UniqueBumpChunk result = detail::BumpChunk::newWithCapacity(chunkSize);
     if (!result) {
         return nullptr;
     }
     MOZ_ASSERT(result->computedSizeOfIncludingThis() == chunkSize);
     return result;
@@ -239,16 +252,17 @@ void*
 LifoAlloc::allocImplOversize(size_t n)
 {
     void* result;
     UniqueBumpChunk newChunk = newChunkWithCapacity(n, true);
     if (!newChunk) {
         return nullptr;
     }
     incrementCurSize(newChunk->computedSizeOfIncludingThis());
+    oversizeSize_ += newChunk->computedSizeOfIncludingThis();
 
     // Since we just created a large enough chunk, this can't fail.
     oversize_.append(std::move(newChunk));
     result = oversize_.last()->tryAlloc(n);
     MOZ_ASSERT(result);
     return result;
 }
 
@@ -330,16 +344,17 @@ LifoAlloc::release(Mark mark)
     }
     unused_.appendAll(std::move(released));
 
     // Free the content of all the blocks which are after the marks.
     cutAtMark(mark.oversize, oversize_);
     while (!released.empty()) {
         UniqueBumpChunk bc = released.popFirst();
         decrementCurSize(bc->computedSizeOfIncludingThis());
+        oversizeSize_ -= bc->computedSizeOfIncludingThis();
     }
 }
 
 void
 LifoAlloc::steal(LifoAlloc* other)
 {
     MOZ_ASSERT(!other->markCount);
     MOZ_DIAGNOSTIC_ASSERT(unused_.empty());
@@ -351,34 +366,37 @@ LifoAlloc::steal(LifoAlloc* other)
     chunks_ = std::move(other->chunks_);
     oversize_ = std::move(other->oversize_);
     unused_ = std::move(other->unused_);
     markCount = other->markCount;
     defaultChunkSize_ = other->defaultChunkSize_;
     oversizeThreshold_ = other->oversizeThreshold_;
     curSize_ = other->curSize_;
     peakSize_ = Max(peakSize_, other->peakSize_);
+    oversizeSize_ = other->oversizeSize_;
 #if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
     fallibleScope_ = other->fallibleScope_;
 #endif
 
     other->reset(defaultChunkSize_);
 }
 
 void
 LifoAlloc::transferFrom(LifoAlloc* other)
 {
     MOZ_ASSERT(!markCount);
     MOZ_ASSERT(!other->markCount);
 
     incrementCurSize(other->curSize_);
+    oversizeSize_ += other->oversizeSize_;
     appendUnused(std::move(other->unused_));
     appendUsed(std::move(other->chunks_));
     oversize_.appendAll(std::move(other->oversize_));
     other->curSize_ = 0;
+    other->oversizeSize_ = 0;
 }
 
 void
 LifoAlloc::transferUnusedFrom(LifoAlloc* other)
 {
     MOZ_ASSERT(!markCount);
 
     size_t size = 0;
--- a/js/src/ds/LifoAlloc.h
+++ b/js/src/ds/LifoAlloc.h
@@ -544,16 +544,17 @@ class LifoAlloc
     // Set of unused chunks, which can be reused for future allocations.
     BumpChunkList unused_;
 
     size_t      markCount;
     size_t      defaultChunkSize_;
     size_t      oversizeThreshold_;
     size_t      curSize_;
     size_t      peakSize_;
+    size_t      oversizeSize_;
 #if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
     bool        fallibleScope_;
 #endif
 
     void operator=(const LifoAlloc&) = delete;
     LifoAlloc(const LifoAlloc&) = delete;
 
     // Return a BumpChunk that can perform an allocation of at least size |n|.
@@ -773,16 +774,17 @@ class LifoAlloc
             bc.release();
         }
         unused_.appendAll(std::move(chunks_));
         // On release, we free any oversize allocations instead of keeping them
         // in unused chunks.
         while (!oversize_.empty()) {
             UniqueBumpChunk bc = oversize_.popFirst();
             decrementCurSize(bc->computedSizeOfIncludingThis());
+            oversizeSize_ -= bc->computedSizeOfIncludingThis();
         }
     }
 
     // Protect the content of the LifoAlloc chunks.
 #ifdef LIFO_CHUNK_PROTECT
     void setReadOnly();
     void setReadWrite();
 #else