Bug 1406570 - "Root" compartment while entering it, r=jonco
authorSteve Fink <sfink@mozilla.com>
Wed, 11 Oct 2017 17:19:24 -0700
changeset 386026 750de14d83712561cc6b274518b1f7096c83b7cc
parent 386025 8adc032add4e21b85ff4eaa31ae0074434dc2a12
child 386027 782e1972037f3830bd04cf70ac529969bb796a56
push id32673
push userarchaeopteryx@coole-files.de
push dateFri, 13 Oct 2017 09:13:17 +0000
treeherdermozilla-central@196dadb2fe50 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjonco
bugs1406570
milestone58.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 1406570 - "Root" compartment while entering it, r=jonco
js/src/jscntxtinlines.h
js/src/jscompartment.cpp
js/src/jscompartment.h
js/src/jsgc.cpp
--- a/js/src/jscntxtinlines.h
+++ b/js/src/jscntxtinlines.h
@@ -450,17 +450,19 @@ JSContext::runningWithTrustedPrincipals(
 }
 
 inline void
 JSContext::enterNonAtomsCompartment(JSCompartment* c)
 {
     enterCompartmentDepth_++;
 
     MOZ_ASSERT(!c->zone()->isAtomsZone());
+    c->holdGlobal();
     enterZoneGroup(c->zone()->group());
+    c->releaseGlobal();
 
     c->enter();
     setCompartment(c, nullptr);
 }
 
 inline void
 JSContext::enterAtomsCompartment(JSCompartment* c,
                                  const js::AutoLockForExclusiveAccess& lock)
--- a/js/src/jscompartment.cpp
+++ b/js/src/jscompartment.cpp
@@ -62,16 +62,17 @@ JSCompartment::JSCompartment(Zone* zone,
     warnedAboutLegacyGenerator(false),
     warnedAboutObjectWatch(false),
     warnedAboutStringGenericsMethods(0),
 #ifdef DEBUG
     firedOnNewGlobalObject(false),
 #endif
     global_(nullptr),
     enterCompartmentDepth(0),
+    globalHolds(0),
     performanceMonitoring(runtime_),
     data(nullptr),
     realmData(nullptr),
     allocationMetadataBuilder(nullptr),
     lastAnimationTime(0),
     regExps(zone),
     globalWriteBarriered(0),
     detachedTypedObjects(0),
@@ -762,17 +763,17 @@ JSCompartment::traceRoots(JSTracer* trc,
     }
 
     if (!JS::CurrentThreadIsHeapMinorCollecting()) {
         // The global is never nursery allocated, so we don't need to
         // trace it when doing a minor collection.
         //
         // If a compartment is on-stack, we mark its global so that
         // JSContext::global() remains valid.
-        if (enterCompartmentDepth && global_.unbarrieredGet())
+        if (shouldTraceGlobal() && global_.unbarrieredGet())
             TraceRoot(trc, global_.unsafeUnbarrieredForTracing(), "on-stack compartment global");
     }
 
     // Nothing below here needs to be treated as a root if we aren't marking
     // this zone for a collection.
     if (traceOrMark == js::gc::GCRuntime::MarkRuntime && !zone()->isCollectingFromAnyThread())
         return;
 
--- a/js/src/jscompartment.h
+++ b/js/src/jscompartment.h
@@ -637,27 +637,37 @@ struct JSCompartment
     void mark() { marked = true; }
 
   private:
     friend struct JSRuntime;
     friend struct JSContext;
     js::ReadBarrieredGlobalObject global_;
 
     unsigned                     enterCompartmentDepth;
+    unsigned                     globalHolds;
 
   public:
     js::PerformanceGroupHolder performanceMonitoring;
 
     void enter() {
         enterCompartmentDepth++;
     }
     void leave() {
         enterCompartmentDepth--;
     }
-    bool hasBeenEntered() { return !!enterCompartmentDepth; }
+    bool hasBeenEntered() const { return !!enterCompartmentDepth; }
+
+    void holdGlobal() {
+        globalHolds++;
+    }
+    void releaseGlobal() {
+        MOZ_ASSERT(globalHolds > 0);
+        globalHolds--;
+    }
+    bool shouldTraceGlobal() const { return globalHolds > 0 || hasBeenEntered(); }
 
     JS::Zone* zone() { return zone_; }
     const JS::Zone* zone() const { return zone_; }
 
     const JS::CompartmentCreationOptions& creationOptions() const { return creationOptions_; }
     JS::CompartmentBehaviors& behaviors() { return behaviors_; }
     const JS::CompartmentBehaviors& behaviors() const { return behaviors_; }
 
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -4084,17 +4084,17 @@ GCRuntime::prepareZonesForCollection(JS:
 
     // Discard JIT code more aggressively if the process is approaching its
     // executable code limit.
     bool canAllocateMoreCode = jit::CanLikelyAllocateMoreExecutableMemory();
 
     for (CompartmentsIter c(rt, WithAtoms); !c.done(); c.next()) {
         c->marked = false;
         c->scheduledForDestruction = false;
-        c->maybeAlive = c->hasBeenEntered() || !c->zone()->isGCScheduled();
+        c->maybeAlive = c->shouldTraceGlobal() || !c->zone()->isGCScheduled();
         if (shouldPreserveJITCode(c, currentTime, reason, canAllocateMoreCode))
             c->zone()->setPreservingCode(true);
     }
 
     if (!cleanUpEverything && canAllocateMoreCode) {
         jit::JitActivationIterator activation(TlsContext.get());
         if (!activation.done())
             activation->compartment()->zone()->setPreservingCode(true);