зеркало из https://github.com/mozilla/pjs.git
bug 561657 - Replacing js_CountThreadRequests with an explicit counter. r=jorendorff
This commit is contained in:
Родитель
1d40dd7271
Коммит
2b9842f7ad
|
@ -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);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче