Ejemplo n.º 1
0
RawFunction
js::CloneFunctionAtCallsite(JSContext *cx, HandleFunction fun, HandleScript script, jsbytecode *pc)
{
    JS_ASSERT(cx->typeInferenceEnabled());
    JS_ASSERT(fun->nonLazyScript()->shouldCloneAtCallsite);
    JS_ASSERT(!fun->nonLazyScript()->enclosingStaticScope());
    JS_ASSERT(types::UseNewTypeForClone(fun));

    typedef CallsiteCloneKey Key;
    typedef CallsiteCloneTable Table;

    Table &table = cx->compartment->callsiteClones;
    if (!table.initialized() && !table.init())
        return NULL;

    Key key;
    SkipRoot skipKey(cx, &key); /* Stop the analysis complaining about unrooted key. */
    key.script = script;
    key.offset = pc - script->code;
    key.original = fun;

    Table::AddPtr p = table.lookupForAdd(key);
    SkipRoot skipHash(cx, &p); /* Prevent the hash from being poisoned. */
    if (p)
        return p->value;

    RootedObject parent(cx, fun->environment());
    RootedFunction clone(cx, CloneFunctionObject(cx, fun, parent));
    if (!clone)
        return NULL;

    /*
     * Store a link back to the original for function.caller and avoid cloning
     * clones.
     */
    clone->nonLazyScript()->shouldCloneAtCallsite = false;
    clone->nonLazyScript()->isCallsiteClone = true;
    clone->nonLazyScript()->setOriginalFunctionObject(fun);

    /* Recalculate the hash if script or fun have been moved. */
    if (key.script != script && key.original != fun) {
        key.script = script;
        key.original = fun;
        Table::AddPtr p = table.lookupForAdd(key);
        JS_ASSERT(!p);
    }

    if (!table.relookupOrAdd(p, key, clone.get()))
        return NULL;

    return clone;
}
Ejemplo n.º 2
0
RawFunction
js::CloneFunctionAtCallsite(JSContext *cx, HandleFunction fun, HandleScript script, jsbytecode *pc)
{
    JS_ASSERT(cx->typeInferenceEnabled());
    JS_ASSERT(fun->isCloneAtCallsite());
    JS_ASSERT(types::UseNewTypeForClone(fun));
    JS_ASSERT(!fun->nonLazyScript()->enclosingStaticScope());

    typedef CallsiteCloneKey Key;
    typedef CallsiteCloneTable Table;

    Table &table = cx->compartment->callsiteClones;
    if (!table.initialized() && !table.init())
        return NULL;

    Key key;
    key.script = script;
    key.offset = pc - script->code;
    key.original = fun;

    Table::AddPtr p = table.lookupForAdd(key);
    SkipRoot skipHash(cx, &p); /* Prevent the hash from being poisoned. */
    if (p)
        return p->value;

    RootedObject parent(cx, fun->environment());
    RootedFunction clone(cx, CloneFunctionObject(cx, fun, parent,
                                                 JSFunction::ExtendedFinalizeKind));
    if (!clone)
        return NULL;

    // Store a link back to the original for function.caller.
    clone->setExtendedSlot(0, ObjectValue(*fun));

    // Recalculate the hash if script or fun have been moved.
    if (key.script != script && key.original != fun) {
        key.script = script;
        key.original = fun;
        Table::AddPtr p = table.lookupForAdd(key);
        JS_ASSERT(!p);
    }

    if (!table.relookupOrAdd(p, key, clone.get()))
        return NULL;

    return clone;
}