bool
TypeInferenceOracle::analyzeTypesForInlinableCallees(JSContext *cx, JSScript *script,
                                                     Vector<JSScript*> &seen)
{
    // Don't analyze scripts which will not be inlined (but always analyze the first script).
    if (seen.length() > 0 && script->getUseCount() < js_IonOptions.usesBeforeInlining())
        return true;

    for (size_t i = 0; i < seen.length(); i++) {
        if (seen[i] == script)
            return true;
    }
    if (!seen.append(script))
        return false;

    if (!script->ensureRanInference(cx))
        return false;

    ScriptAnalysis *analysis = script->analysis();
    JS_ASSERT(analysis->ranInference());

    for (jsbytecode *pc = script->code;
         pc < script->code + script->length;
         pc += GetBytecodeLength(pc))
    {
        if (!(js_CodeSpec[*pc].format & JOF_INVOKE))
            continue;

        if (!analysis->maybeCode(pc))
            continue;

        uint32_t argc = GET_ARGC(pc);

        StackTypeSet *calleeTypes = analysis->poppedTypes(pc, argc + 1);
        if (!analyzeTypesForInlinableCallees(cx, calleeTypes, seen))
            return false;

        // For foo.call() and foo.apply(), also look for any callees in the
        // 'this' types of the call, which might be inlined by Ion.
        if (*pc == JSOP_FUNCALL || *pc == JSOP_FUNAPPLY) {
            StackTypeSet *thisTypes = analysis->poppedTypes(pc, argc);
            if (!analyzeTypesForInlinableCallees(cx, thisTypes, seen))
                return false;
        }
    }

    return true;
}
Beispiel #2
0
StackTypeSet *
TypeInferenceOracle::getCallTarget(UnrootedScript caller, uint32_t argc, jsbytecode *pc)
{
    JS_ASSERT(caller == this->script());
    JS_ASSERT(js_CodeSpec[*pc].format & JOF_INVOKE && JSOp(*pc) != JSOP_EVAL);

    ScriptAnalysis *analysis = script()->analysis();
    return analysis->poppedTypes(pc, argc + 1);
}