// Identify inlining sites
// Heuristic: In hot methods, identify monomorphic call sites to hot methods
boolean revisitScope = false;
Iterator<IRScope> hsIter = hotScopes.iterator();
IRScope hs = null;
while (hsIter.hasNext()) {
if (!revisitScope) hs = hsIter.next();
revisitScope = false;
boolean skip = false;
boolean isHotClosure = hs instanceof IRClosure;
IRScope hc = isHotClosure ? hs : null;
hs = isHotClosure ? hs.getLexicalParent() : hs;
for (BasicBlock b : hs.getCFG().getBasicBlocks()) {
for (Instr instr : b.getInstrs()) {
if ((instr instanceof CallBase) && !((CallBase)instr).inliningBlocked()) {
// System.out.println("checking: " + instr);
CallBase call = (CallBase)instr;
CallSite cs = call.getCallSite();
// System.out.println("callsite: " + cs);
if (cs != null && (cs instanceof CachingCallSite)) {
CachingCallSite ccs = (CachingCallSite)cs;
// SSS FIXME: To use this, CachingCallSite.java needs modification
// isPolymorphic or something equivalent needs to be enabled there.
if (ccs.isOptimizable()) {
CacheEntry ce = ccs.getCache();
DynamicMethod tgt = ce.method;
if (tgt instanceof InterpretedIRMethod) {
InterpretedIRMethod dynMeth = (InterpretedIRMethod)tgt;
IRScope tgtMethod = dynMeth.getIRMethod();
Instr[] instrs = tgtMethod.getInstrsForInterpretation();
// Dont inline large methods -- 200 is arbitrary
// Can be null if a previously inlined method hasn't been rebuilt
if ((instrs == null) || instrs.length > 150) continue;
RubyModule implClass = dynMeth.getImplementationClass();
int classToken = implClass.getGeneration();
String n = tgtMethod.getName();
boolean inlineCall = false;
if (isHotClosure) {
Operand clArg = call.getClosureArg(null);
inlineCall = (clArg instanceof WrappedIRClosure) && (((WrappedIRClosure)clArg).getClosure() == hc);
} else if (hotScopes.contains(tgtMethod)) {