From 9ce0f0d1baa27299dcae89b2e5bdf3f255a213b1 Mon Sep 17 00:00:00 2001 From: Gregor Wagner Date: Thu, 2 Jun 2011 13:02:21 -0700 Subject: [PATCH] Bug 660329 - GC: add reason for GC to GCTimer. r=igor --- js/src/jsapi.cpp | 2 ++ js/src/jscntxt.cpp | 9 +++++++-- js/src/jsgc.cpp | 9 ++++++++- js/src/jsgcstats.cpp | 10 ++++++++-- js/src/jsgcstats.h | 20 ++++++++++++++++++++ js/src/jsscope.cpp | 1 + 6 files changed, 46 insertions(+), 5 deletions(-) diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 2f9965271b8..bef2f3381ca 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -2602,12 +2602,14 @@ JS_CompartmentGC(JSContext *cx, JSCompartment *comp) if (cx->tempPool.current == &cx->tempPool.first) JS_FinishArenaPool(&cx->tempPool); + GCREASON(PUBLIC_API); js_GC(cx, comp, GC_NORMAL); } JS_PUBLIC_API(void) JS_GC(JSContext *cx) { + GCREASON(PUBLIC_API); JS_CompartmentGC(cx, NULL); } diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index d16c699b818..56cbf30c5f0 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -640,6 +640,7 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode) #endif if (last) { + GCREASON(LASTCONTEXT); js_GC(cx, NULL, GC_LAST_CONTEXT); DUMP_EVAL_CACHE_METER(cx); DUMP_FUNCTION_METER(cx); @@ -649,10 +650,13 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode) rt->state = JSRTS_DOWN; JS_NOTIFY_ALL_CONDVAR(rt->stateChange); } else { - if (mode == JSDCM_FORCE_GC) + if (mode == JSDCM_FORCE_GC) { + GCREASON(DESTROYCONTEXT); js_GC(cx, NULL, GC_NORMAL); - else if (mode == JSDCM_MAYBE_GC) + } else if (mode == JSDCM_MAYBE_GC) { + GCREASON(DESTROYCONTEXT); JS_MaybeGC(cx); + } JS_LOCK_GC(rt); js_WaitForGC(rt); } @@ -1574,6 +1578,7 @@ JSRuntime::onTooMuchMalloc() */ js_WaitForGC(this); #endif + GCREASON(TOOMUCHMALLOC); TriggerGC(this); } diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index a446e589541..ee3bf24db2d 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -1187,6 +1187,7 @@ ArenaList::getArenaWithFreeList(JSContext *cx, unsigned thingKind) #endif /* !JS_THREADSAFE */ if (!chunk) { + GCREASON(CHUNK); TriggerGC(cx->runtime); return NULL; } @@ -1349,6 +1350,7 @@ RunLastDitchGC(JSContext *cx) #endif /* The last ditch GC preserves all atoms. */ AutoKeepAtoms keep(rt); + GCREASON(LASTDITCH); js_GC(cx, rt->gcTriggerCompartment, GC_NORMAL); #ifdef JS_THREADSAFE @@ -1879,6 +1881,7 @@ TriggerCompartmentGC(JSCompartment *comp) { JSRuntime *rt = comp->rt; JS_ASSERT(!rt->gcRunning); + GCREASON(COMPARTMENT); if (rt->gcZeal()) { TriggerGC(rt); @@ -1919,18 +1922,22 @@ MaybeGC(JSContext *cx) JSRuntime *rt = cx->runtime; if (rt->gcZeal()) { + GCREASON(MAYBEGC); js_GC(cx, NULL, GC_NORMAL); return; } JSCompartment *comp = cx->compartment; if (rt->gcIsNeeded) { + GCREASON(MAYBEGC); js_GC(cx, (comp == rt->gcTriggerCompartment) ? comp : NULL, GC_NORMAL); return; } - if (comp->gcBytes > 8192 && comp->gcBytes >= 3 * (comp->gcTriggerBytes / 4)) + if (comp->gcBytes > 8192 && comp->gcBytes >= 3 * (comp->gcTriggerBytes / 4)) { + GCREASON(MAYBEGC); js_GC(cx, (rt->gcMode == JSGC_MODE_COMPARTMENT) ? comp : NULL, GC_NORMAL); + } } } /* namespace js */ diff --git a/js/src/jsgcstats.cpp b/js/src/jsgcstats.cpp index 8a152b6bf9a..ffbd8a1156f 100644 --- a/js/src/jsgcstats.cpp +++ b/js/src/jsgcstats.cpp @@ -372,6 +372,10 @@ GCMarker::dumpConservativeRoots() #if defined(MOZ_GCTIMER) || defined(JSGC_TESTPILOT) +volatile GCTimer::JSGCReason gcReason = GCTimer::NOREASON; +const char *gcReasons[] = {" API", "Maybe", "LastC", "DestC", "Compa", "LastD", + "Malloc", "Alloc", "Chunk", "Shape", " None"}; + jsrefcount newChunkCount = 0; jsrefcount destroyChunkCount = 0; @@ -452,14 +456,15 @@ GCTimer::finish(bool lastGC) gcFile = fopen("gcTimer.dat", "a"); fprintf(gcFile, " AppTime, Total, Wait, Mark, Sweep, FinObj," - " FinStr, SwShapes, Destroy, End, +Chu, -Chu\n"); + " FinStr, SwShapes, Destroy, End, +Chu, -Chu, T, Reason\n"); } JS_ASSERT(gcFile); /* App , Tot , Wai , Mar , Swe , FiO , FiS , SwS , Des , End */ fprintf(gcFile, "%12.0f, %6.1f, %6.1f, %6.1f, %6.1f, %6.1f, %6.1f, %8.1f, %6.1f, %6.1f, ", appTime, gcTime, waitTime, markTime, sweepTime, sweepObjTime, sweepStringTime, sweepShapeTime, destroyTime, endTime); - fprintf(gcFile, "%4d, %4d\n", newChunkCount, destroyChunkCount); + fprintf(gcFile, "%4d, %4d,", newChunkCount, destroyChunkCount); + fprintf(gcFile, " %s, %s\n", isCompartmental ? "C" : "G", gcReasons[gcReason]); fflush(gcFile); if (lastGC) { @@ -471,6 +476,7 @@ GCTimer::finish(bool lastGC) } newChunkCount = 0; destroyChunkCount = 0; + gcReason = NOREASON; } #undef TIMEDIFF diff --git a/js/src/jsgcstats.h b/js/src/jsgcstats.h index f474b6e5ce3..076a2399e8b 100644 --- a/js/src/jsgcstats.h +++ b/js/src/jsgcstats.h @@ -211,8 +211,27 @@ struct GCTimer } void finish(bool lastGC); + + enum JSGCReason { + PUBLIC_API, + MAYBEGC, + LASTCONTEXT, + DESTROYCONTEXT, + COMPARTMENT, + LASTDITCH, + TOOMUCHMALLOC, + ALLOCTRIGGER, + CHUNK, + SHAPE, + NOREASON + }; }; +/* We accept the possiblility of races for this variable. */ +extern volatile GCTimer::JSGCReason gcReason; + +#define GCREASON(x) ((gcReason == GCTimer::NOREASON) ? gcReason = GCTimer::x : gcReason = gcReason) + # define GCTIMER_PARAM , GCTimer &gcTimer # define GCTIMER_ARG , gcTimer # define GCTIMESTAMP(stamp_name_) \ @@ -223,6 +242,7 @@ struct GCTimer # define GCTIMER_BEGIN(rt, comp) GCTimer gcTimer(rt, comp) # define GCTIMER_END(last) (gcTimer.finish(last)) #else +# define GCREASON(x) ((void) 0) # define GCTIMER_PARAM # define GCTIMER_ARG # define GCTIMESTAMP(x) ((void) 0) diff --git a/js/src/jsscope.cpp b/js/src/jsscope.cpp index c34fa3395e2..d313a8316a4 100644 --- a/js/src/jsscope.cpp +++ b/js/src/jsscope.cpp @@ -90,6 +90,7 @@ js_GenerateShape(JSRuntime *rt) #ifdef JS_THREADSAFE AutoLockGC lockIf(rt); #endif + GCREASON(SHAPE); TriggerGC(rt); } return shape;