public InlinerInfo cloneForInliningClosure() { InlinerInfo clone = new InlinerInfo(); clone.varRenameMap = new HashMap<Variable, Variable>(); clone.lblRenameMap = new HashMap<Label, Label>(); clone.bbRenameMap = new HashMap<BasicBlock, BasicBlock>(); clone.call = this.call; clone.callArgs = this.callArgs; clone.callerCFG = this.callerCFG; clone.callReceiver = this.callReceiver; clone.inClosureCloneMode = false; clone.inClosureInlineMode = true; clone.canMapArgsStatically = false; return clone; }
@Override public Instr cloneForInlining(InlinerInfo ii) { if (ii.canMapArgsStatically()) { // FIXME: Check this return new CopyInstr(ii.getRenamedVariable(result), ii.getArg(argIndex, true)); } else { return new RestArgMultipleAsgnInstr(ii.getRenamedVariable(result), ii.getArgs(), argIndex, (numUsedArgs - argIndex), argIndex); } }
@Override public Instr cloneForInlinedScope(InlinerInfo ii) { if (ii.canMapArgsStatically()) { // Since we know arity at a callsite, arity check passes or we have an ArgumentError int numArgs = ii.getArgsCount(); if ((numArgs < required) || ((rest == -1) && (numArgs > (required + opt)))) { return new RaiseArgumentErrorInstr(required, opt, rest, rest); } return null; } else { return new CheckArgsArrayArityInstr(ii.getArgs(), required, opt, rest); } }
@Override public Instr cloneForInlinedScope(InlinerInfo ii) { // SSS FIXME: This is not strictly correct -- we have to wrap the block into an // operand type that converts the static code block to a proc which is a closure. if (ii.getCallClosure() instanceof WrappedIRClosure) return NopInstr.NOP; else return new CopyInstr(ii.getRenamedVariable(result), ii.getCallClosure()); }
InlinerInfo ii = new InlinerInfo(call, cfg); Label splitBBLabel = hostScope.getNewLabel(); BasicBlock splitBB; BasicBlock rx = ii.getRenamedBB(x); for (Edge<BasicBlock> e : methodCFG.getOutgoingEdges(x)) { BasicBlock b = e.getDestination().getData(); if (b != mExit) cfg.addEdge(rx, ii.getRenamedBB(b), e.getType()); BasicBlock destination = e.getDestination().getData(); if (destination != mExit) { BasicBlock dstBB = ii.getRenamedBB(destination); if (!ii.canMapArgsStatically()) { dstBB.addInstr(new ToAryInstr((Variable)ii.getArgs(), new Array(call.getCallArgs()), cfg.getScope().getManager().getTrue())); BasicBlock source = e.getSource().getData(); if (source != mEntry) { BasicBlock clonedSource = ii.getRenamedBB(source); if (e.getType() == EdgeType.EXCEPTION) { BasicBlock xRenamed = ii.getRenamedBB(x); BasicBlock xProtector = methodCFG.getRescuerBBFor(x); if (xProtector != null) { cfg.setRescuerBB(xRenamed, ii.getRenamedBB(xProtector)); } else if (callBBrescuer != null) { cfg.setRescuerBB(xRenamed, callBBrescuer); cfg.setEnsurerBB(xRenamed, ii.getRenamedBB(xEnsurer)); } else if (callBBensurer != null) {
ii = ii.cloneForInliningClosure(); ii.setupYieldArgsAndYieldResult(yield, yieldBB, cl.getBlockBody().arity()); BasicBlock bClone = ii.getRenamedBB(b); for (Edge<BasicBlock> e : closureCFG.getOutgoingEdges(b)) { BasicBlock edst = e.getDestination().getData(); if (edst != cExit) cfg.addEdge(bClone, ii.getRenamedBB(edst), e.getType()); BasicBlock destination = e.getDestination().getData(); if (destination != cExit) { cfg.addEdge(yieldBB, ii.getRenamedBB(destination), CFG.EdgeType.FALL_THROUGH); BasicBlock source = e.getSource().getData(); if (source != cEntry) { BasicBlock clonedSource = ii.getRenamedBB(source); if (e.getType() == EdgeType.EXCEPTION) { BasicBlock cbProtector = ii.getRenamedBB(closureCFG.getRescuerBBFor(cb)); if (cbProtector != null) { cfg.setRescuerBB(cb, cbProtector); BasicBlock cbEnsurer = ii.getRenamedBB(closureCFG.getEnsurerBBFor(cb)); if (cbEnsurer != null) { cfg.setEnsurerBB(cb, cbEnsurer);
public IRClosure cloneForClonedInstr(InlinerInfo ii) { IRClosure clonedClosure = new IRClosure(this, ii.getNewLexicalParentForClosure()); clonedClosure.isForLoopBody = this.isForLoopBody; clonedClosure.nestingDepth = this.nestingDepth; clonedClosure.parameterList = this.parameterList; // Create a new inliner info object ii = ii.cloneForCloningClosure(clonedClosure); // clone the cfg, and all instructions clonedClosure.setCFG(getCFG().cloneForCloningClosure(clonedClosure, ii)); return clonedClosure; }
@Override public Instr cloneForInlinedScope(InlinerInfo ii) { if (ii.getInlineHostScope() == scopeToReturnTo) { // If the break got inlined into the scope we had to break to, replace the break // with a COPY of the break-value into the call's result var. // Ex: v = foo { ..; break n; ..}. So, "break n" is replaced with "v = n" // The CFG for the closure will be such that after break, control goes to the // scope exit block. So, we know that after the copy, we'll continue with the // instruction after the call. Variable v = ii.getCallResultVariable(); return (v == null) ? null : new CopyInstr(v, returnValue.cloneForInlining(ii)); } else { return cloneForInlining(ii); } }
public InlinerInfo(CallBase call, CFG c) { this.varRenameMap = new HashMap<Variable, Variable>(); this.lblRenameMap = new HashMap<Label, Label>(); this.bbRenameMap = new HashMap<BasicBlock, BasicBlock>(); this.yieldSites = new ArrayList(); this.call = call; this.callArgs = call.getCallArgs(); this.callerCFG = c; this.callReceiver = call.getReceiver(); this.inClosureCloneMode = false; this.inClosureInlineMode = false; this.canMapArgsStatically = !containsSplat(callArgs); this.argsArray = this.canMapArgsStatically ? null : getInlineHostScope().getNewTemporaryVariable(); synchronized(globalInlineCount) { this.inlineVarPrefix = "%in" + globalInlineCount + "_"; globalInlineCount++; } }
@Override public Instr cloneForInlinedScope(InlinerInfo ii) { Variable v = ii.getCallResultVariable(); return v == null ? null : new CopyInstr(v, returnValue.cloneForInlining(ii)); }
public Operand getArg(int index) { int n = getArgsCount(); return index < n ? (inClosureInlineMode ? ((Array)yieldArg).get(index) : callArgs[index]) : null; }
public Operand getArg(int argIndex, boolean restOfArgArray) { if (restOfArgArray == false) { return getArg(argIndex); } else if (inClosureInlineMode) { throw new RuntimeException("Cannot get rest yield arg at inline time!"); } else { if(argIndex >= callArgs.length) { return new Array(); } else { Operand[] tmp = new Operand[callArgs.length - argIndex]; for (int j = argIndex; j < callArgs.length; j++) tmp[j-argIndex] = callArgs[j]; return new Array(tmp); } } }
InlinerInfo ii = new InlinerInfo(call, cfg); Label splitBBLabel = hostScope.getNewLabel(); BasicBlock splitBB; BasicBlock rx = ii.getRenamedBB(x); for (Edge<BasicBlock> e : methodCFG.getOutgoingEdges(x)) { BasicBlock b = e.getDestination().getData(); if (b != mExit) cfg.addEdge(rx, ii.getRenamedBB(b), e.getType()); BasicBlock destination = e.getDestination().getData(); if (destination != mExit) { BasicBlock dstBB = ii.getRenamedBB(destination); if (!ii.canMapArgsStatically()) { dstBB.addInstr(new ToAryInstr((Variable)ii.getArgs(), new Array(call.getCallArgs()), cfg.getScope().getManager().getTrue())); BasicBlock source = e.getSource().getData(); if (source != mEntry) { BasicBlock clonedSource = ii.getRenamedBB(source); if (e.getType() == EdgeType.EXCEPTION) { BasicBlock xRenamed = ii.getRenamedBB(x); BasicBlock xProtector = methodCFG.getRescuerBBFor(x); if (xProtector != null) { cfg.setRescuerBB(xRenamed, ii.getRenamedBB(xProtector)); } else if (callBBrescuer != null) { cfg.setRescuerBB(xRenamed, callBBrescuer); cfg.setEnsurerBB(xRenamed, ii.getRenamedBB(xEnsurer)); } else if (callBBensurer != null) {
ii = ii.cloneForInliningClosure(); ii.setupYieldArgsAndYieldResult(yield, yieldBB, cl.getBlockBody().arity()); BasicBlock bClone = ii.getRenamedBB(b); for (Edge<BasicBlock> e : closureCFG.getOutgoingEdges(b)) { BasicBlock edst = e.getDestination().getData(); if (edst != cExit) cfg.addEdge(bClone, ii.getRenamedBB(edst), e.getType()); BasicBlock destination = e.getDestination().getData(); if (destination != cExit) { cfg.addEdge(yieldBB, ii.getRenamedBB(destination), CFG.EdgeType.FALL_THROUGH); BasicBlock source = e.getSource().getData(); if (source != cEntry) { BasicBlock clonedSource = ii.getRenamedBB(source); if (e.getType() == EdgeType.EXCEPTION) { BasicBlock cbProtector = ii.getRenamedBB(closureCFG.getRescuerBBFor(cb)); if (cbProtector != null) { cfg.setRescuerBB(cb, cbProtector); BasicBlock cbEnsurer = ii.getRenamedBB(closureCFG.getEnsurerBBFor(cb)); if (cbEnsurer != null) { cfg.setEnsurerBB(cb, cbEnsurer);
@Override public Instr cloneForInlinedScope(InlinerInfo ii) { // SSS FIXME: This is not strictly correct -- we have to wrap the block into an // operand type that converts the static code block to a proc which is a closure. if (ii.getCallClosure() instanceof WrappedIRClosure) return NopInstr.NOP; else return new CopyInstr(ii.getRenamedVariable(result), ii.getCallClosure()); }
public IRClosure cloneForClonedInstr(InlinerInfo ii) { IRClosure clonedClosure = new IRClosure(this, ii.getNewLexicalParentForClosure()); clonedClosure.isForLoopBody = this.isForLoopBody; clonedClosure.nestingDepth = this.nestingDepth; clonedClosure.parameterList = this.parameterList; // Create a new inliner info object ii = ii.cloneForCloningClosure(clonedClosure); // clone the cfg, and all instructions clonedClosure.setCFG(getCFG().cloneForCloningClosure(clonedClosure, ii)); return clonedClosure; }
@Override public Instr cloneForInlinedScope(InlinerInfo ii) { if (ii.getInlineHostScope() == scopeToReturnTo) { // If the break got inlined into the scope we had to break to, replace the break // with a COPY of the break-value into the call's result var. // Ex: v = foo { ..; break n; ..}. So, "break n" is replaced with "v = n" // The CFG for the closure will be such that after break, control goes to the // scope exit block. So, we know that after the copy, we'll continue with the // instruction after the call. Variable v = ii.getCallResultVariable(); return (v == null) ? null : new CopyInstr(v, returnValue.cloneForInlining(ii)); } else { return cloneForInlining(ii); } }
public InlinerInfo(CallBase call, CFG c) { this.varRenameMap = new HashMap<Variable, Variable>(); this.lblRenameMap = new HashMap<Label, Label>(); this.bbRenameMap = new HashMap<BasicBlock, BasicBlock>(); this.yieldSites = new ArrayList(); this.call = call; this.callArgs = call.getCallArgs(); this.callerCFG = c; this.callReceiver = call.getReceiver(); this.inClosureCloneMode = false; this.inClosureInlineMode = false; this.canMapArgsStatically = !containsSplat(callArgs); this.argsArray = this.canMapArgsStatically ? null : getInlineHostScope().getNewTemporaryVariable(); synchronized(globalInlineCount) { this.inlineVarPrefix = "%in" + globalInlineCount + "_"; globalInlineCount++; } }
@Override public Instr cloneForInlinedScope(InlinerInfo ii) { Variable v = ii.getCallResultVariable(); return v == null ? null : new CopyInstr(v, returnValue.cloneForInlining(ii)); }
public Operand getArg(int index) { int n = getArgsCount(); return index < n ? (inClosureInlineMode ? ((Array)yieldArg).get(index) : callArgs[index]) : null; }