示例#1
0
 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;
 }
示例#2
0
  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();
    }
  }