public IRClosure cloneForInlining(CloneInfo ii) { IRClosure clonedClosure; IRScope lexicalParent = ii.getScope(); if (ii instanceof SimpleCloneInfo && !((SimpleCloneInfo)ii).isEnsureBlockCloneMode()) { clonedClosure = new IRClosure(this, lexicalParent, closureId, getName()); } else { int id = lexicalParent.getNextClosureId(); ByteList fullName = lexicalParent.getName().getBytes().dup(); fullName.append(CLOSURE_CLONE); fullName.append(new Integer(id).toString().getBytes()); clonedClosure = new IRClosure(this, lexicalParent, id, getManager().runtime.newSymbol(fullName)); } // WrappedIRClosure should always have a single unique IRClosure in them so we should // not end up adding n copies of the same closure as distinct clones... lexicalParent.addClosure(clonedClosure); return cloneForInlining(ii, clonedClosure); }
private void calculateClosureScopeFlags() { // Compute flags for nested closures (recursively) and set derived flags. for (IRClosure cl: getClosures()) { cl.computeScopeFlags(); if (cl.usesEval()) { flags.add(CAN_RECEIVE_BREAKS); flags.add(CAN_RECEIVE_NONLOCAL_RETURNS); flags.add(USES_ZSUPER); } else { if (cl.flags.contains(HAS_BREAK_INSTRS) || cl.flags.contains(CAN_RECEIVE_BREAKS)) { flags.add(CAN_RECEIVE_BREAKS); } if (cl.flags.contains(HAS_NONLOCAL_RETURNS) || cl.flags.contains(CAN_RECEIVE_NONLOCAL_RETURNS)) { flags.add(CAN_RECEIVE_NONLOCAL_RETURNS); } if (cl.usesZSuper()) { flags.add(USES_ZSUPER); } } } }
public boolean definesLocalVariable(Variable v) { if (definedLocalVars == null) setUpUseDefLocalVarMaps(); if (definedLocalVars.contains(v)) return true; for (IRClosure cl : getClosures()) { if (cl.definesLocalVariable(v)) return true; } return false; }
public IRMethod convertToMethod(RubySymbol name) { // We want variable scoping to be the same as a method and not see outside itself. if (source == null || getFlags().contains(IRFlags.ACCESS_PARENTS_LOCAL_VARIABLES) || // Built methods cannot search down past method scope getFlags().contains(IRFlags.RECEIVES_CLOSURE_ARG) || // we pass in captured block at define_method as block so explicits ones not supported !isNestedClosuresSafeForMethodConversion()) { source = null; return null; } DefNode def = source; source = null; // FIXME: This should be bytelist from param vs being made (see above). return new IRMethod(getManager(), getLexicalParent(), def, name, true, getLine(), getStaticScope(), getFlags().contains(IRFlags.CODE_COVERAGE)); }
@Override protected LocalVariable findExistingLocalVariable(RubySymbol name, int scopeDepth) { LocalVariable lvar = lookupExistingLVar(name); if (lvar != null) return lvar; int newDepth = scopeDepth - 1; if (newDepth >= 0) { lvar = getLexicalParent().findExistingLocalVariable(name, newDepth); if (lvar != null) flags.add(IRFlags.ACCESS_PARENTS_LOCAL_VARIABLES); } return lvar; }
public String toStringBody() { StringBuilder buf = new StringBuilder(); buf.append(getName()).append(" = { \n"); CFG c = getCFG(); if (c != null) { buf.append("\nCFG:\n").append(c.toStringGraph()).append("\nInstructions:\n").append(c.toStringInstrs()); } else { buf.append(toStringInstrs()); } buf.append("\n}\n\n"); return buf.toString(); }
public Operand buildPostExe(PostExeNode postExeNode, IRScope s) { IRClosure endClosure = new IRClosure(manager, s, false, postExeNode.getPosition().getStartLine(), postExeNode.getScope(), Arity.procArityOf(postExeNode.getVarNode()), postExeNode.getArgumentType(), !is1_9() && !is2_0()); // Set up %current_scope and %current_module endClosure.addInstr(new CopyInstr(endClosure.getCurrentScopeVariable(), new CurrentScope(endClosure))); endClosure.addInstr(new CopyInstr(endClosure.getCurrentModuleVariable(), new ScopeModule(endClosure))); build(postExeNode.getBodyNode(), endClosure); // Add an instruction to record the end block at runtime s.addInstr(new RecordEndBlockInstr(s, endClosure)); return manager.getNil(); }
if (spillAllVars || cl.usesLocalVariable(v) || cl.definesLocalVariable(v)) { newDirtyVars.remove(v);
/** Used by cloning code */ private IRClosure(IRClosure c, IRScope lexicalParent) { super(c, lexicalParent); this.closureId = lexicalParent.getNextClosureId(); setName("_CLOSURE_CLONE_" + closureId); this.startLabel = getNewLabel(getName() + "_START"); this.endLabel = getNewLabel(getName() + "_END"); this.body = (c.body instanceof InterpretedIRBlockBody19) ? new InterpretedIRBlockBody19(this, c.body.arity(), c.body.getArgumentType()) : new InterpretedIRBlockBody(this, c.body.arity(), c.body.getArgumentType()); this.addedGEBForUncaughtBreaks = false; }
/** Used by cloning code */ /* Inlining generates a new name and id and basic cloning will reuse the originals name */ protected IRClosure(IRClosure c, IRScope lexicalParent, int closureId, RubySymbol fullName) { super(c, lexicalParent); this.closureId = closureId; super.setName(fullName); this.startLabel = getNewLabel(getId() + "_START"); this.endLabel = getNewLabel(getId() + "_END"); if (getManager().isDryRun()) { this.body = null; } else { boolean shouldJit = getManager().getInstanceConfig().getCompileMode().shouldJIT(); this.body = shouldJit ? new MixedModeIRBlockBody(c, c.getSignature()) : new InterpretedIRBlockBody(c, c.getSignature()); } this.signature = c.signature; }
protected IRClosure(IRManager manager, IRScope lexicalParent, String fileName, int lineNumber, StaticScope staticScope, String prefix) { super(manager, lexicalParent, null, fileName, lineNumber, staticScope); this.isForLoopBody = false; this.startLabel = getNewLabel(prefix + "START"); this.endLabel = getNewLabel(prefix + "END"); this.closureId = lexicalParent.getNextClosureId(); setName(prefix + closureId); this.body = null; this.parameterList = new String[] {}; // set nesting depth int n = 0; IRScope s = this; while (s instanceof IRClosure) { if (!s.isForLoopBody()) n++; s = s.getLexicalParent(); } this.nestingDepth = n; }
@Override public Object retrieve(ThreadContext context, IRubyObject self, DynamicScope currDynScope, Object[] temp) { BlockBody body = closure.getBlockBody(); closure.getStaticScope().determineModule(); Binding binding = context.currentBinding(self, currDynScope); return new Block(body, binding); }
ii.setupYieldArgsAndYieldResult(yield, yieldBB, cl.getBlockBody().arity()); CFG closureCFG = cl.getCFG(); BasicBlock cEntry = closureCFG.getEntryBB(); BasicBlock cExit = closureCFG.getExitBB();
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 LocalVariable getLocalVariable(String name, int scopeDepth) { if (isForLoopBody) return getLexicalParent().getLocalVariable(name, scopeDepth); LocalVariable lvar = findExistingLocalVariable(name, scopeDepth); if (lvar == null) lvar = getNewLocalVariable(name, scopeDepth); // Create a copy of the variable usable at the right depth if (lvar.getScopeDepth() != scopeDepth) lvar = lvar.cloneForDepth(scopeDepth); return lvar; }
@Override public int getNextClosureId() { return getLexicalParent().getNextClosureId(); }
@Override public void setName(RubySymbol name) { ByteList newName = getLexicalParent().getName().getBytes().dup(); newName.append(name.getBytes()); super.setName(getManager().getRuntime().newSymbol(newName)); }
public IRClosure(IRManager manager, IRScope lexicalParent, int lineNumber, StaticScope staticScope, Signature signature, ByteList prefix, boolean isBeginEndBlock, boolean needsCoverage) { this(manager, lexicalParent, lineNumber, staticScope, prefix); this.signature = signature; lexicalParent.addClosure(this); if (getManager().isDryRun()) { this.body = null; } else { boolean shouldJit = manager.getInstanceConfig().getCompileMode().shouldJIT(); this.body = shouldJit ? new MixedModeIRBlockBody(this, signature) : new InterpretedIRBlockBody(this, signature); if (staticScope != null && !isBeginEndBlock) { staticScope.setIRScope(this); staticScope.setScopeType(this.getScopeType()); } } if (needsCoverage) getFlags().add(IRFlags.CODE_COVERAGE); }
cl.computeScopeFlags(); if (cl.hasBreakInstrs || cl.canReceiveBreaks) { canReceiveBreaks = true; canReceiveNonlocalReturns = true; if (cl.usesZSuper()) { usesZSuper = true;
public InterpretedIRBlockBody(IRClosure closure, Signature signature) { super(closure, signature); this.pushScope = true; this.reuseParentScope = false; // JIT currently JITs blocks along with their method and no on-demand by themselves. We only // promote to full build here if we are -X-C. if (closure.getManager().getInstanceConfig().getCompileMode().shouldJIT() || Options.JIT_THRESHOLD.load() == -1) { callCount = -1; } }