Bug 1473213 (Part 1) - Track the number of tenured cells r=jonco
authorPaul Bone <pbone@mozilla.com>
Fri, 20 Jul 2018 15:09:01 +1000
changeset 431384 9022f602d14632498cab4a73c947797365b2f459
parent 431383 9a627240fa20844a88bd8d1bee6057f5e5e8cefa
child 431385 8217b33680fa66e2553d27c9076a6bf429df3431
push id34440
push userapavel@mozilla.com
push dateTue, 14 Aug 2018 16:15:57 +0000
treeherdermozilla-central@48a45df79f32 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjonco
bugs1473213
milestone63.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 1473213 (Part 1) - Track the number of tenured cells r=jonco
js/src/gc/Marking.cpp
js/src/gc/Nursery.cpp
js/src/gc/Nursery.h
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -2997,16 +2997,17 @@ js::TenuringTracer::moveToTenuredSlow(JS
         if (tarray->hasInlineElements()) {
             AllocKind srcKind = GetGCObjectKind(TypedArrayObject::FIXED_DATA_START);
             size_t headerSize = Arena::thingSize(srcKind);
             srcSize = headerSize + tarray->byteLength();
         }
     }
 
     tenuredSize += dstSize;
+    tenuredCells++;
 
     // Copy the Cell contents.
     MOZ_ASSERT(OffsetToChunkEnd(src) >= ptrdiff_t(srcSize));
     js_memcpy(dst, src, srcSize);
 
     // Move the slots and elements, if we need to.
     if (src->isNative()) {
         NativeObject* ndst = &dst->as<NativeObject>();
@@ -3045,16 +3046,17 @@ js::TenuringTracer::movePlainObjectToTen
     MOZ_ASSERT(IsInsideNursery(src));
     MOZ_ASSERT(!src->zone()->usedByHelperThread());
 
     AllocKind dstKind = src->allocKindForTenure();
     auto dst = allocTenured<PlainObject>(src->zone(), dstKind);
 
     size_t srcSize = Arena::thingSize(dstKind);
     tenuredSize += srcSize;
+    tenuredCells++;
 
     // Copy the Cell contents.
     MOZ_ASSERT(OffsetToChunkEnd(src) >= ptrdiff_t(srcSize));
     js_memcpy(dst, src, srcSize);
 
     // Move the slots and elements.
     tenuredSize += moveSlotsToTenured(dst, src);
     tenuredSize += moveElementsToTenured(dst, src, dstKind);
@@ -3161,16 +3163,17 @@ js::TenuringTracer::moveToTenured(JSStri
     MOZ_ASSERT(!src->zone()->usedByHelperThread());
 
     AllocKind dstKind = src->getAllocKind();
     Zone* zone = src->zone();
     zone->tenuredStrings++;
 
     JSString* dst = allocTenured<JSString>(zone, dstKind);
     tenuredSize += moveStringToTenured(dst, src, dstKind);
+    tenuredCells++;
 
     RelocationOverlay* overlay = RelocationOverlay::fromCell(src);
     overlay->forwardTo(dst);
     insertIntoStringFixupList(overlay);
 
     gcTracer.tracePromoteToTenured(src, dst);
     return dst;
 }
--- a/js/src/gc/Nursery.cpp
+++ b/js/src/gc/Nursery.cpp
@@ -535,16 +535,17 @@ js::Nursery::forwardBufferPointer(HeapSl
     MOZ_ASSERT(!isInside(*pSlotsElems));
     MOZ_ASSERT(IsWriteableAddress(*pSlotsElems));
 }
 
 js::TenuringTracer::TenuringTracer(JSRuntime* rt, Nursery* nursery)
   : JSTracer(rt, JSTracer::TracerKindTag::Tenuring, TraceWeakMapKeysValues)
   , nursery_(*nursery)
   , tenuredSize(0)
+  , tenuredCells(0)
   , objHead(nullptr)
   , objTail(&objHead)
   , stringHead(nullptr)
   , stringTail(&stringHead)
 {
 }
 
 inline float
@@ -594,16 +595,17 @@ js::Nursery::renderProfileJSON(JSONPrint
     }
 
     json.beginObject();
 
     json.property("status", "complete");
 
     json.property("reason", JS::gcreason::ExplainReason(previousGC.reason));
     json.property("bytes_tenured", previousGC.tenuredBytes);
+    json.property("cells_tenured", previousGC.tenuredCells);
     json.property("bytes_used", previousGC.nurseryUsedBytes);
     json.property("cur_capacity", previousGC.nurseryCapacity);
     const size_t newCapacity = spaceToEnd(maxChunkCount());
     if (newCapacity != previousGC.nurseryCapacity)
         json.property("new_capacity", newCapacity);
     if (previousGC.nurseryLazyCapacity != previousGC.nurseryCapacity)
         json.property("lazy_capacity", previousGC.nurseryLazyCapacity);
     if (!timeInChunkAlloc_.IsZero())
@@ -736,16 +738,17 @@ js::Nursery::collect(JS::gcreason::Reaso
     previousGC.reason = JS::gcreason::NO_REASON;
     if (!isEmpty()) {
         doCollection(reason, tenureCounts);
     } else {
         previousGC.nurseryUsedBytes = 0;
         previousGC.nurseryCapacity = spaceToEnd(maxChunkCount());
         previousGC.nurseryLazyCapacity = spaceToEnd(allocatedChunkCount());
         previousGC.tenuredBytes = 0;
+        previousGC.tenuredCells = 0;
     }
 
     // Resize the nursery.
     maybeResizeNursery(reason);
 
     // If we are promoting the nursery, or exhausted the store buffer with
     // pointers to nursery things, which will force a collection well before
     // the nursery is full, look for object groups that are getting promoted
@@ -949,16 +952,17 @@ js::Nursery::doCollection(JS::gcreason::
 #endif
     endProfile(ProfileKey::CheckHashTables);
 
     previousGC.reason = reason;
     previousGC.nurseryCapacity = initialNurseryCapacity;
     previousGC.nurseryLazyCapacity = spaceToEnd(allocatedChunkCount());
     previousGC.nurseryUsedBytes = initialNurseryUsedBytes;
     previousGC.tenuredBytes = mover.tenuredSize;
+    previousGC.tenuredCells = mover.tenuredCells;
 }
 
 void
 js::Nursery::FreeMallocedBuffersTask::transferBuffersToFree(MallocedBuffersSet& buffersToFree,
                                                             const AutoLockHelperThreadState& lock)
 {
     // Transfer the contents of the source set to the task's buffers_ member by
     // swapping the sets, which also clears the source.
--- a/js/src/gc/Nursery.h
+++ b/js/src/gc/Nursery.h
@@ -71,16 +71,18 @@ class MacroAssembler;
 
 class TenuringTracer : public JSTracer
 {
     friend class Nursery;
     Nursery& nursery_;
 
     // Amount of data moved to the tenured generation during collection.
     size_t tenuredSize;
+    // Number of cells moved to the tenured generation.
+    size_t tenuredCells;
 
     // These lists are threaded through the Nursery using the space from
     // already moved things. The lists are used to fix up the moved things and
     // to find things held live by intra-Nursery pointers.
     gc::RelocationOverlay* objHead;
     gc::RelocationOverlay** objTail;
     gc::RelocationOverlay* stringHead;
     gc::RelocationOverlay** stringTail;
@@ -433,16 +435,17 @@ class Nursery
     ProfileDurations totalDurations_;
 
     struct {
         JS::gcreason::Reason reason = JS::gcreason::NO_REASON;
         size_t nurseryCapacity = 0;
         size_t nurseryLazyCapacity = 0;
         size_t nurseryUsedBytes = 0;
         size_t tenuredBytes = 0;
+        size_t tenuredCells = 0;
     } previousGC;
 
     /*
      * Calculate the promotion rate of the most recent minor GC.
      * The valid_for_tenuring parameter is used to return whether this
      * promotion rate is accurate enough (the nursery was full enough) to be
      * used for tenuring and other decisions.
      *