diff --git a/js/src/gc/Zone.cpp b/js/src/gc/Zone.cpp index 1d8aa9dccddd..e871a4b3d5dc 100644 --- a/js/src/gc/Zone.cpp +++ b/js/src/gc/Zone.cpp @@ -76,6 +76,7 @@ Zone::setNeedsBarrier(bool needs, ShouldUpdateIon updateIon) if (needs && runtimeFromMainThread()->isAtomsZone(this)) JS_ASSERT(!runtimeFromMainThread()->exclusiveThreadsPresent()); + JS_ASSERT_IF(needs, canCollect()); needsBarrier_ = needs; } diff --git a/js/src/gc/Zone.h b/js/src/gc/Zone.h index 8b6fc91b5f29..8d25dc34624c 100644 --- a/js/src/gc/Zone.h +++ b/js/src/gc/Zone.h @@ -189,20 +189,16 @@ struct Zone : private JS::shadow::Zone, void setGCState(CompartmentGCState state) { JS_ASSERT(runtimeFromMainThread()->isHeapBusy()); + JS_ASSERT_IF(state != NoGC, canCollect()); gcState = state; } void scheduleGC() { - JSRuntime *rt = runtimeFromMainThread(); - JS_ASSERT(!rt->isHeapBusy()); + JS_ASSERT(!runtimeFromMainThread()->isHeapBusy()); - /* Note: zones cannot be collected while in use by other threads. */ - if (usedByExclusiveThread) - return; - if (rt->isAtomsZone(this) && rt->exclusiveThreadsPresent()) - return; - - gcScheduled = true; + // Ignore attempts to schedule GCs on zones which can't be collected. + if (canCollect()) + gcScheduled = true; } void unscheduleGC() { @@ -217,6 +213,16 @@ struct Zone : private JS::shadow::Zone, gcPreserveCode = preserving; } + bool canCollect() { + // Zones cannot be collected while in use by other threads. + if (usedByExclusiveThread) + return false; + JSRuntime *rt = runtimeFromMainThread(); + if (rt->isAtomsZone(this) && rt->exclusiveThreadsPresent()) + return false; + return true; + } + bool wasGCStarted() const { return gcState != NoGC; } diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index e9c25e737170..d4dc263f1f6d 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -4847,7 +4847,7 @@ JS::CanCompileOffThread(JSContext *cx, const CompileOptions &options) // atoms compartment, to avoid triggering barriers. Outside the atoms // compartment, the compilation will use a new zone which doesn't require // barriers itself. - if (cx->runtime()->atomsZoneNeedsBarrier()) + if (cx->runtime()->activeGCInAtomsZone()) return false; // Blacklist filenames which cause mysterious assertion failures in diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index 2ea9662f470a..d01ee66ac6c4 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -401,12 +401,6 @@ JSRuntime::isAtomsZone(JS::Zone *zone) return zone == atomsCompartment_->zone(); } -inline bool -JSRuntime::atomsZoneNeedsBarrier() -{ - return atomsCompartment_->zone()->needsBarrier(); -} - // For use when changing the debug mode flag on one or more compartments. // Do not run scripts in any compartment that is scheduled for GC using this // object. See comment in updateForDebugMode. diff --git a/js/src/vm/Runtime.cpp b/js/src/vm/Runtime.cpp index 4999e4364941..7e9340d95609 100644 --- a/js/src/vm/Runtime.cpp +++ b/js/src/vm/Runtime.cpp @@ -716,6 +716,13 @@ JSRuntime::onOutOfMemory(void *p, size_t nbytes, JSContext *cx) return NULL; } +bool +JSRuntime::activeGCInAtomsZone() +{ + Zone *zone = atomsCompartment_->zone(); + return zone->needsBarrier() || zone->isGCScheduled() || zone->wasGCStarted(); +} + #ifdef JS_THREADSAFE void diff --git a/js/src/vm/Runtime.h b/js/src/vm/Runtime.h index 6da5d2ac5f7f..8a2bb7bce51b 100644 --- a/js/src/vm/Runtime.h +++ b/js/src/vm/Runtime.h @@ -1415,7 +1415,7 @@ struct JSRuntime : public JS::shadow::Runtime, // The atoms compartment is the only one in its zone. inline bool isAtomsZone(JS::Zone *zone); - inline bool atomsZoneNeedsBarrier(); + bool activeGCInAtomsZone(); union { /*