示例#1
0
 protected void post(InterpreterContext ic, ThreadContext context) {
   // update call stacks (pop: ..)
   context.popFrame();
   if (ic.popDynScope()) {
     context.popScope();
   }
 }
示例#2
0
 public void postTrace() {
   popFrame();
   setWithinTrace(false);
 }
示例#3
0
 public void postExecuteUnder() {
   popFrame();
   popScope();
   popRubyClass();
 }
示例#4
0
 public void postMproc() {
   popFrame();
 }
示例#5
0
 public void postMethodBacktraceDummyScope() {
   popFrame();
   popRubyClass();
   popScope();
 }
示例#6
0
 public void postNodeEval() {
   popFrame();
   popRubyClass();
 }
示例#7
0
 public void postMethodBacktraceAndScope() {
   postMethodScopeOnly();
   popFrame();
 }
示例#8
0
 public void postMethodBacktraceOnly() {
   popFrame();
 }
示例#9
0
 public void postMethodFrameAndScope() {
   popRubyClass();
   popScope();
   popFrame();
 }
示例#10
0
 public void postMethodFrameOnly() {
   popFrame();
   popRubyClass();
 }
示例#11
0
 public void postBsfApply() {
   popFrame();
 }
示例#12
0
 public void postClassEval() {
   popScope();
   popRubyClass();
   popFrame();
 }
示例#13
0
 public void postCompiledClass() {
   popScope();
   popRubyClass();
   popFrame();
 }
示例#14
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();
    }
  }
示例#15
0
  private static IRubyObject interpret(
      ThreadContext context,
      IRubyObject self,
      IRScope scope,
      Visibility visibility,
      RubyModule implClass,
      IRubyObject[] args,
      Block block,
      Block.Type blockType) {
    Instr[] instrs = scope.getInstrsForInterpretation();

    // The base IR may not have been processed yet
    if (instrs == null) instrs = scope.prepareForInterpretation(blockType == Block.Type.LAMBDA);

    int numTempVars = scope.getTemporaryVariableSize();
    Object[] temp = numTempVars > 0 ? new Object[numTempVars] : null;
    int n = instrs.length;
    int ipc = 0;
    Instr instr = null;
    Object exception = null;
    int kwArgHashCount =
        (scope.receivesKeywordArgs() && args[args.length - 1] instanceof RubyHash) ? 1 : 0;
    DynamicScope currDynScope = context.getCurrentScope();

    // Counter tpCount = null;

    // Init profiling this scope
    boolean debug = IRRuntimeHelpers.isDebug();
    boolean profile = IRRuntimeHelpers.inProfileMode();
    Integer scopeVersion = profile ? initProfiling(scope) : 0;

    // Enter the looooop!
    while (ipc < n) {
      instr = instrs[ipc];
      ipc++;
      Operation operation = instr.getOperation();
      if (debug) {
        LOG.info("I: {}", instr);
        interpInstrsCount++;
      } else if (profile) {
        if (operation.modifiesCode()) codeModificationsCount++;
        interpInstrsCount++;
        /*
        Counter cnt = opStats.get(operation);
        if (cnt == null) {
            cnt = new Counter();
            opStats.put(operation, cnt);
        }
        cnt.count++;
        */
      }

      try {
        switch (operation.opClass) {
          case ARG_OP:
            {
              receiveArg(
                  context,
                  instr,
                  operation,
                  args,
                  kwArgHashCount,
                  currDynScope,
                  temp,
                  exception,
                  block);
              break;
            }
          case BRANCH_OP:
            {
              if (operation == Operation.JUMP) {
                ipc = ((JumpInstr) instr).getJumpTarget().getTargetPC();
              } else {
                ipc = instr.interpretAndGetNewIPC(context, currDynScope, self, temp, ipc);
              }
              break;
            }
          case CALL_OP:
            {
              if (profile) updateCallSite(instr, scope, scopeVersion);
              processCall(
                  context, instr, operation, scope, currDynScope, temp, self, block, blockType);
              break;
            }
          case BOOK_KEEPING_OP:
            {
              switch (operation) {
                case PUSH_FRAME:
                  {
                    context.preMethodFrameAndClass(
                        implClass, scope.getName(), self, block, scope.getStaticScope());
                    context.setCurrentVisibility(visibility);
                    break;
                  }
                case PUSH_BINDING:
                  {
                    // SSS NOTE: Method scopes only!
                    //
                    // Blocks are a headache -- so, these instrs. are only added to IRMethods.
                    // Blocks have more complicated logic for pushing a dynamic scope (see
                    // InterpretedIRBlockBody)
                    // Changed by DPR
                    currDynScope =
                        DynamicScope.newDynamicScope(
                            scope.getStaticScope(), context.getCurrentScope().getDepth());
                    context.pushScope(currDynScope);
                    break;
                  }
                case CHECK_ARITY:
                  ((CheckArityInstr) instr).checkArity(context.runtime, args.length);
                  break;
                case POP_FRAME:
                  context.popFrame();
                  context.popRubyClass();
                  break;
                case POP_BINDING:
                  context.popScope();
                  break;
                case THREAD_POLL:
                  if (profile) {
                    // SSS: Not being used currently
                    // tpCount.count++;
                    globalThreadPollCount++;

                    // 20K is arbitrary
                    // Every 20K profile counts, spit out profile stats
                    if (globalThreadPollCount % 20000 == 0) {
                      analyzeProfile();
                      // outputProfileStats();
                    }
                  }
                  context.callThreadPoll();
                  break;
                case LINE_NUM:
                  context.setLine(((LineNumberInstr) instr).lineNumber);
                  break;
                case RECORD_END_BLOCK:
                  ((RecordEndBlockInstr) instr).interpret();
                  break;
              }
              break;
            }
          case OTHER_OP:
            {
              Object result = null;
              switch (operation) {
                  // --------- Return flavored instructions --------
                case BREAK:
                  {
                    BreakInstr bi = (BreakInstr) instr;
                    IRubyObject rv =
                        (IRubyObject)
                            bi.getReturnValue().retrieve(context, self, currDynScope, temp);
                    // This also handles breaks in lambdas -- by converting them to a return
                    return IRRuntimeHelpers.initiateBreak(
                        context, scope, bi.getScopeToReturnTo().getScopeId(), rv, blockType);
                  }
                case RETURN:
                  {
                    return (IRubyObject)
                        retrieveOp(
                            ((ReturnBase) instr).getReturnValue(),
                            context,
                            self,
                            currDynScope,
                            temp);
                  }
                case NONLOCAL_RETURN:
                  {
                    NonlocalReturnInstr ri = (NonlocalReturnInstr) instr;
                    IRubyObject rv =
                        (IRubyObject)
                            retrieveOp(ri.getReturnValue(), context, self, currDynScope, temp);
                    ipc = n;
                    // If not in a lambda, check if this was a non-local return
                    if (!IRRuntimeHelpers.inLambda(blockType)) {
                      IRRuntimeHelpers.initiateNonLocalReturn(
                          context, scope, ri.methodToReturnFrom, rv);
                    }
                    return rv;
                  }

                  // ---------- Common instruction ---------
                case COPY:
                  {
                    CopyInstr c = (CopyInstr) instr;
                    result = retrieveOp(c.getSource(), context, self, currDynScope, temp);
                    setResult(temp, currDynScope, c.getResult(), result);
                    break;
                  }

                case GET_FIELD:
                  {
                    GetFieldInstr gfi = (GetFieldInstr) instr;
                    IRubyObject object =
                        (IRubyObject) gfi.getSource().retrieve(context, self, currDynScope, temp);
                    VariableAccessor a = gfi.getAccessor(object);
                    result = a == null ? null : (IRubyObject) a.get(object);
                    if (result == null) {
                      result = context.nil;
                    }
                    setResult(temp, currDynScope, gfi.getResult(), result);
                    break;
                  }

                case SEARCH_CONST:
                  {
                    SearchConstInstr sci = (SearchConstInstr) instr;
                    result = sci.getCachedConst();
                    if (!sci.isCached(context, result))
                      result = sci.cache(context, currDynScope, self, temp);
                    setResult(temp, currDynScope, sci.getResult(), result);
                    break;
                  }

                  // ---------- All the rest ---------
                default:
                  result = instr.interpret(context, currDynScope, self, temp, block);
                  setResult(temp, currDynScope, instr, result);
                  break;
              }

              break;
            }
        }
      } catch (Throwable t) {
        // Unrescuable:
        //    IRReturnJump, ThreadKill, RubyContinuation, MainExitException, etc.
        //    These cannot be rescued -- only run ensure blocks
        //
        // Others:
        //    IRBreakJump, Ruby exceptions, errors, and other java exceptions.
        //    These can be rescued -- run rescue blocks

        if (debug)
          LOG.info(
              "in scope: "
                  + scope
                  + ", caught Java throwable: "
                  + t
                  + "; excepting instr: "
                  + instr);
        ipc = (t instanceof Unrescuable) ? scope.getEnsurerPC(instr) : scope.getRescuerPC(instr);
        if (debug) LOG.info("ipc for rescuer/ensurer: " + ipc);

        if (ipc == -1) {
          Helpers.throwException((Throwable) t);
        } else {
          exception = t;
        }
      }
    }

    // Control should never get here!
    // SSS FIXME: But looks like BEGIN/END blocks get here -- needs fixing
    return null;
  }