JSContext * js::NewContext(JSRuntime *rt, size_t stackChunkSize) { JS_AbortIfWrongThread(rt); JSContext *cx = js_new<JSContext>(rt); if (!cx) return NULL; JS_ASSERT(cx->findVersion() == JSVERSION_DEFAULT); if (!cx->cycleDetectorSet.init()) { js_delete(cx); return NULL; } /* * Here the GC lock is still held after js_InitContextThreadAndLockGC took it and * the GC is not running on another thread. */ bool first = JS_CLIST_IS_EMPTY(&rt->contextList); JS_APPEND_LINK(&cx->link, &rt->contextList); js_InitRandom(cx); /* * If cx is the first context on this runtime, initialize well-known atoms, * keywords, numbers, strings and self-hosted scripts. If one of these * steps should fail, the runtime will be left in a partially initialized * state, with zeroes and nulls stored in the default-initialized remainder * of the struct. We'll clean the runtime up under DestroyContext, because * cx will be "last" as well as "first". */ if (first) { #ifdef JS_THREADSAFE JS_BeginRequest(cx); #endif bool ok = rt->staticStrings.init(cx); if (ok) ok = InitCommonAtoms(cx); if (ok) ok = rt->initSelfHosting(cx); #ifdef JS_THREADSAFE JS_EndRequest(cx); #endif if (!ok) { DestroyContext(cx, DCM_NEW_FAILED); return NULL; } } JSContextCallback cxCallback = rt->cxCallback; if (cxCallback && !cxCallback(cx, JSCONTEXT_NEW)) { DestroyContext(cx, DCM_NEW_FAILED); return NULL; } return cx; }
void lookupInEvalCache(JSLinearString *str, JSScript *callerScript, jsbytecode *pc) { lookupStr_ = str; lookup_.str = str; lookup_.callerScript = callerScript; lookup_.version = cx_->findVersion(); lookup_.pc = pc; p_ = cx_->runtime()->evalCache.lookupForAdd(lookup_); if (p_) { script_ = p_->script; cx_->runtime()->evalCache.remove(p_); script_->uncacheForEval(); } }
~EvalScriptGuard() { if (script_) { CallDestroyScriptHook(context->runtime->defaultFreeOp(), script_); script_->isActiveEval = false; script_->isCachedEval = true; if (str && IsEvalCacheCandidate(script_)) { EvalCacheLookup key(str, caller, staticLevel, context->findVersion(), context->compartment); EvalCache::AddPtr p = context->runtime->evalCache.lookupForAdd(key); if (p) context->runtime->evalCache.add(p, script_); } } }
void lookupInEvalCache(JSLinearString *str, JSScript *callerScript, jsbytecode *pc) { lookupStr_ = str; lookup_.str = str; lookup_.callerScript = callerScript; lookup_.version = cx_->findVersion(); lookup_.pc = pc; p_ = cx_->runtime->evalCache.lookupForAdd(lookup_); if (p_) { script_ = p_->script; cx_->runtime->evalCache.remove(p_); CallNewScriptHook(cx_, script_, NullPtr()); script_->isCachedEval = false; script_->isActiveEval = true; } }
void lookupInEvalCache(JSLinearString *str, JSFunction *caller, unsigned staticLevel) { lookup_.str = str; lookup_.caller = caller; lookup_.staticLevel = staticLevel; lookup_.version = cx_->findVersion(); lookup_.compartment = cx_->compartment; p_ = cx_->runtime->evalCache.lookupForAdd(lookup_); if (p_) { script_ = *p_; cx_->runtime->evalCache.remove(p_); js_CallNewScriptHook(cx_, script_, NULL); script_->isCachedEval = false; script_->isActiveEval = true; } }
void lookupInEvalCache(JSLinearString *str, JSFunction *caller, unsigned staticLevel) { this->str = str; this->caller = caller; this->staticLevel = staticLevel; EvalCacheLookup key(str, caller, staticLevel, context->findVersion(), context->compartment); EvalCache::Ptr p = context->runtime->evalCache.lookupForAdd(key); if (p) { script_ = *p; context->runtime->evalCache.remove(p); js_CallNewScriptHook(context, script_, NULL); script_->isCachedEval = false; script_->isActiveEval = true; } }
JSContext * js_NewContext(JSRuntime *rt, size_t stackChunkSize) { JSContext *cx; JSBool first; JSContextCallback cxCallback; /* * 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. */ void *mem = OffTheBooks::calloc_(sizeof *cx); if (!mem) return NULL; cx = new (mem) JSContext(rt); cx->debugHooks = &rt->globalDebugHooks; #if JS_STACK_GROWTH_DIRECTION > 0 cx->stackLimit = (jsuword) -1; #endif cx->iterValue.setMagic(JS_NO_ITER_VALUE); JS_STATIC_ASSERT(JSVERSION_DEFAULT == 0); JS_ASSERT(cx->findVersion() == JSVERSION_DEFAULT); VOUCH_DOES_NOT_REQUIRE_STACK(); JS_InitArenaPool(&cx->tempPool, "temp", TEMP_POOL_CHUNK_SIZE, sizeof(jsdouble)); JS_InitArenaPool(&cx->regExpPool, "regExp", TEMP_POOL_CHUNK_SIZE, sizeof(int)); JS_ASSERT(cx->resolveFlags == 0); if (!cx->busyArrays.init()) { Foreground::delete_(cx); return NULL; } #ifdef JS_THREADSAFE if (!js_InitContextThreadAndLockGC(cx)) { Foreground::delete_(cx); return NULL; } #endif /* * Here the GC lock is still held after js_InitContextThreadAndLockGC took it and * the GC is not running on another thread. */ for (;;) { if (rt->state == JSRTS_UP) { JS_ASSERT(!JS_CLIST_IS_EMPTY(&rt->contextList)); first = JS_FALSE; break; } if (rt->state == JSRTS_DOWN) { JS_ASSERT(JS_CLIST_IS_EMPTY(&rt->contextList)); first = JS_TRUE; rt->state = JSRTS_LAUNCHING; break; } JS_WAIT_CONDVAR(rt->stateChange, JS_NO_TIMEOUT); /* * During the above wait after we are notified about the state change * but before we wake up, another thread could enter the GC from * js_DestroyContext, bug 478336. So we must wait here to ensure that * when we exit the loop with the first flag set to true, that GC is * finished. */ js_WaitForGC(rt); } JS_APPEND_LINK(&cx->link, &rt->contextList); JS_UNLOCK_GC(rt); js_InitRandom(cx); /* * 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 * runtime will be left in a partially initialized state, with zeroes and * nulls stored in the default-initialized remainder of the struct. We'll * clean the runtime up under js_DestroyContext, because cx will be "last" * as well as "first". */ if (first) { #ifdef JS_THREADSAFE JS_BeginRequest(cx); #endif JSBool ok = js_InitCommonAtoms(cx); #ifdef JS_THREADSAFE JS_EndRequest(cx); #endif if (!ok) { js_DestroyContext(cx, JSDCM_NEW_FAILED); return NULL; } AutoLockGC lock(rt); rt->state = JSRTS_UP; JS_NOTIFY_ALL_CONDVAR(rt->stateChange); } cxCallback = rt->cxCallback; if (cxCallback && !cxCallback(cx, JSCONTEXT_NEW)) { js_DestroyContext(cx, JSDCM_NEW_FAILED); return NULL; } return cx; }
JSContext * js_NewContext(JSRuntime *rt, size_t stackChunkSize) { JS_AbortIfWrongThread(rt); /* * 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. */ JSContext *cx = OffTheBooks::new_<JSContext>(rt); if (!cx) return NULL; JS_ASSERT(cx->findVersion() == JSVERSION_DEFAULT); VOUCH_DOES_NOT_REQUIRE_STACK(); if (!cx->busyArrays.init()) { Foreground::delete_(cx); return NULL; } #ifdef JS_THREADSAFE if (!js_InitContextThreadAndLockGC(cx)) { Foreground::delete_(cx); return NULL; } #endif /* * Here the GC lock is still held after js_InitContextThreadAndLockGC took it and * the GC is not running on another thread. */ bool first; for (;;) { if (rt->state == JSRTS_UP) { JS_ASSERT(!JS_CLIST_IS_EMPTY(&rt->contextList)); first = false; break; } if (rt->state == JSRTS_DOWN) { JS_ASSERT(JS_CLIST_IS_EMPTY(&rt->contextList)); first = true; rt->state = JSRTS_LAUNCHING; break; } JS_WAIT_CONDVAR(rt->stateChange, JS_NO_TIMEOUT); /* * During the above wait after we are notified about the state change * but before we wake up, another thread could enter the GC from * js_DestroyContext, bug 478336. So we must wait here to ensure that * when we exit the loop with the first flag set to true, that GC is * finished. */ js_WaitForGC(rt); } JS_APPEND_LINK(&cx->link, &rt->contextList); JS_UNLOCK_GC(rt); js_InitRandom(cx); /* * 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 * runtime will be left in a partially initialized state, with zeroes and * nulls stored in the default-initialized remainder of the struct. We'll * clean the runtime up under js_DestroyContext, because cx will be "last" * as well as "first". */ if (first) { #ifdef JS_THREADSAFE JS_BeginRequest(cx); #endif bool ok = rt->staticStrings.init(cx); if (ok) ok = js_InitCommonAtoms(cx); #ifdef JS_THREADSAFE JS_EndRequest(cx); #endif if (!ok) { js_DestroyContext(cx, JSDCM_NEW_FAILED); return NULL; } AutoLockGC lock(rt); rt->state = JSRTS_UP; JS_NOTIFY_ALL_CONDVAR(rt->stateChange); } JSContextCallback cxCallback = rt->cxCallback; if (cxCallback && !cxCallback(cx, JSCONTEXT_NEW)) { js_DestroyContext(cx, JSDCM_NEW_FAILED); return NULL; } return cx; }
JSContext * js_NewContext(JSRuntime *rt, size_t stackChunkSize) { JS_AbortIfWrongThread(rt); /* * 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. */ JSContext *cx = OffTheBooks::new_<JSContext>(rt); if (!cx) return NULL; JS_ASSERT(cx->findVersion() == JSVERSION_DEFAULT); if (!cx->busyArrays.init()) { Foreground::delete_(cx); return NULL; } /* * Here the GC lock is still held after js_InitContextThreadAndLockGC took it and * the GC is not running on another thread. */ bool first = JS_CLIST_IS_EMPTY(&rt->contextList); JS_APPEND_LINK(&cx->link, &rt->contextList); js_InitRandom(cx); /* * 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 * runtime will be left in a partially initialized state, with zeroes and * nulls stored in the default-initialized remainder of the struct. We'll * clean the runtime up under js_DestroyContext, because cx will be "last" * as well as "first". */ if (first) { #ifdef JS_THREADSAFE JS_BeginRequest(cx); #endif bool ok = rt->staticStrings.init(cx); if (ok) ok = js_InitCommonAtoms(cx); #ifdef JS_THREADSAFE JS_EndRequest(cx); #endif if (!ok) { js_DestroyContext(cx, JSDCM_NEW_FAILED); return NULL; } } JSContextCallback cxCallback = rt->cxCallback; if (cxCallback && !cxCallback(cx, JSCONTEXT_NEW)) { js_DestroyContext(cx, JSDCM_NEW_FAILED); return NULL; } return cx; }