bug 561657 - Replacing js_CountThreadRequests with an explicit counter. r=jorendorff

This commit is contained in:
Igor Bukanov 2010-05-27 16:57:55 +02:00
Родитель 1d40dd7271
Коммит 2b9842f7ad
5 изменённых файлов: 49 добавлений и 68 удалений

Просмотреть файл

@ -780,6 +780,7 @@ JS_BeginRequest(JSContext *cx)
/* Indicate that a request is running. */
rt->requestCount++;
cx->thread->contextsInRequests++;
cx->requestDepth = 1;
cx->outstandingRequests++;
return;
@ -799,12 +800,14 @@ JS_EndRequest(JSContext *cx)
JS_ASSERT(CURRENT_THREAD_IS_ME(cx->thread));
JS_ASSERT(cx->requestDepth > 0);
JS_ASSERT(cx->outstandingRequests > 0);
JS_ASSERT(cx->thread->contextsInRequests > 0);
if (cx->requestDepth == 1) {
LeaveTrace(cx); /* for GC safety */
/* Lock before clearing to interlock with ClaimScope, in jslock.c. */
rt = cx->runtime;
AutoLockGC lock(rt);
cx->requestDepth = 0;
cx->outstandingRequests--;
@ -813,11 +816,11 @@ JS_EndRequest(JSContext *cx)
/* Give the GC a chance to run if this was the last request running. */
JS_ASSERT(rt->requestCount > 0);
rt->requestCount--;
cx->thread->contextsInRequests--;
if (rt->requestCount == 0)
JS_NOTIFY_REQUEST_DONE(rt);
return;
}
cx->requestDepth--;
cx->outstandingRequests--;
#endif

Просмотреть файл

@ -1247,48 +1247,6 @@ js_NextActiveContext(JSRuntime *rt, JSContext *cx)
#endif
}
#ifdef JS_THREADSAFE
uint32
js_CountThreadRequests(JSContext *cx)
{
JSCList *head, *link;
uint32 nrequests;
JS_ASSERT(CURRENT_THREAD_IS_ME(cx->thread));
head = &cx->thread->contextList;
nrequests = 0;
for (link = head->next; link != head; link = link->next) {
JSContext *acx = CX_FROM_THREAD_LINKS(link);
JS_ASSERT(acx->thread == cx->thread);
if (acx->requestDepth)
nrequests++;
}
return nrequests;
}
/*
* If the GC is running and we're called on another thread, wait for this GC
* activation to finish. We can safely wait here without fear of deadlock (in
* the case where we are called within a request on another thread's context)
* because the GC doesn't set rt->gcRunning until after it has waited for all
* active requests to end.
*
* We call here js_CurrentThreadId() after checking for rt->gcRunning to avoid
* expensive calls when the GC is not running.
*/
void
js_WaitForGC(JSRuntime *rt)
{
if (rt->gcRunning && rt->gcThread->id != js_CurrentThreadId()) {
do {
JS_AWAIT_GC_DONE(rt);
} while (rt->gcRunning);
}
}
#endif
static JSDHashNumber
resolving_HashKey(JSDHashTable *table, const void *ptr)
{

Просмотреть файл

@ -1076,6 +1076,12 @@ struct JSThread {
*/
bool gcWaiting;
/*
* Number of JSContext instances that are in requests on this thread. For
* such instances JSContext::requestDepth > 0 holds.
*/
uint32 contextsInRequests;
/* Factored out of JSThread for !JS_THREADSAFE embedding in JSRuntime. */
JSThreadData data;
};
@ -2705,29 +2711,6 @@ js_ContextIterator(JSRuntime *rt, JSBool unlocked, JSContext **iterp);
extern JS_FRIEND_API(JSContext *)
js_NextActiveContext(JSRuntime *, JSContext *);
#ifdef JS_THREADSAFE
/*
* Count the number of contexts entered requests on the current thread.
*/
extern uint32
js_CountThreadRequests(JSContext *cx);
/*
* This is a helper for code at can potentially run outside JS request to
* ensure that the GC is not running when the function returns.
*
* This function must be called with the GC lock held.
*/
extern void
js_WaitForGC(JSRuntime *rt);
#else /* !JS_THREADSAFE */
# define js_WaitForGC(rt) ((void) 0)
#endif
/*
* JSClass.resolve and watchpoint recursion damping machinery.
*/

Просмотреть файл

@ -2941,6 +2941,27 @@ GC(JSContext *cx GCTIMER_PARAM)
}
#ifdef JS_THREADSAFE
/*
* If the GC is running and we're called on another thread, wait for this GC
* activation to finish. We can safely wait here without fear of deadlock (in
* the case where we are called within a request on another thread's context)
* because the GC doesn't set rt->gcRunning until after it has waited for all
* active requests to end.
*
* We call here js_CurrentThreadId() after checking for rt->gcState to avoid
* an expensive call when the GC is not running.
*/
void
js_WaitForGC(JSRuntime *rt)
{
if (rt->gcRunning && rt->gcThread->id != js_CurrentThreadId()) {
do {
JS_AWAIT_GC_DONE(rt);
} while (rt->gcRunning);
}
}
/*
* GC is running on another thread. Temporarily suspend all requests running
* on the current thread and wait until the GC is done.
@ -2952,7 +2973,7 @@ LetOtherGCFinish(JSContext *cx)
JS_ASSERT(rt->gcThread);
JS_ASSERT(cx->thread != rt->gcThread);
size_t requestDebit = js_CountThreadRequests(cx);
size_t requestDebit = cx->thread->contextsInRequests;
JS_ASSERT(requestDebit <= rt->requestCount);
#ifdef JS_TRACER
JS_ASSERT_IF(requestDebit == 0, !JS_ON_TRACE(cx));
@ -3034,7 +3055,7 @@ BeginGCSession(JSContext *cx)
* JS_NOTIFY_REQUEST_DONE, which will wake us up, is only called on
* rt->requestCount transitions to 0.
*/
size_t requestDebit = js_CountThreadRequests(cx);
size_t requestDebit = cx->thread->contextsInRequests;
JS_ASSERT_IF(cx->requestDepth != 0, requestDebit >= 1);
JS_ASSERT(requestDebit <= rt->requestCount);
if (requestDebit != rt->requestCount) {

Просмотреть файл

@ -227,6 +227,22 @@ extern bool
js_SetProtoOrParentCheckingForCycles(JSContext *cx, JSObject *obj,
uint32 slot, JSObject *pobj);
#ifdef JS_THREADSAFE
/*
* This is a helper for code at can potentially run outside JS request to
* ensure that the GC is not running when the function returns.
*
* This function must be called with the GC lock held.
*/
extern void
js_WaitForGC(JSRuntime *rt);
#else /* !JS_THREADSAFE */
# define js_WaitForGC(rt) ((void) 0)
#endif
extern void
js_CallGCMarker(JSTracer *trc, void *thing, uint32 kind);