diff --git a/js/src/gc/Nursery.cpp b/js/src/gc/Nursery.cpp index bacdfaf6bfa8..19ad94b77a96 100644 --- a/js/src/gc/Nursery.cpp +++ b/js/src/gc/Nursery.cpp @@ -181,7 +181,7 @@ class MinorCollectionTracer : public JSTracer 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. */ @@ -198,7 +198,7 @@ class MinorCollectionTracer : public JSTracer session(runtime, MinorCollecting), head(NULL), tail(&head), - priorNeedsBarrier(runtime->needsBarrier()), + savedNeedsBarrier(runtime->needsBarrier()), disableStrictProxyChecking(runtime) { JS_TracerInit(this, runtime, Nursery::MinorGCCallback); @@ -206,10 +206,14 @@ class MinorCollectionTracer : public JSTracer 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(); } }; @@ -242,6 +246,14 @@ js::Nursery::allocateFromTenured(Zone *zone, AllocKind thingKind) 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(t)->markIfUnmarked(); + return t; } diff --git a/js/src/gc/Zone.h b/js/src/gc/Zone.h index a1519890daab..a9c444b6a5ab 100644 --- a/js/src/gc/Zone.h +++ b/js/src/gc/Zone.h @@ -113,10 +113,31 @@ struct Zone : private JS::shadow::Zone, public js::gc::GraphNodeBase private: bool ionUsingBarriers_; - public: + /* + * 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 + void saveNeedsBarrier(bool newNeeds) { + savedNeedsBarrier_ = needsBarrier_; + needsBarrier_ = newNeeds; + } + + void restoreNeedsBarrier() { + needsBarrier_ = savedNeedsBarrier_; + } + + bool savedNeedsBarrier() const { + return savedNeedsBarrier_; + } + bool needsBarrier() const { return needsBarrier_; }