Esempio n. 1
0
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;
}
Esempio n. 2
0
 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();
     }
 }
Esempio n. 3
0
 ~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_);
         }
     }
 }
Esempio n. 4
0
 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;
     }
 }
Esempio n. 6
0
 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;
     }
 }
Esempio n. 7
0
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;
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
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;
}