Пример #1
0
  @Override
  public Object execute(VirtualFrame frame) {
    while (true) {
      getContext().getSafepointManager().poll();

      Object result;

      try {
        result = tryPart.execute(frame);
      } catch (ControlFlowException exception) {
        controlFlowProfile.enter();
        throw exception;
      } catch (RaiseException exception) {
        raiseExceptionProfile.enter();

        try {
          return handleException(frame, exception);
        } catch (RetryException e) {
          continue;
        }
      } finally {
        clearExceptionVariableNode.execute(frame);
      }

      elseProfile.enter();
      elsePart.executeVoid(frame);
      return result;
    }
  }
Пример #2
0
  @Override
  public Object execute(VirtualFrame frame) {
    while (true) {
      try {
        final Object result = tryPart.execute(frame);
        elsePart.executeVoid(frame);
        return result;
      } catch (ControlFlowException exception) {
        controlFlowProfile.enter();

        throw exception;
      } catch (RuntimeException exception) {
        CompilerDirectives.transferToInterpreter();

        try {
          return handleException(frame, exception);
        } catch (RetryException e) {
          continue;
        }
      }
    }
  }
Пример #3
0
/**
 * Represents a block of code run with exception handlers. There's no {@code try} keyword in Ruby -
 * it's implicit - but it's similar to a try statement in any other language.
 */
public class TryNode extends RubyNode {

  @Child protected ExceptionTranslatingNode tryPart;
  @Children final RescueNode[] rescueParts;
  @Child protected RubyNode elsePart;
  @Child protected WriteInstanceVariableNode clearExceptionVariableNode;

  private final BranchProfile elseProfile = BranchProfile.create();
  private final BranchProfile controlFlowProfile = BranchProfile.create();
  private final BranchProfile raiseExceptionProfile = BranchProfile.create();

  public TryNode(
      RubyContext context,
      SourceSection sourceSection,
      ExceptionTranslatingNode tryPart,
      RescueNode[] rescueParts,
      RubyNode elsePart) {
    super(context, sourceSection);
    this.tryPart = tryPart;
    this.rescueParts = rescueParts;
    this.elsePart = elsePart;
    clearExceptionVariableNode =
        new WriteInstanceVariableNode(
            context,
            sourceSection,
            "$!",
            new ObjectLiteralNode(
                context, sourceSection, context.getCoreLibrary().getGlobalVariablesObject()),
            new ObjectLiteralNode(context, sourceSection, context.getCoreLibrary().getNilObject()),
            true);
  }

  @Override
  public Object execute(VirtualFrame frame) {
    while (true) {
      getContext().getSafepointManager().poll();

      Object result;

      try {
        result = tryPart.execute(frame);
      } catch (ControlFlowException exception) {
        controlFlowProfile.enter();
        throw exception;
      } catch (RaiseException exception) {
        raiseExceptionProfile.enter();

        try {
          return handleException(frame, exception);
        } catch (RetryException e) {
          continue;
        }
      } finally {
        clearExceptionVariableNode.execute(frame);
      }

      elseProfile.enter();
      elsePart.executeVoid(frame);
      return result;
    }
  }

  @ExplodeLoop
  private Object handleException(VirtualFrame frame, RaiseException exception) {
    CompilerAsserts.neverPartOfCompilation();

    notDesignedForCompilation();
    getContext()
        .getCoreLibrary()
        .getGlobalVariablesObject()
        .getOperations()
        .setInstanceVariable(
            getContext().getCoreLibrary().getGlobalVariablesObject(),
            "$!",
            exception.getRubyException());

    for (RescueNode rescue : rescueParts) {
      if (rescue.canHandle(frame, exception.getRubyException())) {
        return rescue.execute(frame);
      }
    }

    throw exception;
  }
}