зеркало из https://github.com/mozilla/gecko-dev.git
bug 477021 - make sure that js_(New|Destroy)Context() do not race against the GC. r=brendan
This commit is contained in:
Родитель
6ee38d80d3
Коммит
befa19923d
|
@ -237,33 +237,47 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize)
|
|||
return NULL;
|
||||
#endif
|
||||
|
||||
cx = (JSContext *) malloc(sizeof *cx);
|
||||
/*
|
||||
* We need to initialize the new context fully before adding it to the
|
||||
* runtime list. After that it can be accessed from another thread via
|
||||
* js_ContextIterator.
|
||||
*/
|
||||
cx = (JSContext *) calloc(1, sizeof *cx);
|
||||
if (!cx)
|
||||
return NULL;
|
||||
memset(cx, 0, sizeof *cx);
|
||||
|
||||
cx->runtime = rt;
|
||||
js_InitOperationLimit(cx);
|
||||
cx->debugHooks = &rt->globalDebugHooks;
|
||||
#if JS_STACK_GROWTH_DIRECTION > 0
|
||||
cx->stackLimit = (jsuword)-1;
|
||||
cx->stackLimit = (jsuword) -1;
|
||||
#endif
|
||||
cx->scriptStackQuota = JS_DEFAULT_SCRIPT_STACK_QUOTA;
|
||||
#ifdef JS_THREADSAFE
|
||||
cx->gcLocalFreeLists = (JSGCFreeListSet *) &js_GCEmptyFreeListSet;
|
||||
|
||||
/*
|
||||
* At this point cx is not on rt->contextList. Thus we do not need to
|
||||
* prevent a race against the GC when adding cx to JSThread.contextList.
|
||||
*/
|
||||
js_InitContextThread(cx, thread);
|
||||
#endif
|
||||
JS_STATIC_ASSERT(JSVERSION_DEFAULT == 0);
|
||||
JS_ASSERT(cx->version == JSVERSION_DEFAULT);
|
||||
VOUCH_DOES_NOT_REQUIRE_STACK();
|
||||
JS_INIT_ARENA_POOL(&cx->stackPool, "stack", stackChunkSize, sizeof(jsval),
|
||||
&cx->scriptStackQuota);
|
||||
|
||||
JS_INIT_ARENA_POOL(&cx->tempPool, "temp",
|
||||
1024, /* FIXME: bug 421435 */
|
||||
sizeof(jsdouble), &cx->scriptStackQuota);
|
||||
|
||||
js_InitRegExpStatics(cx);
|
||||
JS_ASSERT(cx->resolveFlags == 0);
|
||||
|
||||
JS_LOCK_GC(rt);
|
||||
for (;;) {
|
||||
first = (rt->contextList.next == &rt->contextList);
|
||||
if (rt->state == JSRTS_UP) {
|
||||
JS_ASSERT(!first);
|
||||
|
||||
/* Ensure that it is safe to update rt->contextList below. */
|
||||
js_WaitForGC(rt);
|
||||
break;
|
||||
}
|
||||
if (rt->state == JSRTS_DOWN) {
|
||||
|
@ -276,26 +290,6 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize)
|
|||
JS_APPEND_LINK(&cx->link, &rt->contextList);
|
||||
JS_UNLOCK_GC(rt);
|
||||
|
||||
/*
|
||||
* First we do the infallible, every-time per-context initializations.
|
||||
* Should a later, fallible initialization (js_InitRegExpStatics, e.g.,
|
||||
* or the stuff under 'if (first)' below) fail, at least the version
|
||||
* and arena-pools will be valid and safe to use (say, from the last GC
|
||||
* done by js_DestroyContext).
|
||||
*/
|
||||
cx->version = JSVERSION_DEFAULT;
|
||||
VOUCH_DOES_NOT_REQUIRE_STACK();
|
||||
JS_INIT_ARENA_POOL(&cx->stackPool, "stack", stackChunkSize, sizeof(jsval),
|
||||
&cx->scriptStackQuota);
|
||||
|
||||
JS_INIT_ARENA_POOL(&cx->tempPool, "temp",
|
||||
1024, /* FIXME: bug 421435 */
|
||||
sizeof(jsdouble), &cx->scriptStackQuota);
|
||||
|
||||
js_InitRegExpStatics(cx);
|
||||
|
||||
cx->resolveFlags = 0;
|
||||
|
||||
/*
|
||||
* If cx is the first context on this runtime, initialize well-known atoms,
|
||||
* keywords, numbers, and strings. If one of these steps should fail, the
|
||||
|
@ -437,16 +431,21 @@ js_DestroyContext(JSContext *cx, JSDestroyContextMode mode)
|
|||
}
|
||||
}
|
||||
|
||||
/* Remove cx from context list first. */
|
||||
JS_LOCK_GC(rt);
|
||||
JS_ASSERT(rt->state == JSRTS_UP || rt->state == JSRTS_LAUNCHING);
|
||||
#ifdef JS_THREADSAFE
|
||||
/*
|
||||
* Typically we are called outside a request, so ensure that the GC is not
|
||||
* running before removing the context from rt->contextList, see bug 477021.
|
||||
*/
|
||||
if (cx->requestDepth == 0)
|
||||
js_WaitForGC(rt);
|
||||
js_RevokeGCLocalFreeLists(cx);
|
||||
#endif
|
||||
JS_REMOVE_LINK(&cx->link);
|
||||
last = (rt->contextList.next == &rt->contextList);
|
||||
if (last)
|
||||
rt->state = JSRTS_LANDING;
|
||||
#ifdef JS_THREADSAFE
|
||||
js_RevokeGCLocalFreeLists(cx);
|
||||
#endif
|
||||
JS_UNLOCK_GC(rt);
|
||||
|
||||
if (last) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче