From 4f7d40e8bc731e51e63f6dfc00687ff53a21b513 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Thu, 22 Apr 2010 07:32:13 -0500 Subject: [PATCH] Bug 553671 part 9 - Extract ProcessAllSetSlotRequests from js_GC. r=Waldo. --HG-- extra : rebase_source : 920c2465f4a498d679b89811b0969e4cd6674580 --- js/src/jsgc.cpp | 84 ++++++++++++++++++++++++++++--------------------- 1 file changed, 49 insertions(+), 35 deletions(-) diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index e99ac1da5ff..143a6ffff32 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -3442,6 +3442,53 @@ FireGCEnd(JSContext *cx, JSGCInvocationKind gckind) return true; } +/* + * Process all JSSetSlotRequests for this runtime. Then, if necessary, + * change *gckindp to GC_LOCK_HELD and prepare for GC. + */ +static bool +ProcessAllSetSlotRequests(JSContext *cx, JSGCInvocationKind *gckindp) +{ + JSRuntime *rt = cx->runtime; + + while (JSSetSlotRequest *ssr = rt->setSlotRequests) { + rt->setSlotRequests = ssr->next; + AutoUnlockGC unlock(rt); + ssr->next = NULL; + ProcessSetSlotRequest(cx, ssr); + } + + /* + * If another thread has requested GC, modify *gckindp to ensure we do GC + * during the current session. + * + * Note that we have not called the GC callback yet; FireGCBegin does not + * call it if gckind == GC_SET_SLOT_REQUEST. So now we have to give up + * being the GC thread, call the GC callback, and then call BeginGCSession + * again to gather up any other threads that entered requests while we were + * in the GC callback. + * + * But do NOT call EndGCSession; that would cause JS_GC to return in + * the other threads without GC having been done. + */ + if (rt->gcLevel > 1 || rt->gcPoke || rt->gcIsNeeded) { + rt->gcLevel = 0; + rt->gcPoke = JS_FALSE; + rt->gcRunning = JS_FALSE; +#ifdef JS_THREADSAFE + rt->gcThread = NULL; +#endif + *gckindp = GC_LOCK_HELD; + if (!FireGCBegin(cx, *gckindp)) { /* GC is vetoed */ + JS_NOTIFY_GC_DONE(rt); + return false; + } + if (!BeginGCSession(cx, *gckindp)) /* another thread did GC */ + return false; + } + return true; +} + /* * The gckind flag bit GC_LOCK_HELD indicates a call from js_NewGCThing with * rt->gcLock already held, so the lock should be kept on return. @@ -3488,41 +3535,8 @@ js_GC(JSContext *cx, JSGCInvocationKind gckind) return; } - if (gckind == GC_SET_SLOT_REQUEST) { - while (JSSetSlotRequest *ssr = rt->setSlotRequests) { - rt->setSlotRequests = ssr->next; - AutoUnlockGC unlock(rt); - ssr->next = NULL; - ProcessSetSlotRequest(cx, ssr); - } - - /* - * If another thread has requested GC, we'll do it below. But note that - * we didn't call the GC callback in FireGCBegin above. - * - * So now we have to give up being the GC thread, call the GC callback, - * and then call BeginGCSession again to gather up any other threads - * that entered requests while we were in the GC callback. - * - * But do NOT call EndGCSession; that would cause JS_GC to return in - * the other threads without GC having been done. - */ - if (rt->gcLevel > 1 || rt->gcPoke || rt->gcIsNeeded) { - rt->gcLevel = 0; - rt->gcPoke = JS_FALSE; - rt->gcRunning = JS_FALSE; -#ifdef JS_THREADSAFE - rt->gcThread = NULL; -#endif - gckind = GC_LOCK_HELD; - if (!FireGCBegin(cx, gckind)) { /* GC is vetoed */ - JS_NOTIFY_GC_DONE(rt); - return; - } - if (!BeginGCSession(cx, gckind)) /* another thread did GC */ - return; - } - } + if (gckind == GC_SET_SLOT_REQUEST && !ProcessAllSetSlotRequests(cx, &gckind)) + return; if (gckind != GC_SET_SLOT_REQUEST) { if (!JS_ON_TRACE(cx))