public void inlineMethod(IRScope method, RubyModule implClass, int classToken, BasicBlock basicBlock, CallBase call) { // Inline depends(cfg()); new CFGInliner(cfg).inlineMethod(method, implClass, classToken, basicBlock, call); // Reset state resetState(); // Re-run opts for (CompilerPass pass: getManager().getInliningCompilerPasses(this)) { pass.run(this); } }
if (isRecursiveInline(scopeToInline)) return "cannot inline recursive scopes"; if (debug) printInlineDebugPrologue(scopeToInline, call); callBB = findCallsiteBB(call); if (callBB == null) { if (debug) printInlineCannotFindCallsiteBB(call); return "cannot find callsite in host scope: " + call; } else { if (debug) printInlineFoundBB(callBB); BasicBlock afterInlineBB = callBB.splitAtInstruction(call, splitBBLabel, false); BasicBlock beforeInlineBB = callBB; connectOuterEdges(beforeInlineBB, afterInlineBB); if (debug) printInlineSplitBBs(beforeInlineBB, afterInlineBB); SimpleCloneInfo hostCloneInfo = cloneHost ? cloneHostInstrs() : null; Variable callReceiverVar = getReceiverVariable(call.getReceiver()); InlineCloneInfo ii = new InlineCloneInfo(call, cfg, callReceiverVar, scopeToInline); if (isRecursiveInline(scopeToInline)) { CFG selfClone = cloneSelf(ii); inlineClosureAtYieldSite(ii, ((WrappedIRClosure) closureArg).getClosure(), (BasicBlock) t.a, (YieldInstr) t.b); addMissingJumps(); if (debug) printInlineEpilogue();
CFG selfClone = cloneSelf(ii); inlineClosureAtYieldSite(ii, ((WrappedIRClosure) closureArg).getClosure(), (BasicBlock) t.a, (YieldInstr) t.b);
connectOuterEdges(beforeInlineBB, afterInlineBB); if (debug) printInlineSplitBBs(beforeInlineBB, afterInlineBB);
if (isRecursiveInline(scopeToInline)) return "cannot inline recursive scopes"; if (debug) printInlineDebugPrologue(scopeToInline, call); callBB = findCallsiteBB(call); if (callBB == null) { if (debug) printInlineCannotFindCallsiteBB(call); return "cannot find callsite in host scope: " + call; } else { if (debug) printInlineFoundBB(callBB); BasicBlock afterInlineBB = callBB.splitAtInstruction(call, splitBBLabel, false); BasicBlock beforeInlineBB = callBB; connectOuterEdges(beforeInlineBB, afterInlineBB); if (debug) printInlineSplitBBs(beforeInlineBB, afterInlineBB); SimpleCloneInfo hostCloneInfo = cloneHost ? cloneHostInstrs() : null; Variable callReceiverVar = getReceiverVariable(call.getReceiver()); InlineCloneInfo ii = new InlineCloneInfo(call, cfg, callReceiverVar, scopeToInline); if (isRecursiveInline(scopeToInline)) { CFG selfClone = cloneSelf(ii); inlineClosureAtYieldSite(ii, ((WrappedIRClosure) closureArg).getClosure(), (BasicBlock) t.a, (YieldInstr) t.b); addMissingJumps(); if (debug) printInlineEpilogue();
CFG selfClone = cloneSelf(ii); inlineClosureAtYieldSite(ii, ((WrappedIRClosure) closureArg).getClosure(), (BasicBlock) t.a, (YieldInstr) t.b);
connectOuterEdges(beforeInlineBB, afterInlineBB); if (debug) printInlineSplitBBs(beforeInlineBB, afterInlineBB);
public void inlineMethod(IRScope method, RubyModule implClass, int classToken, BasicBlock basicBlock, CallBase call) { // Inline depends(cfg()); new CFGInliner(cfg).inlineMethod(method, implClass, classToken, basicBlock, call); // Reset state resetState(); // Re-run opts for (CompilerPass pass: getManager().getInliningCompilerPasses(this)) { pass.run(this); } }
private FullInterpreterContext inlineMethodCommon(IRMethod methodToInline, long callsiteId, int classToken, boolean cloneHost) { alreadyHasInline = true; // FIXME: Tried prepareFullBuild here and for methodToInline and a couple of missing callsiteid errors happened in spec:ruby:fast if (getFullInterpreterContext() == null) return inlineFailed("inline into startup interpreter scope"); // FIXME: So a potential problem is closures contain local variables in the method being inlined then we will nuke // those scoped variables and the closure cannot see them. One idea is since for deoptimization we will need to // create a scope restore table we will have a list of all lvars -> temps. Since this will be a map we depend on // for restoring scope we can probably make an temp variable which will look for values from this table. Even in // that solution we need access to the temp table from the closure so I am unsure that will work. // // Another solution is to force inline those closures but that only works if the methods they are calling through // are IR methods (or are native but can be substituted with IR methods). // // Note: we can look for scoped methods and make this less conservative. if (!methodToInline.getClosures().isEmpty()) return inlineFailed("inline a method which contains nested closures"); FullInterpreterContext newContext = getFullInterpreterContext().duplicate(); BasicBlock basicBlock = newContext.findBasicBlockOf(callsiteId); CallBase call = (CallBase) basicBlock.siteOf(callsiteId); // we know it is callBase and not a yield RubyModule implClass = compilable.getImplementationClass(); String error = new CFGInliner(newContext).inlineMethod(methodToInline, implClass, classToken, basicBlock, call, cloneHost); return error == null ? newContext : inlineFailed(error); }
private FullInterpreterContext inlineMethodCommon(IRMethod methodToInline, long callsiteId, int classToken, boolean cloneHost) { alreadyHasInline = true; // FIXME: Tried prepareFullBuild here and for methodToInline and a couple of missing callsiteid errors happened in spec:ruby:fast if (getFullInterpreterContext() == null) return inlineFailed("inline into startup interpreter scope"); // FIXME: So a potential problem is closures contain local variables in the method being inlined then we will nuke // those scoped variables and the closure cannot see them. One idea is since for deoptimization we will need to // create a scope restore table we will have a list of all lvars -> temps. Since this will be a map we depend on // for restoring scope we can probably make an temp variable which will look for values from this table. Even in // that solution we need access to the temp table from the closure so I am unsure that will work. // // Another solution is to force inline those closures but that only works if the methods they are calling through // are IR methods (or are native but can be substituted with IR methods). // // Note: we can look for scoped methods and make this less conservative. if (!methodToInline.getClosures().isEmpty()) return inlineFailed("inline a method which contains nested closures"); FullInterpreterContext newContext = getFullInterpreterContext().duplicate(); BasicBlock basicBlock = newContext.findBasicBlockOf(callsiteId); CallBase call = (CallBase) basicBlock.siteOf(callsiteId); // we know it is callBase and not a yield RubyModule implClass = compilable.getImplementationClass(); String error = new CFGInliner(newContext).inlineMethod(methodToInline, implClass, classToken, basicBlock, call, cloneHost); return error == null ? newContext : inlineFailed(error); }