diff --git a/js/public/GCAPI.h b/js/public/GCAPI.h index 8cdcfe99e38e..7d1ef07960fa 100644 --- a/js/public/GCAPI.h +++ b/js/public/GCAPI.h @@ -90,7 +90,7 @@ namespace JS { D(REFRESH_FRAME) \ D(FULL_GC_TIMER) \ D(SHUTDOWN_CC) \ - D(FINISH_LARGE_EVALUATE) + D(FINISH_LARGE_EVALUTE) namespace gcreason { diff --git a/js/src/builtin/TestingFunctions.cpp b/js/src/builtin/TestingFunctions.cpp index 74e979ddb700..b70d744d3d76 100644 --- a/js/src/builtin/TestingFunctions.cpp +++ b/js/src/builtin/TestingFunctions.cpp @@ -268,7 +268,7 @@ MinorGC(JSContext *cx, unsigned argc, jsval *vp) if (args.get(0) == BooleanValue(true)) cx->runtime()->gc.storeBuffer.setAboutToOverflow(); - cx->minorGC(gcreason::API); + MinorGC(cx, gcreason::API); #endif args.rval().setUndefined(); return true; @@ -519,7 +519,7 @@ SelectForGC(JSContext *cx, unsigned argc, Value *vp) * to be in the set, so evict the nursery before adding items. */ JSRuntime *rt = cx->runtime(); - rt->gc.evictNursery(); + MinorGC(rt, JS::gcreason::EVICT_NURSERY); for (unsigned i = 0; i < args.length(); i++) { if (args[i].isObject()) { @@ -628,7 +628,7 @@ GCSlice(JSContext *cx, unsigned argc, Value *vp) limit = false; } - cx->runtime()->gc.gcDebugSlice(limit, budget); + GCDebugSlice(cx->runtime(), limit, budget); args.rval().setUndefined(); return true; } diff --git a/js/src/gc/GCRuntime.h b/js/src/gc/GCRuntime.h index b9f7a03caa98..5379ceb4f4d8 100644 --- a/js/src/gc/GCRuntime.h +++ b/js/src/gc/GCRuntime.h @@ -278,13 +278,10 @@ class GCRuntime void maybePeriodicFullGC(); void minorGC(JS::gcreason::Reason reason); void minorGC(JSContext *cx, JS::gcreason::Reason reason); - void evictNursery(JS::gcreason::Reason reason = JS::gcreason::EVICT_NURSERY) { minorGC(reason); } void gcIfNeeded(JSContext *cx); - void gc(JSGCInvocationKind gckind, JS::gcreason::Reason reason); + void collect(bool incremental, int64_t budget, JSGCInvocationKind gckind, + JS::gcreason::Reason reason); void gcSlice(JSGCInvocationKind gckind, JS::gcreason::Reason reason, int64_t millis = 0); - void gcFinalSlice(JSGCInvocationKind gckind, JS::gcreason::Reason reason); - void gcDebugSlice(bool limit, int64_t objCount); - void runDebugGC(); inline void poke(); @@ -468,8 +465,6 @@ class GCRuntime bool initZeal(); void requestInterrupt(JS::gcreason::Reason reason); - void collect(bool incremental, int64_t budget, JSGCInvocationKind gckind, - JS::gcreason::Reason reason); bool gcCycle(bool incremental, int64_t budget, JSGCInvocationKind gckind, JS::gcreason::Reason reason); gcstats::ZoneGCStats scanZonesBeforeGC(); diff --git a/js/src/gc/Iteration.cpp b/js/src/gc/Iteration.cpp index 0c2e31fce44e..c6e799580e96 100644 --- a/js/src/gc/Iteration.cpp +++ b/js/src/gc/Iteration.cpp @@ -23,7 +23,7 @@ js::TraceRuntime(JSTracer *trc) JS_ASSERT(!IS_GC_MARKING_TRACER(trc)); JSRuntime *rt = trc->runtime(); - rt->gc.evictNursery(); + MinorGC(rt, JS::gcreason::EVICT_NURSERY); AutoPrepareForTracing prep(rt, WithAtoms); rt->gc.markRuntime(trc); } @@ -93,7 +93,7 @@ void js::IterateScripts(JSRuntime *rt, JSCompartment *compartment, void *data, IterateScriptCallback scriptCallback) { - rt->gc.evictNursery(); + MinorGC(rt, JS::gcreason::EVICT_NURSERY); AutoPrepareForTracing prep(rt, SkipAtoms); if (compartment) { @@ -113,7 +113,7 @@ js::IterateScripts(JSRuntime *rt, JSCompartment *compartment, void js::IterateGrayObjects(Zone *zone, GCThingCallback cellCallback, void *data) { - zone->runtimeFromMainThread()->gc.evictNursery(); + MinorGC(zone->runtimeFromMainThread(), JS::gcreason::EVICT_NURSERY); AutoPrepareForTracing prep(zone->runtimeFromMainThread(), SkipAtoms); for (size_t finalizeKind = 0; finalizeKind <= FINALIZE_OBJECT_LAST; finalizeKind++) { diff --git a/js/src/gc/Verifier.cpp b/js/src/gc/Verifier.cpp index 9bbe39a25f4a..5499a53b6f7f 100644 --- a/js/src/gc/Verifier.cpp +++ b/js/src/gc/Verifier.cpp @@ -182,7 +182,7 @@ gc::GCRuntime::startVerifyPreBarriers() if (verifyPostData) return; - evictNursery(); + MinorGC(rt, JS::gcreason::EVICT_NURSERY); AutoPrepareForTracing prep(rt, WithAtoms); @@ -410,7 +410,7 @@ gc::GCRuntime::startVerifyPostBarriers() return; } - evictNursery(); + MinorGC(rt, JS::gcreason::EVICT_NURSERY); number++; diff --git a/js/src/gc/Zone.cpp b/js/src/gc/Zone.cpp index 0bf676576bd6..ad2613456399 100644 --- a/js/src/gc/Zone.cpp +++ b/js/src/gc/Zone.cpp @@ -97,10 +97,8 @@ Zone::setGCMaxMallocBytes(size_t value) void Zone::onTooMuchMalloc() { - if (!gcMallocGCTriggered) { - GCRuntime &gc = runtimeFromAnyThread()->gc; - gcMallocGCTriggered = gc.triggerZoneGC(this, JS::gcreason::TOO_MUCH_MALLOC); - } + if (!gcMallocGCTriggered) + gcMallocGCTriggered = TriggerZoneGC(this, JS::gcreason::TOO_MUCH_MALLOC); } void diff --git a/js/src/jit/BaselineDebugModeOSR.cpp b/js/src/jit/BaselineDebugModeOSR.cpp index 6472f8f1bf6e..c118ce94ef80 100644 --- a/js/src/jit/BaselineDebugModeOSR.cpp +++ b/js/src/jit/BaselineDebugModeOSR.cpp @@ -658,7 +658,7 @@ jit::RecompileOnStackBaselineScriptsForDebugMode(JSContext *cx, JSCompartment *c #ifdef JSGC_GENERATIONAL // Scripts can entrain nursery things. See note in js::ReleaseAllJITCode. if (!entries.empty()) - cx->runtime()->gc.evictNursery(); + MinorGC(cx->runtime(), JS::gcreason::EVICT_NURSERY); #endif // When the profiler is enabled, we need to suppress sampling from here until diff --git a/js/src/jsapi-tests/testGCFinalizeCallback.cpp b/js/src/jsapi-tests/testGCFinalizeCallback.cpp index 4c38c45407f6..fc4dc708464b 100644 --- a/js/src/jsapi-tests/testGCFinalizeCallback.cpp +++ b/js/src/jsapi-tests/testGCFinalizeCallback.cpp @@ -88,12 +88,12 @@ BEGIN_TEST(testGCFinalizeCallback) FinalizeCalls = 0; JS_SetGCZeal(cx, 9, 1000000); JS::PrepareForFullGC(rt); - rt->gc.gcDebugSlice(true, 1); + js::GCDebugSlice(rt, true, 1); CHECK(rt->gc.state() == js::gc::MARK); CHECK(rt->gc.isFullGc()); JS::RootedObject global4(cx, createGlobal()); - rt->gc.gcDebugSlice(true, 1); + js::GCDebugSlice(rt, true, 1); CHECK(rt->gc.state() == js::gc::NO_INCREMENTAL); CHECK(!rt->gc.isFullGc()); CHECK(checkMultipleGroups()); diff --git a/js/src/jsapi-tests/testGCHeapPostBarriers.cpp b/js/src/jsapi-tests/testGCHeapPostBarriers.cpp index 2fc66907921c..6aa4dced04a1 100644 --- a/js/src/jsapi-tests/testGCHeapPostBarriers.cpp +++ b/js/src/jsapi-tests/testGCHeapPostBarriers.cpp @@ -51,7 +51,7 @@ TestHeapPostBarriers(T initialObj) uintptr_t initialObjAsInt = uintptr_t(initialObj); /* Perform minor GC and check heap wrapper is udated with new pointer. */ - cx->minorGC(JS::gcreason::API); + js::MinorGC(cx, JS::gcreason::API); CHECK(uintptr_t(heapData->get()) != initialObjAsInt); CHECK(!js::gc::IsInsideNursery(heapData->get())); diff --git a/js/src/jsapi-tests/testWeakMap.cpp b/js/src/jsapi-tests/testWeakMap.cpp index 8c3db691d2fa..7bfacf118017 100644 --- a/js/src/jsapi-tests/testWeakMap.cpp +++ b/js/src/jsapi-tests/testWeakMap.cpp @@ -87,7 +87,7 @@ BEGIN_TEST(testWeakMap_keyDelegates) * zone to finish marking before the delegate zone. */ CHECK(newCCW(map, delegate)); - rt->gc.gcDebugSlice(true, 1000000); + GCDebugSlice(rt, true, 1000000); #ifdef DEBUG CHECK(map->zone()->lastZoneGroupIndex() < delegate->zone()->lastZoneGroupIndex()); #endif @@ -100,7 +100,7 @@ BEGIN_TEST(testWeakMap_keyDelegates) /* Check the delegate keeps the entry alive even if the key is not reachable. */ key = nullptr; CHECK(newCCW(map, delegate)); - rt->gc.gcDebugSlice(true, 100000); + GCDebugSlice(rt, true, 100000); CHECK(checkSize(map, 1)); /* diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 89bfa8e876a7..c2d15765045b 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -1873,7 +1873,7 @@ JS_GC(JSRuntime *rt) { AssertHeapIsIdle(rt); JS::PrepareForFullGC(rt); - rt->gc.gc(GC_NORMAL, JS::gcreason::API); + GC(rt, GC_NORMAL, JS::gcreason::API); } JS_PUBLIC_API(void) @@ -4807,7 +4807,7 @@ Evaluate(JSContext *cx, HandleObject obj, const ReadOnlyCompileOptions &optionsA if (script->length() > LARGE_SCRIPT_LENGTH) { script = nullptr; PrepareZoneForGC(cx->zone()); - cx->runtime()->gc.gc(GC_NORMAL, JS::gcreason::FINISH_LARGE_EVALUATE); + GC(cx->runtime(), GC_NORMAL, JS::gcreason::FINISH_LARGE_EVALUTE); } return result; diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index e6aa3c0c2cb0..f5effb931662 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -251,7 +251,7 @@ js::DestroyContext(JSContext *cx, DestroyContextMode mode) if (mode == DCM_FORCE_GC) { JS_ASSERT(!rt->isHeapBusy()); JS::PrepareForFullGC(rt); - rt->gc.gc(GC_NORMAL, JS::gcreason::DESTROY_CONTEXT); + GC(rt, GC_NORMAL, JS::gcreason::DESTROY_CONTEXT); } js_delete_poison(cx); } @@ -986,7 +986,7 @@ js::InvokeInterruptCallback(JSContext *cx) // callbacks. rt->resetJitStackLimit(); - cx->gcIfNeeded(); + js::gc::GCIfNeeded(cx); rt->interruptPar = false; diff --git a/js/src/jscntxt.h b/js/src/jscntxt.h index 734ee731f1ec..7f7a8add373d 100644 --- a/js/src/jscntxt.h +++ b/js/src/jscntxt.h @@ -548,14 +548,6 @@ struct JSContext : public js::ExclusiveContext, } #endif - void minorGC(JS::gcreason::Reason reason) { - runtime_->gc.minorGC(this, reason); - } - - void gcIfNeeded() { - runtime_->gc.gcIfNeeded(this); - } - private: /* Innermost-executing generator or null if no generator are executing. */ JSGenerator *innermostGenerator_; diff --git a/js/src/jsfriendapi.cpp b/js/src/jsfriendapi.cpp index 520ba1b18cf1..d46d33db6c2b 100644 --- a/js/src/jsfriendapi.cpp +++ b/js/src/jsfriendapi.cpp @@ -197,25 +197,25 @@ JS::SkipZoneForGC(Zone *zone) JS_FRIEND_API(void) JS::GCForReason(JSRuntime *rt, gcreason::Reason reason) { - rt->gc.gc(GC_NORMAL, reason); + GC(rt, GC_NORMAL, reason); } JS_FRIEND_API(void) JS::ShrinkingGC(JSRuntime *rt, gcreason::Reason reason) { - rt->gc.gc(GC_SHRINK, reason); + GC(rt, GC_SHRINK, reason); } JS_FRIEND_API(void) JS::IncrementalGC(JSRuntime *rt, gcreason::Reason reason, int64_t millis) { - rt->gc.gcSlice(GC_NORMAL, reason, millis); + GCSlice(rt, GC_NORMAL, reason, millis); } JS_FRIEND_API(void) JS::FinishIncrementalGC(JSRuntime *rt, gcreason::Reason reason) { - rt->gc.gcFinalSlice(GC_NORMAL, reason); + GCFinalSlice(rt, GC_NORMAL, reason); } JS_FRIEND_API(JSPrincipals *) @@ -810,7 +810,7 @@ js::DumpHeapComplete(JSRuntime *rt, FILE *fp, js::DumpHeapNurseryBehaviour nurse { #ifdef JSGC_GENERATIONAL if (nurseryBehaviour == js::CollectNurseryBeforeDump) - rt->gc.evictNursery(JS::gcreason::API); + MinorGC(rt, JS::gcreason::API); #endif DumpHeapTracer dtrc(fp, rt, DumpHeapVisitRoot, TraceWeakMapKeysValues); diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 1ef5dde331a1..07d3a4ffbc3c 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -939,7 +939,7 @@ Chunk::allocateArena(Zone *zone, AllocKind thingKind) if (zone->usage.gcBytes() >= zone->threshold.gcTriggerBytes()) { AutoUnlockGC unlock(rt); - rt->gc.triggerZoneGC(zone, JS::gcreason::ALLOC_TRIGGER); + TriggerZoneGC(zone, JS::gcreason::ALLOC_TRIGGER); } return aheader; @@ -1186,7 +1186,7 @@ GCRuntime::setZeal(uint8_t zeal, uint32_t frequency) #ifdef JSGC_GENERATIONAL if (zealMode == ZealGenerationalGCValue) { - evictNursery(JS::gcreason::DEBUG_GC); + minorGC(JS::gcreason::DEBUG_GC); nursery.leaveZealMode(); } @@ -2169,7 +2169,7 @@ RunLastDitchGC(JSContext *cx, JS::Zone *zone, AllocKind thingKind) /* The last ditch GC preserves all atoms. */ AutoKeepAtoms keepAtoms(cx->perThreadData); - rt->gc.gc(GC_NORMAL, JS::gcreason::LAST_DITCH); + GC(rt, GC_NORMAL, JS::gcreason::LAST_DITCH); /* * The JSGC_END callback can legitimately allocate new GC @@ -2271,6 +2271,12 @@ ArenaLists::refillFreeList(ThreadSafeContext *cx, AllocKind thingKind); template void * ArenaLists::refillFreeList(ThreadSafeContext *cx, AllocKind thingKind); +JSGCTraceKind +js_GetGCThingTraceKind(void *thing) +{ + return GetGCThingTraceKind(thing); +} + /* static */ int64_t SliceBudget::TimeBudget(int64_t millis) { @@ -2328,6 +2334,12 @@ GCRuntime::requestInterrupt(JS::gcreason::Reason reason) rt->requestInterrupt(JSRuntime::RequestInterruptMainThread); } +bool +js::TriggerGC(JSRuntime *rt, JS::gcreason::Reason reason) +{ + return rt->gc.triggerGC(reason); +} + bool GCRuntime::triggerGC(JS::gcreason::Reason reason) { @@ -2357,6 +2369,12 @@ GCRuntime::triggerGC(JS::gcreason::Reason reason) return true; } +bool +js::TriggerZoneGC(Zone *zone, JS::gcreason::Reason reason) +{ + return zone->runtimeFromAnyThread()->gc.triggerZoneGC(zone, reason); +} + bool GCRuntime::triggerZoneGC(Zone *zone, JS::gcreason::Reason reason) { @@ -2383,14 +2401,14 @@ GCRuntime::triggerZoneGC(Zone *zone, JS::gcreason::Reason reason) #ifdef JS_GC_ZEAL if (zealMode == ZealAllocValue) { - triggerGC(reason); + TriggerGC(rt, reason); return true; } #endif if (rt->isAtomsZone(zone)) { /* We can't do a zone GC of the atoms compartment. */ - triggerGC(reason); + TriggerGC(rt, reason); return true; } @@ -2407,13 +2425,13 @@ GCRuntime::maybeGC(Zone *zone) #ifdef JS_GC_ZEAL if (zealMode == ZealAllocValue || zealMode == ZealPokeValue) { JS::PrepareForFullGC(rt); - gc(GC_NORMAL, JS::gcreason::MAYBEGC); + GC(rt, GC_NORMAL, JS::gcreason::MAYBEGC); return true; } #endif if (isNeeded) { - gcSlice(GC_NORMAL, JS::gcreason::MAYBEGC); + GCSlice(rt, GC_NORMAL, JS::gcreason::MAYBEGC); return true; } @@ -2424,7 +2442,7 @@ GCRuntime::maybeGC(Zone *zone) !isBackgroundSweeping()) { PrepareZoneForGC(zone); - gcSlice(GC_NORMAL, JS::gcreason::MAYBEGC); + GCSlice(rt, GC_NORMAL, JS::gcreason::MAYBEGC); return true; } @@ -2450,7 +2468,7 @@ GCRuntime::maybePeriodicFullGC() numArenasFreeCommitted > decommitThreshold) { JS::PrepareForFullGC(rt); - gcSlice(GC_SHRINK, JS::gcreason::MAYBEGC); + GCSlice(rt, GC_SHRINK, JS::gcreason::MAYBEGC); } else { nextFullGCTime = now + GC_IDLE_FULL_SPAN; } @@ -4749,7 +4767,7 @@ GCRuntime::incrementalCollectSlice(int64_t budget, if (reason == JS::gcreason::DEBUG_GC && budget != SliceBudget::Unlimited) { /* * Do the incremental collection type specified by zeal mode if the - * collection was triggered by runDebugGC() and incremental GC has not + * collection was triggered by RunDebugGC() and incremental GC has not * been cancelled by resetIncrementalGC(). */ zeal = zealMode; @@ -5182,9 +5200,15 @@ GCRuntime::collect(bool incremental, int64_t budget, JSGCInvocationKind gckind, } void -GCRuntime::gc(JSGCInvocationKind gckind, JS::gcreason::Reason reason) +js::GC(JSRuntime *rt, JSGCInvocationKind gckind, JS::gcreason::Reason reason) { - collect(false, SliceBudget::Unlimited, gckind, reason); + rt->gc.collect(false, SliceBudget::Unlimited, gckind, reason); +} + +void +js::GCSlice(JSRuntime *rt, JSGCInvocationKind gckind, JS::gcreason::Reason reason, int64_t millis) +{ + rt->gc.gcSlice(gckind, reason, millis); } void @@ -5202,9 +5226,9 @@ GCRuntime::gcSlice(JSGCInvocationKind gckind, JS::gcreason::Reason reason, int64 } void -GCRuntime::gcFinalSlice(JSGCInvocationKind gckind, JS::gcreason::Reason reason) +js::GCFinalSlice(JSRuntime *rt, JSGCInvocationKind gckind, JS::gcreason::Reason reason) { - collect(true, SliceBudget::Unlimited, gckind, reason); + rt->gc.collect(true, SliceBudget::Unlimited, gckind, reason); } void @@ -5247,7 +5271,7 @@ ZonesSelected(JSRuntime *rt) } void -GCRuntime::gcDebugSlice(bool limit, int64_t objCount) +js::GCDebugSlice(JSRuntime *rt, bool limit, int64_t objCount) { int64_t budget = limit ? SliceBudget::WorkBudget(objCount) : SliceBudget::Unlimited; if (!ZonesSelected(rt)) { @@ -5256,7 +5280,7 @@ GCRuntime::gcDebugSlice(bool limit, int64_t objCount) else JS::PrepareForFullGC(rt); } - collect(true, budget, GC_NORMAL, JS::gcreason::DEBUG_GC); + rt->gc.collect(true, budget, GC_NORMAL, JS::gcreason::DEBUG_GC); } /* Schedule a full GC unless a zone will already be collected. */ @@ -5286,6 +5310,12 @@ GCRuntime::shrinkBuffers() expireChunksAndArenas(true); } +void +js::MinorGC(JSRuntime *rt, JS::gcreason::Reason reason) +{ + rt->gc.minorGC(reason); +} + void GCRuntime::minorGC(JS::gcreason::Reason reason) { @@ -5298,10 +5328,16 @@ GCRuntime::minorGC(JS::gcreason::Reason reason) } void -GCRuntime::minorGC(JSContext *cx, JS::gcreason::Reason reason) +js::MinorGC(JSContext *cx, JS::gcreason::Reason reason) { // Alternate to the runtime-taking form above which allows marking type // objects as needing pretenuring. + cx->runtime()->gc.minorGC(cx, reason); +} + +void +GCRuntime::minorGC(JSContext *cx, JS::gcreason::Reason reason) +{ #ifdef JSGC_GENERATIONAL TraceLogger *logger = TraceLoggerForMainThread(rt); AutoTraceLog logMinorGC(logger, TraceLogger::MinorGC); @@ -5341,6 +5377,12 @@ GCRuntime::enableGenerationalGC() #endif } +void +js::gc::GCIfNeeded(JSContext *cx) +{ + cx->runtime()->gc.gcIfNeeded(cx); +} + void GCRuntime::gcIfNeeded(JSContext *cx) { @@ -5357,6 +5399,12 @@ GCRuntime::gcIfNeeded(JSContext *cx) gcSlice(GC_NORMAL, rt->gc.triggerReason, 0); } +void +js::gc::FinishBackgroundFinalize(JSRuntime *rt) +{ + rt->gc.waitBackgroundSweepEnd(); +} + AutoFinishGC::AutoFinishGC(JSRuntime *rt) { if (JS::IsIncrementalGCInProgress(rt)) { @@ -5364,7 +5412,7 @@ AutoFinishGC::AutoFinishGC(JSRuntime *rt) JS::FinishIncrementalGC(rt, JS::gcreason::API); } - rt->gc.waitBackgroundSweepEnd(); + gc::FinishBackgroundFinalize(rt); } AutoPrepareForTracing::AutoPrepareForTracing(JSRuntime *rt, ZoneSelector selector) @@ -5472,6 +5520,12 @@ gc::MergeCompartments(JSCompartment *source, JSCompartment *target) target->zone()->types.typeLifoAlloc.transferFrom(&source->zone()->types.typeLifoAlloc); } +void +gc::RunDebugGC(JSContext *cx) +{ + cx->runtime()->gc.runDebugGC(); +} + void GCRuntime::runDebugGC() { @@ -5482,7 +5536,7 @@ GCRuntime::runDebugGC() return; if (type == js::gc::ZealGenerationalGCValue) - return minorGC(JS::gcreason::DEBUG_GC); + return MinorGC(rt, JS::gcreason::DEBUG_GC); PrepareForDebugGC(rt); @@ -5580,7 +5634,7 @@ js::ReleaseAllJITCode(FreeOp *fop) * Scripts can entrain nursery things, inserting references to the script * into the store buffer. Clear the store buffer before discarding scripts. */ - fop->runtime()->gc.evictNursery(); + MinorGC(fop->runtime(), JS::gcreason::EVICT_NURSERY); #endif for (ZonesIter zone(fop->runtime(), SkipAtoms); !zone.done(); zone.next()) { diff --git a/js/src/jsgc.h b/js/src/jsgc.h index c5f5a5571636..8cdd447a3e92 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -963,6 +963,14 @@ MarkCompartmentActive(js::InterpreterFrame *fp); extern void TraceRuntime(JSTracer *trc); +/* Must be called with GC lock taken. */ +extern bool +TriggerGC(JSRuntime *rt, JS::gcreason::Reason reason); + +/* Must be called with GC lock taken. */ +extern bool +TriggerZoneGC(Zone *zone, JS::gcreason::Reason reason); + extern void ReleaseAllJITCode(FreeOp *op); @@ -977,9 +985,27 @@ typedef enum JSGCInvocationKind { GC_SHRINK = 1 } JSGCInvocationKind; +extern void +GC(JSRuntime *rt, JSGCInvocationKind gckind, JS::gcreason::Reason reason); + +extern void +GCSlice(JSRuntime *rt, JSGCInvocationKind gckind, JS::gcreason::Reason reason, int64_t millis = 0); + +extern void +GCFinalSlice(JSRuntime *rt, JSGCInvocationKind gckind, JS::gcreason::Reason reason); + +extern void +GCDebugSlice(JSRuntime *rt, bool limit, int64_t objCount); + extern void PrepareForDebugGC(JSRuntime *rt); +extern void +MinorGC(JSRuntime *rt, JS::gcreason::Reason reason); + +extern void +MinorGC(JSContext *cx, JS::gcreason::Reason reason); + /* Functions for managing cross compartment gray pointers. */ extern void @@ -1199,6 +1225,17 @@ NewCompartment(JSContext *cx, JS::Zone *zone, JSPrincipals *principals, namespace gc { +extern void +GCIfNeeded(JSContext *cx); + +/* Tries to run a GC no matter what (used for GC zeal). */ +void +RunDebugGC(JSContext *cx); + +/* Wait for the background thread to finish sweeping if it is running. */ +void +FinishBackgroundFinalize(JSRuntime *rt); + /* * Merge all contents of source into target. This can only be used if source is * the only compartment in its zone. diff --git a/js/src/jsgcinlines.h b/js/src/jsgcinlines.h index 384b2a0af4a2..8e764d08d0d6 100644 --- a/js/src/jsgcinlines.h +++ b/js/src/jsgcinlines.h @@ -368,13 +368,14 @@ class ZoneCellIter : public ZoneCellIterImpl if (IsBackgroundFinalized(kind) && zone->allocator.arenas.needBackgroundFinalizeWait(kind)) { - zone->runtimeFromMainThread()->gc.waitBackgroundSweepEnd(); + gc::FinishBackgroundFinalize(zone->runtimeFromMainThread()); } #ifdef JSGC_GENERATIONAL /* Evict the nursery before iterating so we can see all things. */ JSRuntime *rt = zone->runtimeFromMainThread(); - rt->gc.evictNursery(); + if (!rt->gc.nursery.isEmpty()) + MinorGC(rt, JS::gcreason::EVICT_NURSERY); #endif if (lists->isSynchronizedFreeList(kind)) { @@ -472,7 +473,7 @@ TryNewNurseryObject(JSContext *cx, size_t thingSize, size_t nDynamicSlots) if (obj) return obj; if (allowGC && !rt->mainThread.suppressGC) { - cx->minorGC(JS::gcreason::OUT_OF_NURSERY); + MinorGC(cx, JS::gcreason::OUT_OF_NURSERY); /* Exceeding gcMaxBytes while tenuring can disable the Nursery. */ if (nursery.isEnabled()) { @@ -546,13 +547,13 @@ CheckAllocatorState(ThreadSafeContext *cx, AllocKind kind) if (allowGC) { #ifdef JS_GC_ZEAL if (rt->gc.needZealousGC()) - rt->gc.runDebugGC(); + js::gc::RunDebugGC(ncx); #endif if (rt->interrupt) { // Invoking the interrupt callback can fail and we can't usefully // handle that here. Just check in case we need to collect instead. - ncx->gcIfNeeded(); + js::gc::GCIfNeeded(ncx); } } @@ -681,7 +682,7 @@ AllocateObjectForCacheHit(JSContext *cx, AllocKind kind, InitialHeap heap) JSObject *obj = TryNewNurseryObject(cx, thingSize, 0); if (!obj && allowGC) { - cx->minorGC(JS::gcreason::OUT_OF_NURSERY); + MinorGC(cx, JS::gcreason::OUT_OF_NURSERY); return nullptr; } return obj; diff --git a/js/src/vm/ForkJoin.cpp b/js/src/vm/ForkJoin.cpp index fe89743475b4..a7f9952b6b1f 100644 --- a/js/src/vm/ForkJoin.cpp +++ b/js/src/vm/ForkJoin.cpp @@ -355,7 +355,7 @@ ForkJoinActivation::ForkJoinActivation(JSContext *cx) JS::FinishIncrementalGC(cx->runtime(), JS::gcreason::API); } - cx->runtime()->gc.evictNursery(); + MinorGC(cx->runtime(), JS::gcreason::API); cx->runtime()->gc.waitBackgroundSweepEnd(); @@ -1492,11 +1492,10 @@ ForkJoinShared::transferArenasToCompartmentAndProcessGCRequests() if (gcRequested_) { Spew(SpewGC, "Triggering garbage collection in SpiderMonkey heap"); - gc::GCRuntime &gc = cx_->runtime()->gc; if (!gcZone_) - gc.triggerGC(gcReason_); + TriggerGC(cx_->runtime(), gcReason_); else - gc.triggerZoneGC(gcZone_, gcReason_); + TriggerZoneGC(gcZone_, gcReason_); gcRequested_ = false; gcZone_ = nullptr; } diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index e5fc625344b1..9967804c1dea 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -415,7 +415,7 @@ struct AutoGCIfNeeded { JSContext *cx_; explicit AutoGCIfNeeded(JSContext *cx) : cx_(cx) {} - ~AutoGCIfNeeded() { cx_->gcIfNeeded(); } + ~AutoGCIfNeeded() { js::gc::GCIfNeeded(cx_); } }; /* diff --git a/js/src/vm/Runtime.cpp b/js/src/vm/Runtime.cpp index 994cdfd3f9d1..9c1729d7c655 100644 --- a/js/src/vm/Runtime.cpp +++ b/js/src/vm/Runtime.cpp @@ -376,7 +376,7 @@ JSRuntime::~JSRuntime() profilingScripts = false; JS::PrepareForFullGC(this); - gc.gc(GC_NORMAL, JS::gcreason::DESTROY_RUNTIME); + GC(this, GC_NORMAL, JS::gcreason::DESTROY_RUNTIME); } /*