Bug 1341093 - Transfer malloc bytes when zones are merged r=sfink
authorJon Coppeard <jcoppeard@mozilla.com>
Wed, 04 Oct 2017 13:22:29 +0100
changeset 426976 0d7a9ad2f02b3cd9f4cbab4ac794f2bd7a96a118
parent 426975 a7d845dd8d7a9ab34f9bd102574ef66a097fe8e4
child 426977 fa3f9e9479ae96c92b9a68ca0e8dda2808d9e260
push id97
push userfmarier@mozilla.com
push dateSat, 14 Oct 2017 01:12:59 +0000
reviewerssfink
bugs1341093
milestone58.0a1
Bug 1341093 - Transfer malloc bytes when zones are merged r=sfink
js/src/gc/GCRuntime.h
js/src/gc/Zone.h
js/src/jsgc.cpp
--- a/js/src/gc/GCRuntime.h
+++ b/js/src/gc/GCRuntime.h
@@ -701,16 +701,21 @@ class MemoryCounter
         return triggered_;
     }
 
     void decrement(size_t bytes) {
         MOZ_ASSERT(bytes <= bytes_);
         bytes_ -= bytes;
     }
 
+    void adopt(MemoryCounter<T>& other) {
+        bytes_ += other.bytes();
+        other.reset();
+    }
+
     ptrdiff_t bytes() const { return bytes_; }
     size_t maxBytes() const { return maxBytes_; }
     size_t initialMaxBytes(const AutoLockGC& lock) const { return initialMaxBytes_; }
     bool isTooMuchMalloc() const { return bytes_ >= maxBytes_; }
 
   private:
     void reset() {
         bytes_ = 0;
--- a/js/src/gc/Zone.h
+++ b/js/src/gc/Zone.h
@@ -447,16 +447,19 @@ struct Zone : public JS::shadow::Zone,
     }
     void setGCMaxMallocBytes(size_t value, const js::AutoLockGC& lock) {
         gcMallocCounter.setMax(value, lock);
     }
     void updateMallocCounter(size_t nbytes) {
         if (!runtime_->gc.updateMallocCounter(nbytes))
             gcMallocCounter.update(this, nbytes);
     }
+    void adoptMallocBytes(Zone* other) {
+        gcMallocCounter.adopt(other->gcMallocCounter);
+    }
     size_t GCMaxMallocBytes() const { return gcMallocCounter.maxBytes(); }
     size_t GCMallocBytes() const { return gcMallocCounter.bytes(); }
 
     void updateJitCodeMallocBytes(size_t size) { jitCodeCounter.update(this, size); }
 
     // Updates all the memory counters after GC.
     void updateAllMallocBytesOnGC(const js::AutoLockGC& lock) {
         updateGCMallocBytesOnGC(lock);
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -7724,16 +7724,19 @@ js::NewCompartment(JSContext* cx, JSPrin
     return compartment.forget();
 }
 
 void
 gc::MergeCompartments(JSCompartment* source, JSCompartment* target)
 {
     JSRuntime* rt = source->runtimeFromActiveCooperatingThread();
     rt->gc.mergeCompartments(source, target);
+
+    AutoLockGC lock(rt);
+    rt->gc.maybeAllocTriggerZoneGC(target->zone(), lock);
 }
 
 void
 GCRuntime::mergeCompartments(JSCompartment* source, JSCompartment* target)
 {
     // The source compartment must be specifically flagged as mergable.  This
     // also implies that the compartment is not visible to the debugger.
     MOZ_ASSERT(source->creationOptions_.mergeable());
@@ -7811,16 +7814,17 @@ GCRuntime::mergeCompartments(JSCompartme
     // The source should be the only compartment in its zone.
     for (CompartmentsInZoneIter c(source->zone()); !c.done(); c.next())
         MOZ_ASSERT(c.get() == source);
 
     // Merge the allocator, stats and UIDs in source's zone into target's zone.
     target->zone()->arenas.adoptArenas(rt, &source->zone()->arenas, targetZoneIsCollecting);
     target->zone()->usage.adopt(source->zone()->usage);
     target->zone()->adoptUniqueIds(source->zone());
+    target->zone()->adoptMallocBytes(source->zone());
 
     // Merge other info in source's zone into target's zone.
     target->zone()->types.typeLifoAlloc().transferFrom(&source->zone()->types.typeLifoAlloc());
 
     // Atoms which are marked in source's zone are now marked in target's zone.
     atomMarking.adoptMarkedAtoms(target->zone(), source->zone());
 
     // Merge script name maps in the target compartment's map.