Bug 869235 - Disable Zone::needsBarrier during minor GCs; r=billm
authorTerrence Cole <terrence@mozilla.com>
Wed, 08 May 2013 11:45:12 -0700
changeset 142580 cf21050ee99d08171f0be813648d530fd357b4a1
parent 142579 c1a91eac6358a87475071d2a6d56186b39ac0dd2
child 142581 c314ee86060a8afaba68593da57b6ab7fb7c7853
push id2579
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 18:52:47 +0000
treeherdermozilla-beta@b69b7de8a05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs869235
milestone23.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 869235 - Disable Zone::needsBarrier during minor GCs; r=billm
js/src/gc/Nursery.cpp
js/src/gc/Zone.h
--- a/js/src/gc/Nursery.cpp
+++ b/js/src/gc/Nursery.cpp
@@ -176,45 +176,49 @@ class MinorCollectionTracer : public JST
      * This list is threaded through the Nursery using the space from already
      * moved things. The list is used to fix up the moved things and to find
      * things held live by intra-Nursery pointers.
      */
     RelocationOverlay *head;
     RelocationOverlay **tail;
 
     /* Save and restore all of the runtime state we use during MinorGC. */
-    bool priorNeedsBarrier;
+    bool savedNeedsBarrier;
     AutoDisableProxyCheck disableStrictProxyChecking;
 
     /* Insert the given relocation entry into the list of things to visit. */
     JS_ALWAYS_INLINE void insertIntoFixupList(RelocationOverlay *entry) {
         *tail = entry;
         tail = &entry->next_;
         *tail = NULL;
     }
 
     MinorCollectionTracer(JSRuntime *rt, Nursery *nursery)
       : JSTracer(),
         nursery(nursery),
         runtime(rt),
         session(runtime, MinorCollecting),
         head(NULL),
         tail(&head),
-        priorNeedsBarrier(runtime->needsBarrier()),
+        savedNeedsBarrier(runtime->needsBarrier()),
         disableStrictProxyChecking(runtime)
     {
         JS_TracerInit(this, runtime, Nursery::MinorGCCallback);
         eagerlyTraceWeakMaps = TraceWeakMapKeysValues;
 
         runtime->gcNumber++;
         runtime->setNeedsBarrier(false);
+        for (ZonesIter zone(rt); !zone.done(); zone.next())
+            zone->saveNeedsBarrier(false);
     }
 
     ~MinorCollectionTracer() {
-        runtime->setNeedsBarrier(priorNeedsBarrier);
+        runtime->setNeedsBarrier(savedNeedsBarrier);
+        for (ZonesIter zone(runtime); !zone.done(); zone.next())
+            zone->restoreNeedsBarrier();
     }
 };
 
 } /* namespace gc */
 } /* namespace js */
 
 static AllocKind
 GetObjectAllocKindForCopy(JSObject *obj)
@@ -237,16 +241,24 @@ GetObjectAllocKindForCopy(JSObject *obj)
 void *
 js::Nursery::allocateFromTenured(Zone *zone, AllocKind thingKind)
 {
     void *t = zone->allocator.arenas.allocateFromFreeList(thingKind, Arena::thingSize(thingKind));
     if (!t) {
         zone->allocator.arenas.checkEmptyFreeList(thingKind);
         t = zone->allocator.arenas.allocateFromArena(zone, thingKind);
     }
+
+    /*
+     * Pre barriers are disabled during minor collection, however, we still
+     * want objects to be allocated black if an incremental GC is in progress.
+     */
+    if (zone->savedNeedsBarrier())
+        static_cast<Cell *>(t)->markIfUnmarked();
+
     return t;
 }
 
 void *
 js::Nursery::moveToTenured(MinorCollectionTracer *trc, JSObject *src)
 {
     Zone *zone = src->zone();
     AllocKind dstKind = GetObjectAllocKindForCopy(src);
--- a/js/src/gc/Zone.h
+++ b/js/src/gc/Zone.h
@@ -108,19 +108,40 @@ struct Zone : private JS::shadow::Zone, 
     js::Allocator                allocator;
 
     js::CompartmentVector        compartments;
 
     bool                         hold;
 
   private:
     bool                         ionUsingBarriers_;
+
+    /*
+     * This flag saves the value of needsBarrier_ during minor collection,
+     * since needsBarrier_ is always set to false during minor collection.
+     * Outside of minor collection, the value of savedNeedsBarrier_ is
+     * undefined.
+     */
+    bool                         savedNeedsBarrier_;
+
   public:
+    bool                         active;  // GC flag, whether there are active frames
 
-    bool                         active;  // GC flag, whether there are active frames
+    void saveNeedsBarrier(bool newNeeds) {
+        savedNeedsBarrier_ = needsBarrier_;
+        needsBarrier_ = newNeeds;
+    }
+
+    void restoreNeedsBarrier() {
+        needsBarrier_ = savedNeedsBarrier_;
+    }
+
+    bool savedNeedsBarrier() const {
+        return savedNeedsBarrier_;
+    }
 
     bool needsBarrier() const {
         return needsBarrier_;
     }
 
     bool compileBarriers(bool needsBarrier) const {
         return needsBarrier || rt->gcZeal() == js::gc::ZealVerifierPreValue;
     }