Ejemplo n.º 1
0
    void beginCompile(HandleFunction fun) {
        if (!active[SpewCompile])
            return;

        spew(SpewCompile, "COMPILE %p:%s:%u",
             fun.get(), fun->nonLazyScript()->filename, fun->nonLazyScript()->lineno);
        depth++;
    }
Ejemplo n.º 2
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.º 3
0
static bool
CheckArgumentsWithinEval(JSContext *cx, Parser<FullParseHandler> &parser, HandleFunction fun)
{
    if (fun->hasRest()) {
        // It's an error to use |arguments| in a function that has a rest
        // parameter.
        parser.report(ParseError, false, NULL, JSMSG_ARGUMENTS_AND_REST);
        return false;
    }

    // Force construction of arguments objects for functions that use
    // |arguments| within an eval.
    RootedScript script(cx, fun->nonLazyScript());
    if (script->argumentsHasVarBinding()) {
        if (!JSScript::argumentsOptimizationFailed(cx, script))
            return false;
    }

    // It's an error to use |arguments| in a legacy generator expression.
    if (script->isGeneratorExp && script->isLegacyGenerator) {
        parser.report(ParseError, false, NULL, JSMSG_BAD_GENEXP_BODY, js_arguments_str);
        return false;
    }

    return true;
}
Ejemplo n.º 4
0
bool
FrameIter::matchCallee(JSContext *cx, HandleFunction fun) const
{
    RootedFunction currentCallee(cx, calleeTemplate());

    // As we do not know if the calleeTemplate is the real function, or the
    // template from which it would be cloned, we compare properties which are
    // stable across the cloning of JSFunctions.
    if (((currentCallee->flags() ^ fun->flags()) & JSFunction::STABLE_ACROSS_CLONES) != 0 ||
        currentCallee->nargs() != fun->nargs())
    {
        return false;
    }

    // Only some lambdas are optimized in a way which cannot be recovered without
    // invalidating the frame. Thus, if one of the function is not a lambda we can just
    // compare it against the calleeTemplate.
    if (!fun->isLambda() || !currentCallee->isLambda())
        return currentCallee == fun;

    // Use the same condition as |js::CloneFunctionObject|, to know if we should
    // expect both functions to have the same JSScript. If so, and if they are
    // different, then they cannot be equal.
    bool useSameScript = CloneFunctionObjectUseSameScript(fun->compartment(), currentCallee);
    if (useSameScript &&
        (currentCallee->hasScript() != fun->hasScript() ||
         currentCallee->nonLazyScript() != fun->nonLazyScript()))
    {
        return false;
    }

    // If none of the previous filters worked, then take the risk of
    // invalidating the frame to identify the JSFunction.
    return callee(cx) == fun;
}
Ejemplo n.º 5
0
JS_GetFunctionScript(JSContext *cx, HandleFunction fun)
{
    if (fun->isNative())
        return nullptr;
    if (fun->isInterpretedLazy()) {
        AutoCompartment funCompartment(cx, fun);
        JSScript *script = fun->getOrCreateScript(cx);
        if (!script)
            MOZ_CRASH();
        return script;
    }
    return fun->nonLazyScript();
}
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
0
    ParallelIonInvoke(JSContext *cx, HandleFunction callee, uint32_t argc)
      : argc_(argc),
        args(argv_ + 2)
    {
        JS_ASSERT(argc <= maxArgc + 2);

        // Set 'callee' and 'this'.
        argv_[0] = ObjectValue(*callee);
        argv_[1] = UndefinedValue();

        // Find JIT code pointer.
        IonScript *ion = callee->nonLazyScript()->parallelIonScript();
        IonCode *code = ion->method();
        jitcode_ = code->raw();
        enter_ = cx->compartment->ionCompartment()->enterJIT();
        calleeToken_ = CalleeToParallelToken(callee);
    }
static bool
CheckArgumentsWithinEval(JSContext *cx, Parser &parser, HandleFunction fun)
{
    if (fun->hasRest()) {
        // It's an error to use |arguments| in a function that has a rest
        // parameter.
        parser.reportError(NULL, JSMSG_ARGUMENTS_AND_REST);
        return false;
    }

    // Force construction of arguments objects for functions that use
    // |arguments| within an eval.
    RootedScript script(cx, fun->nonLazyScript());
    if (script->argumentsHasVarBinding()) {
        if (!JSScript::argumentsOptimizationFailed(cx, script))
            return false;
    }

    return true;
}