public void addInstr(Instr instr) { if (needsLineNumInfo) { needsLineNumInfo = false; addInstr(manager.newLineNumber(_lastProcessedLineNum)); if (RubyInstanceConfig.FULL_TRACE_ENABLED) { addInstr(new TraceInstr(RubyEvent.LINE, methodNameFor(), getFileName(), _lastProcessedLineNum)); if (needsCodeCoverage()) { addInstr(new TraceInstr(RubyEvent.COVERAGE, methodNameFor(), getFileName(), _lastProcessedLineNum)); } } } // If we are building an ensure body, stash the instruction // in the ensure body's list. If not, add it to the scope directly. if (ensureBodyBuildStack.empty()) { if (instr instanceof ThreadPollInstr) scope.threadPollInstrsCount++; instr.computeScopeFlags(scope); if (hasListener()) manager.getIRScopeListener().addedInstr(scope, instr, instructions.size()); instructions.add(instr); } else { ensureBodyBuildStack.peek().addInstr(instr); } }
public void addInstrAtBeginning(Instr instr) { // If we are building an ensure body, stash the instruction // in the ensure body's list. If not, add it to the scope directly. if (ensureBodyBuildStack.empty()) { instr.computeScopeFlags(scope); if (hasListener()) manager.getIRScopeListener().addedInstr(scope, instr, 0); instructions.add(0, instr); } else { ensureBodyBuildStack.peek().addInstrAtBeginning(instr); } }
private void emitEnsureBlocks(IRLoop loop) { int n = activeEnsureBlockStack.size(); EnsureBlockInfo[] ebArray = activeEnsureBlockStack.toArray(new EnsureBlockInfo[n]); for (int i = n-1; i >= 0; i--) { EnsureBlockInfo ebi = ebArray[i]; // For "break" and "next" instructions, we only want to run // ensure blocks from the loops they are present in. if (loop != null && ebi.innermostLoop != loop) break; // Clone into host scope ebi.cloneIntoHostScope(this); } }
ensure.cloneIntoHostScope(this); addInstr(new JumpInstr(rEndLabel));
EnsureBlockInfo ebi = new EnsureBlockInfo(scope, (ensureBodyNode instanceof RescueNode) ? (RescueNode)ensureBodyNode : null, getCurrentLoop(), ebi.cloneIntoHostScope(this); addInstr(new JumpInstr(ebi.end)); ebi.emitBody(this);
ensure.cloneIntoHostScope(this); addInstr(new JumpInstr(rEndLabel));
EnsureBlockInfo ebi = new EnsureBlockInfo(s, (bodyNode instanceof RescueNode) ? (RescueNode)bodyNode : null, getCurrentLoop()); _ensureBlockStack.push(ebi);
EnsureBlockInfo ebi = new EnsureBlockInfo(scope, (ensureBodyNode instanceof RescueNode) ? (RescueNode)ensureBodyNode : null, getCurrentLoop(), ebi.cloneIntoHostScope(this); addInstr(new JumpInstr(ebi.end)); ebi.emitBody(this);
EnsureBlockInfo ebi = new EnsureBlockInfo(s, (bodyNode instanceof RescueNode) ? (RescueNode)bodyNode : null, getCurrentLoop()); _ensureBlockStack.push(ebi);
activeEnsureBlockStack.peek().cloneIntoHostScope(this);
if (!_ensureBlockStack.empty()) EnsureBlockInfo.emitJumpChain(s, _ensureBlockStack, currLoop); else if (!_rescueBlockStack.empty()) _rescueBlockStack.peek().restoreException(s, currLoop);
public Operand buildReturn(ReturnNode returnNode, IRScope s) { Operand retVal = (returnNode.getValueNode() == null) ? manager.getNil() : build(returnNode.getValueNode(), s); // Before we return, // - have to go execute all the ensure blocks if there are any. // this code also takes care of resetting "$!" // - if we dont have any ensure blocks, we have to clear "$!" if (!_ensureBlockStack.empty()) EnsureBlockInfo.emitJumpChain(s, _ensureBlockStack, null); else if (!_rescueBlockStack.empty()) s.addInstr(new PutGlobalVarInstr("$!", manager.getNil())); if (s instanceof IRClosure) { // If 'm' is a block scope, a return returns from the closest enclosing method. // If this happens to be a module body, the runtime throws a local jump error if // the closure is a proc. If the closure is a lambda, then this is just a normal // return and the static methodToReturnFrom value is ignored s.addInstr(new NonlocalReturnInstr(retVal, s.getNearestMethod())); } else if (s.isModuleBody()) { IRMethod sm = s.getNearestMethod(); // Cannot return from top-level module bodies! if (sm == null) s.addInstr(new ThrowExceptionInstr(IRException.RETURN_LocalJumpError)); else s.addInstr(new NonlocalReturnInstr(retVal, sm)); } else { s.addInstr(new ReturnInstr(retVal)); } // The value of the return itself in the containing expression can never be used because of control-flow reasons. // The expression that uses this result can never be executed beyond the return and hence the value itself is just // a placeholder operand. return UnexecutableNil.U_NIL; }
activeEnsureBlockStack.peek().cloneIntoHostScope(this);
if (!_ensureBlockStack.empty()) EnsureBlockInfo.emitJumpChain(s, _ensureBlockStack, currLoop); else if (!_rescueBlockStack.empty()) _rescueBlockStack.peek().restoreException(s, currLoop);
public Operand buildReturn(ReturnNode returnNode, IRScope s) { Operand retVal = (returnNode.getValueNode() == null) ? manager.getNil() : build(returnNode.getValueNode(), s); // Before we return, // - have to go execute all the ensure blocks if there are any. // this code also takes care of resetting "$!" // - if we dont have any ensure blocks, we have to clear "$!" if (!_ensureBlockStack.empty()) EnsureBlockInfo.emitJumpChain(s, _ensureBlockStack, null); else if (!_rescueBlockStack.empty()) s.addInstr(new PutGlobalVarInstr("$!", manager.getNil())); if (s instanceof IRClosure) { // If 'm' is a block scope, a return returns from the closest enclosing method. // If this happens to be a module body, the runtime throws a local jump error if // the closure is a proc. If the closure is a lambda, then this is just a normal // return and the static methodToReturnFrom value is ignored s.addInstr(new NonlocalReturnInstr(retVal, s.getNearestMethod())); } else if (s.isModuleBody()) { IRMethod sm = s.getNearestMethod(); // Cannot return from top-level module bodies! if (sm == null) s.addInstr(new ThrowExceptionInstr(IRException.RETURN_LocalJumpError)); else s.addInstr(new NonlocalReturnInstr(retVal, sm)); } else { s.addInstr(new ReturnInstr(retVal)); } // The value of the return itself in the containing expression can never be used because of control-flow reasons. // The expression that uses this result can never be executed beyond the return and hence the value itself is just // a placeholder operand. return UnexecutableNil.U_NIL; }
public void addInstr(Instr instr) { if (needsLineNumInfo) { needsLineNumInfo = false; addInstr(manager.newLineNumber(_lastProcessedLineNum)); if (RubyInstanceConfig.FULL_TRACE_ENABLED) { addInstr(new TraceInstr(RubyEvent.LINE, methodNameFor(), getFileName(), _lastProcessedLineNum)); if (needsCodeCoverage()) { addInstr(new TraceInstr(RubyEvent.COVERAGE, methodNameFor(), getFileName(), _lastProcessedLineNum)); } } } // If we are building an ensure body, stash the instruction // in the ensure body's list. If not, add it to the scope directly. if (ensureBodyBuildStack.empty()) { if (instr instanceof ThreadPollInstr) scope.threadPollInstrsCount++; instr.computeScopeFlags(scope); if (hasListener()) manager.getIRScopeListener().addedInstr(scope, instr, instructions.size()); instructions.add(instr); } else { ensureBodyBuildStack.peek().addInstr(instr); } }
public Operand buildNext(final NextNode nextNode, IRScope s) { IRLoop currLoop = getCurrentLoop(); Operand rv = (nextNode.getValueNode() == null) ? manager.getNil() : build(nextNode.getValueNode(), s); // If we have ensure blocks, have to run those first! if (!_ensureBlockStack.empty()) EnsureBlockInfo.emitJumpChain(s, _ensureBlockStack, currLoop); else if (!_rescueBlockStack.empty()) _rescueBlockStack.peek().restoreException(s, currLoop); if (currLoop != null) { // If a regular loop, the next is simply a jump to the end of the iteration s.addInstr(new JumpInstr(currLoop.iterEndLabel)); } else { s.addInstr(new ThreadPollInstr(true)); // If a closure, the next is simply a return from the closure! if (s instanceof IRClosure) s.addInstr(new ReturnInstr(rv)); else s.addInstr(new ThrowExceptionInstr(IRException.NEXT_LocalJumpError)); } // Once the "next instruction" (closure-return) executes, control exits this scope return UnexecutableNil.U_NIL; }
public Operand buildNext(final NextNode nextNode, IRScope s) { IRLoop currLoop = getCurrentLoop(); Operand rv = (nextNode.getValueNode() == null) ? manager.getNil() : build(nextNode.getValueNode(), s); // If we have ensure blocks, have to run those first! if (!_ensureBlockStack.empty()) EnsureBlockInfo.emitJumpChain(s, _ensureBlockStack, currLoop); else if (!_rescueBlockStack.empty()) _rescueBlockStack.peek().restoreException(s, currLoop); if (currLoop != null) { // If a regular loop, the next is simply a jump to the end of the iteration s.addInstr(new JumpInstr(currLoop.iterEndLabel)); } else { s.addInstr(new ThreadPollInstr(true)); // If a closure, the next is simply a return from the closure! if (s instanceof IRClosure) s.addInstr(new ReturnInstr(rv)); else s.addInstr(new ThrowExceptionInstr(IRException.NEXT_LocalJumpError)); } // Once the "next instruction" (closure-return) executes, control exits this scope return UnexecutableNil.U_NIL; }
private void emitEnsureBlocks(IRLoop loop) { int n = activeEnsureBlockStack.size(); EnsureBlockInfo[] ebArray = activeEnsureBlockStack.toArray(new EnsureBlockInfo[n]); for (int i = n-1; i >= 0; i--) { EnsureBlockInfo ebi = ebArray[i]; // For "break" and "next" instructions, we only want to run // ensure blocks from the loops they are present in. if (loop != null && ebi.innermostLoop != loop) break; // Clone into host scope ebi.cloneIntoHostScope(this); } }
public void addInstrAtBeginning(Instr instr) { // If we are building an ensure body, stash the instruction // in the ensure body's list. If not, add it to the scope directly. if (ensureBodyBuildStack.empty()) { instr.computeScopeFlags(scope); if (hasListener()) manager.getIRScopeListener().addedInstr(scope, instr, 0); instructions.add(0, instr); } else { ensureBodyBuildStack.peek().addInstrAtBeginning(instr); } }