public BasicBlock splitAtInstruction(Instr splitPoint, Label newLabel, boolean includeSplitPointInstr) { BasicBlock newBB = new BasicBlock(cfg, newLabel); int idx = 0; int numInstrs = instrs.size(); boolean found = false; for (Instr i: instrs) { if (i == splitPoint) found = true; // Move instructions from split point into the new bb if (found) { if (includeSplitPointInstr || i != splitPoint) newBB.addInstr(i); } else { idx++; } } // Remove all instructions from current bb that were moved over. for (int j = 0; j < numInstrs-idx; j++) { instrs.remove(idx); } return newBB; }
public BasicBlock splitAtInstruction(Instr splitPoint, Label newLabel, boolean includeSplitPointInstr) { BasicBlock newBB = new BasicBlock(cfg, newLabel); int idx = 0; int numInstrs = instrs.size(); boolean found = false; for (Instr i: instrs) { if (i == splitPoint) found = true; // Move instructions from split point into the new bb if (found) { if (includeSplitPointInstr || i != splitPoint) newBB.addInstr(i); } else { idx++; } } // Remove all instructions from current bb that were moved over. for (int j = 0; j < numInstrs-idx; j++) { instrs.remove(idx); } return newBB; }
private static void addJumpIfNextNotDestination(CFG cfg, BasicBlock next, Instr lastInstr, BasicBlock current) { Iterator<BasicBlock> outs = cfg.getOutgoingDestinations(current).iterator(); BasicBlock target = outs.hasNext() ? outs.next() : null; if (target != null && !outs.hasNext()) { if ((target != next) && ((lastInstr == null) || !lastInstr.getOperation().transfersControl())) { current.addInstr(new JumpInstr(target.getLabel())); } } }
private static void addJumpIfNextNotDestination(CFG cfg, BasicBlock next, Instr lastInstr, BasicBlock current) { Iterator<BasicBlock> outs = cfg.getOutgoingDestinations(current).iterator(); BasicBlock target = outs.hasNext() ? outs.next() : null; if (target != null && !outs.hasNext()) { if ((target != next) && ((lastInstr == null) || !lastInstr.getOperation().transfersControl())) { current.addInstr(new JumpInstr(target.getLabel())); } } }
private static void addJumpIfNextNotDestination(CFG cfg, BasicBlock next, Instr lastInstr, BasicBlock current) { Iterator<BasicBlock> outs = cfg.getOutgoingDestinations(current).iterator(); BasicBlock target = outs.hasNext() ? outs.next() : null; if (target != null && !outs.hasNext()) { if ((target != next) && ((lastInstr == null) || !lastInstr.getOperation().transfersControl())) { current.addInstr(new JumpInstr(target.getLabel())); } } }
private static void addJumpIfNextNotDestination(CFG cfg, BasicBlock next, Instr lastInstr, BasicBlock current) { Iterator<BasicBlock> outs = cfg.getOutgoingDestinations(current).iterator(); BasicBlock target = outs.hasNext() ? outs.next() : null; if (target != null && !outs.hasNext()) { if ((target != next) && ((lastInstr == null) || !lastInstr.getOperation().transfersControl())) { current.addInstr(new JumpInstr(target.getLabel())); } } }
public BasicBlock splitAtInstruction(Site splitPoint, Label newLabel, boolean includeSplitPointInstr) { BasicBlock newBB = new BasicBlock(cfg, newLabel); int idx = 0; int numInstrs = instrs.size(); boolean found = false; for (Instr i: instrs) { // FIXME: once found we should not be continually checking for more should be in !found if (i instanceof Site && ((Site) i).getCallSiteId() == splitPoint.getCallSiteId()) found = true; // Move instructions from split point into the new bb if (found) { // FIXME: move includeSplit when found so we can remove consuing site id logic from here... if (includeSplitPointInstr || !(i instanceof Site) || ((Site) i).getCallSiteId() != splitPoint.getCallSiteId()) newBB.addInstr(i); } else { idx++; } } if (!found) throw new RuntimeException("Cound not find split point: " + splitPoint); // Remove all instructions from current bb that were moved over. for (int j = 0; j < numInstrs-idx; j++) { instrs.remove(idx); } return newBB; }
public BasicBlock cloneForInlining(InlineCloneInfo ii) { BasicBlock clonedBB = ii.getOrCreateRenamedBB(this); for (Instr i: getInstrs()) { Instr clonedInstr = i.clone(ii); if (clonedInstr != null) { clonedBB.addInstr(clonedInstr); if (clonedInstr instanceof YieldInstr) { ii.recordYieldSite(clonedBB, (YieldInstr)clonedInstr); } else if (i instanceof NonlocalReturnInstr && clonedInstr instanceof CopyInstr) { // non-local returns assign to method return variable but must jump to proper exit point clonedBB.addInstr(new JumpInstr(ii.getHostScope().getCFG().getExitBB().getLabel())); // FIXME: enebo...I see no guarantee that this copy will be part of a return? This behavior is // masked in any case I can see with optimization to not use a copy but convert non-local to local return. } } } return clonedBB; }
public BasicBlock cloneForInlining(InlineCloneInfo ii) { BasicBlock clonedBB = ii.getOrCreateRenamedBB(this); for (Instr i: getInstrs()) { Instr clonedInstr = i.clone(ii); if (clonedInstr != null) { clonedBB.addInstr(clonedInstr); if (clonedInstr instanceof YieldInstr) { ii.recordYieldSite(clonedBB, (YieldInstr)clonedInstr); } else if (i instanceof NonlocalReturnInstr && clonedInstr instanceof CopyInstr) { // non-local returns assign to method return variable but must jump to proper exit point clonedBB.addInstr(new JumpInstr(ii.getHostScope().getCFG().getExitBB().getLabel())); // FIXME: enebo...I see no guarantee that this copy will be part of a return? This behavior is // masked in any case I can see with optimization to not use a copy but convert non-local to local return. } } } return clonedBB; }
public BasicBlock cloneForInlinedClosure(InlinerInfo ii) { // Update cfg for this bb IRScope hostScope = ii.getInlineHostScope(); BasicBlock clonedBB = ii.getOrCreateRenamedBB(this); // Process instructions for (Instr i: getInstrs()) { Instr clonedInstr = i.cloneForInlinedClosure(ii); if (clonedInstr != null) { clonedBB.addInstr(clonedInstr); if (clonedInstr instanceof CallBase) { CallBase call = (CallBase)clonedInstr; Operand block = call.getClosureArg(null); if (block instanceof WrappedIRClosure) hostScope.addClosure(((WrappedIRClosure)block).getClosure()); } } } return clonedBB; }
public BasicBlock cloneForInlinedClosure(InlinerInfo ii) { // Update cfg for this bb IRScope hostScope = ii.getInlineHostScope(); BasicBlock clonedBB = ii.getOrCreateRenamedBB(this); // Process instructions for (Instr i: getInstrs()) { Instr clonedInstr = i.cloneForInlinedClosure(ii); if (clonedInstr != null) { clonedBB.addInstr(clonedInstr); if (clonedInstr instanceof CallBase) { CallBase call = (CallBase)clonedInstr; Operand block = call.getClosureArg(null); if (block instanceof WrappedIRClosure) hostScope.addClosure(((WrappedIRClosure)block).getClosure()); } } } return clonedBB; }
public void setupYieldArgsAndYieldResult(YieldInstr yi, BasicBlock yieldBB, int blockArityValue) { Operand yieldInstrArg = yi.getYieldArg(); if ((yieldInstrArg == UndefinedValue.UNDEFINED) || blockArityValue == 0) { yieldArg = new Array(); // Zero-elt array } else if (yieldInstrArg instanceof Array) { yieldArg = yieldInstrArg; // 1:1 arg match if (((Array) yieldInstrArg).size() == blockArityValue) canMapArgsStatically = true; } else if (blockArityValue == 1 && yi.unwrapArray == false) { yieldArg = yieldInstrArg; canMapArgsStatically = true; } else { // SSS FIXME: The code below is not entirely correct. We have to process 'yi.getYieldArg()' similar // to how InterpretedIRBlockBody (1.8 and 1.9 modes) processes it. We may need a special instruction // that takes care of aligning the stars and bringing good fortune to arg yielder and arg receiver. IRScope callerScope = getHostScope(); Variable yieldArgArray = callerScope.createTemporaryVariable(); yieldBB.addInstr(new ToAryInstr(yieldArgArray, yieldInstrArg)); yieldArg = yieldArgArray; } yieldResult = yi.getResult(); }
public BasicBlock cloneForInlinedMethod(InlinerInfo ii) { IRScope hostScope = ii.getInlineHostScope(); BasicBlock clonedBB = ii.getOrCreateRenamedBB(this); for (Instr i: getInstrs()) { Instr clonedInstr = i.cloneForInlinedScope(ii); if (clonedInstr != null) { clonedBB.addInstr(clonedInstr); if (clonedInstr instanceof YieldInstr) ii.recordYieldSite(clonedBB, (YieldInstr)clonedInstr); if (clonedInstr instanceof CallBase) { CallBase call = (CallBase)clonedInstr; Operand block = call.getClosureArg(null); if (block instanceof WrappedIRClosure) hostScope.addClosure(((WrappedIRClosure)block).getClosure()); } } } return clonedBB; }
public void setupYieldArgsAndYieldResult(YieldInstr yi, BasicBlock yieldBB, int blockArityValue) { Operand yieldInstrArg = yi.getYieldArg(); if ((yieldInstrArg == UndefinedValue.UNDEFINED) || blockArityValue == 0) { yieldArg = new Array(); // Zero-elt array } else if (yieldInstrArg instanceof Array) { yieldArg = yieldInstrArg; // 1:1 arg match if (((Array) yieldInstrArg).size() == blockArityValue) canMapArgsStatically = true; } else if (blockArityValue == 1 && yi.unwrapArray == false) { yieldArg = yieldInstrArg; canMapArgsStatically = true; } else { // SSS FIXME: The code below is not entirely correct. We have to process 'yi.getYieldArg()' similar // to how InterpretedIRBlockBody (1.8 and 1.9 modes) processes it. We may need a special instruction // that takes care of aligning the stars and bringing good fortune to arg yielder and arg receiver. IRScope callerScope = getHostScope(); Variable yieldArgArray = callerScope.createTemporaryVariable(); yieldBB.addInstr(new ToAryInstr(yieldArgArray, yieldInstrArg)); yieldArg = yieldArgArray; } yieldResult = yi.getResult(); }
public BasicBlock cloneForInlinedMethod(InlinerInfo ii) { IRScope hostScope = ii.getInlineHostScope(); BasicBlock clonedBB = ii.getOrCreateRenamedBB(this); for (Instr i: getInstrs()) { Instr clonedInstr = i.cloneForInlinedScope(ii); if (clonedInstr != null) { clonedBB.addInstr(clonedInstr); if (clonedInstr instanceof YieldInstr) ii.recordYieldSite(clonedBB, (YieldInstr)clonedInstr); if (clonedInstr instanceof CallBase) { CallBase call = (CallBase)clonedInstr; Operand block = call.getClosureArg(null); if (block instanceof WrappedIRClosure) hostScope.addClosure(((WrappedIRClosure)block).getClosure()); } } } return clonedBB; }
public BasicBlock clone(CloneInfo info, CFG newCFG) { BasicBlock newBB = new BasicBlock(newCFG, info.getRenamedLabel(label)); boolean isClosureClone = info instanceof InlineCloneInfo && ((InlineCloneInfo) info).isClosure(); for (Instr instr: instrs) { Instr newInstr = instr.clone(info); // Inlining clones the original CFG/BBs and we want to maintain ipc since it is how // we find which instr we want (we clone original instr and ipc is our identity). //if (info instanceof SimpleCloneInfo && ((SimpleCloneInfo) info).shouldCloneIPC()) { // newInstr.setIPC(instr.getIPC()); // newInstr.setRPC(instr.getRPC()); //} // All call-derived types do not clone this field. Inliner clones original instrs // and we need this preserved to make sure we do not endless inline the same call. if (instr instanceof CallBase && ((CallBase) instr).inliningBlocked()) { ((CallBase) newInstr).blockInlining(); } if (newInstr != null) { // inliner may kill off unneeded instr newBB.addInstr(newInstr); if (isClosureClone && newInstr instanceof YieldInstr) { ((InlineCloneInfo) info).recordYieldSite(newBB, (YieldInstr) newInstr); } } } return newBB; }
public void setupYieldArgsAndYieldResult(YieldInstr yi, BasicBlock yieldBB, Arity blockArity) { int blockArityValue = blockArity.getValue(); Operand yieldInstrArg = yi.getYieldArg(); if ((yieldInstrArg == UndefinedValue.UNDEFINED) || (blockArityValue == 0)) { this.yieldArg = new Array(); // Zero-elt array } else if (yieldInstrArg instanceof Array) { this.yieldArg = yieldInstrArg; // 1:1 arg match if (((Array)yieldInstrArg).size() == blockArityValue) canMapArgsStatically = true; } else { // SSS FIXME: The code below is not entirely correct. We have to process 'yi.getYieldArg()' similar // to how InterpretedIRBlockBody (1.8 and 1.9 modes) processes it. We may need a special instruction // that takes care of aligning the stars and bringing good fortune to arg yielder and arg receiver. IRScope callerScope = getInlineHostScope(); boolean needSpecialProcessing = (blockArityValue != -1) && (blockArityValue != 1); Variable yieldArgArray = callerScope.getNewTemporaryVariable(); yieldBB.addInstr(new ToAryInstr(yieldArgArray, yieldInstrArg, callerScope.getManager().getTrue())); this.yieldArg = yieldArgArray; } this.yieldResult = yi.getResult(); }
public void setupYieldArgsAndYieldResult(YieldInstr yi, BasicBlock yieldBB, Arity blockArity) { int blockArityValue = blockArity.getValue(); Operand yieldInstrArg = yi.getYieldArg(); if ((yieldInstrArg == UndefinedValue.UNDEFINED) || (blockArityValue == 0)) { this.yieldArg = new Array(); // Zero-elt array } else if (yieldInstrArg instanceof Array) { this.yieldArg = yieldInstrArg; // 1:1 arg match if (((Array)yieldInstrArg).size() == blockArityValue) canMapArgsStatically = true; } else { // SSS FIXME: The code below is not entirely correct. We have to process 'yi.getYieldArg()' similar // to how InterpretedIRBlockBody (1.8 and 1.9 modes) processes it. We may need a special instruction // that takes care of aligning the stars and bringing good fortune to arg yielder and arg receiver. IRScope callerScope = getInlineHostScope(); boolean needSpecialProcessing = (blockArityValue != -1) && (blockArityValue != 1); Variable yieldArgArray = callerScope.getNewTemporaryVariable(); yieldBB.addInstr(new ToAryInstr(yieldArgArray, yieldInstrArg, callerScope.getManager().getTrue())); this.yieldArg = yieldArgArray; } this.yieldResult = yi.getResult(); }
private void addMissingJumps() { for (BasicBlock bb: cfg.getBasicBlocks()) { boolean fallThrough = false; Label jumpLabel = null; for (Edge<BasicBlock> edge : cfg.getOutgoingEdges(bb)) { if (edge.getType() == EdgeType.FALL_THROUGH) { // Assume next BB will be correct fallThrough = true; } else if (edge.getType() == EdgeType.REGULAR || edge.getType() == EdgeType.EXIT) { // Not sure if we can have regular and fallthrough but only add regular if no fallthrough if (fallThrough) continue; jumpLabel = edge.getDestination().getData().getLabel(); } } if (fallThrough) continue; // we know this will just go to next BB already so no missing jump. if (jumpLabel == null) continue; // last instr does not transfer control so nothing to add. Instr lastInstr = bb.getLastInstr(); if (lastInstr != null && !lastInstr.transfersControl()) { bb.addInstr(new JumpInstr(jumpLabel)); } } }
private void addMissingJumps() { for (BasicBlock bb: cfg.getBasicBlocks()) { boolean fallThrough = false; Label jumpLabel = null; for (Edge<BasicBlock> edge : cfg.getOutgoingEdges(bb)) { if (edge.getType() == EdgeType.FALL_THROUGH) { // Assume next BB will be correct fallThrough = true; } else if (edge.getType() == EdgeType.REGULAR || edge.getType() == EdgeType.EXIT) { // Not sure if we can have regular and fallthrough but only add regular if no fallthrough if (fallThrough) continue; jumpLabel = edge.getDestination().getData().getLabel(); } } if (fallThrough) continue; // we know this will just go to next BB already so no missing jump. if (jumpLabel == null) continue; // last instr does not transfer control so nothing to add. Instr lastInstr = bb.getLastInstr(); if (lastInstr != null && !lastInstr.transfersControl()) { bb.addInstr(new JumpInstr(jumpLabel)); } } }