Leaving outermost request should js_LeaveTrace (480301, r=brendan).

This commit is contained in:
jorendorff 2009-04-20 18:22:00 -07:00
parent 7f4de719f8
commit e1b8077e65
5 changed files with 59 additions and 8 deletions

View File

@ -953,6 +953,8 @@ JS_EndRequest(JSContext *cx)
JS_ASSERT(cx->requestDepth > 0);
JS_ASSERT(cx->outstandingRequests > 0);
if (cx->requestDepth == 1) {
js_LeaveTrace(cx); /* for GC safety */
/* Lock before clearing to interlock with ClaimScope, in jslock.c. */
rt = cx->runtime;
JS_LOCK_GC(rt);

View File

@ -851,6 +851,14 @@ js_DiscountRequestsForGC(JSContext *cx)
JS_ASSERT(cx->thread);
JS_ASSERT(cx->runtime->gcThread != cx->thread);
#ifdef JS_TRACER
if (JS_ON_TRACE(cx)) {
JS_UNLOCK_GC(cx->runtime);
js_LeaveTrace(cx);
JS_LOCK_GC(cx->runtime);
}
#endif
requestDebit = js_CountThreadRequests(cx);
if (requestDebit != 0) {
JSRuntime *rt = cx->runtime;

View File

@ -178,6 +178,11 @@ struct JSTraceMonitor {
typedef struct InterpStruct InterpStruct;
/*
* N.B. JS_ON_TRACE(cx) is true if JIT code is on the stack in the current
* thread, regardless of whether cx is the context in which that trace is
* executing. cx must be a context on the current thread.
*/
#ifdef JS_TRACER
# define JS_ON_TRACE(cx) (JS_TRACE_MONITOR(cx).onTrace)
#else
@ -230,6 +235,11 @@ struct JSThreadData {
/* Property cache for faster call/get/set invocation. */
JSPropertyCache propertyCache;
/*
* N.B. JS_ON_TRACE(cx) is true if JIT code is on the stack in the current
* thread, regardless of whether cx is the context in which that trace is
* executing. cx must be a context on the current thread.
*/
#ifdef JS_TRACER
/* Trace-tree JIT recorder/interpreter state. */
JSTraceMonitor traceMonitor;

View File

@ -628,6 +628,14 @@ ClaimTitle(JSTitle *title, JSContext *cx)
* rt->titleSharingDone.
*/
requestDebit = js_DiscountRequestsForGC(cx);
if (title->ownercx != ownercx) {
/*
* js_DiscountRequestsForGC released and reacquired the GC lock,
* and the title was taken or shared. Start over.
*/
js_RecountRequestsAfterGC(rt, requestDebit);
continue;
}
/*
* We know that some other thread's context owns title, which is now
@ -652,7 +660,7 @@ ClaimTitle(JSTitle *title, JSContext *cx)
* Don't clear titleToShare until after we're through waiting on
* all condition variables protected by rt->gcLock -- that includes
* rt->titleSharingDone *and* rt->gcDone (hidden in the call to
* js_ActivateRequestAfterGC immediately above).
* js_RecountRequestsAfterGC immediately above).
*
* Otherwise, the GC could easily deadlock with another thread that
* owns a title wanted by a finalizer. By keeping cx->titleToShare

View File

@ -5030,15 +5030,38 @@ js_DeepBail(JSContext *cx)
{
JS_ASSERT(JS_ON_TRACE(cx));
/* It's a bug if a non-FAIL_STATUS builtin gets here. */
JS_ASSERT(cx->bailExit);
/*
* Exactly one context on the current thread is on trace. Find out which
* one. (Most callers cannot guarantee that it's cx.)
*/
JSContext *tracecx = NULL;
#ifdef JS_THREADSAFE
JSCList *head = &cx->thread->contextList;
for (JSCList *link = head->next; link != head; link = link->next) {
JSContext *acx = CX_FROM_THREAD_LINKS(link);
JS_ASSERT(!(acx->requestDepth == 0 && acx->bailExit));
#else
JSContext *acx, *iter = NULL;
while ((acx = js_ContextIterator(cx->runtime, JS_TRUE, &iter)) != NULL) {
#endif
if (acx->bailExit) {
JS_ASSERT(!tracecx);
tracecx = acx;
#ifndef DEBUG
break;
#endif
}
}
JS_TRACE_MONITOR(cx).onTrace = false;
JS_TRACE_MONITOR(cx).prohibitFlush++;
/* It's a bug if a non-FAIL_STATUS builtin gets here. */
JS_ASSERT(tracecx->bailExit);
JS_TRACE_MONITOR(tracecx).onTrace = false;
JS_TRACE_MONITOR(tracecx).prohibitFlush++;
debug_only_v(printf("Deep bail.\n");)
LeaveTree(*cx->interpState, cx->bailExit);
cx->bailExit = NULL;
cx->interpState->builtinStatus |= JSBUILTIN_BAILED;
LeaveTree(*tracecx->interpState, tracecx->bailExit);
tracecx->bailExit = NULL;
tracecx->interpState->builtinStatus |= JSBUILTIN_BAILED;
}
JS_REQUIRES_STACK jsval&