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; }
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); }