public Label getRenamedLabel(Label l) { Label newLbl = this.lblRenameMap.get(l); if (newLbl == null) { newLbl = inClosureCloneMode ? l.clone() : getInlineHostScope().getNewLabel(); this.lblRenameMap.put(l, newLbl); } return newLbl; }
public static IRubyObject interpret(ThreadContext context, CFG cfg, InterpreterContext interp) { Ruby runtime = context.getRuntime(); boolean inClosure = (cfg.getScope() instanceof IRClosure); boolean passThroughBreak = false; try { interp.setMethodExitLabel( cfg.getExitBB().getLabel()); // used by return and break instructions! Instr[] instrs = cfg.prepareForInterpretation(); int n = instrs.length; int ipc = 0; Instr lastInstr = null; while (ipc < n) { interpInstrsCount++; lastInstr = instrs[ipc]; if (isDebug()) LOG.debug("I: {}", lastInstr); try { Label jumpTarget = lastInstr.interpret(interp); ipc = (jumpTarget == null) ? ipc + 1 : jumpTarget.getTargetPC(); } // SSS FIXME: This only catches Ruby exceptions // What about Java exceptions? catch (org.jruby.exceptions.RaiseException re) { ipc = cfg.getRescuerPC(lastInstr); if (ipc == -1) throw re; // No one rescued exception, pass it on! interp.setException(re.getException()); } } // If a closure, and lastInstr was a return, have to return from the nearest method! IRubyObject rv = (IRubyObject) interp.getReturnValue(); if (lastInstr instanceof ReturnInstr && inClosure && !interp.inLambda()) { throw new IRReturnJump(((ReturnInstr) lastInstr).methodToReturnFrom, rv); } // If a closure, and lastInstr was a break, have to return from the nearest closure! else if (lastInstr instanceof BREAK_Instr) { if (!inClosure) throw runtime.newLocalJumpError(Reason.BREAK, rv, "unexpected break"); passThroughBreak = true; RuntimeHelpers.breakJump(context, rv); } return rv; } catch (JumpException.BreakJump bj) { if (passThroughBreak) throw bj; return (IRubyObject) bj.getValue(); } catch (IRReturnJump rj) { // - If we are in a lambda, stop propagating // - If not in a lambda // - if in a closure, pass it along // - if not in a closure, we got this return jump from a closure further up the call stack. // So, continue popping the call stack till we get to the right method if (!interp.inLambda() && (inClosure || (rj.methodToReturnFrom != cfg.getScope()))) throw rj; // pass it along return (IRubyObject) rj.returnValue; } finally { if (interp.getFrame() != null) { context.popFrame(); interp.setFrame(null); } if (interp.hasAllocatedDynamicScope()) context.postMethodScopeOnly(); } }