示例#1
0
/**
 * Catch a {@code break} from a call with a block containing a break or inside a while/until loop.
 */
public class CatchBreakNode extends RubyNode {

  @Child private RubyNode body;

  private final BreakID breakID;

  private final BranchProfile breakProfile = BranchProfile.create();
  private final ConditionProfile matchingBreakProfile = ConditionProfile.createCountingProfile();

  public CatchBreakNode(
      RubyContext context, SourceSection sourceSection, RubyNode body, BreakID breakID) {
    super(context, sourceSection);
    this.body = body;
    this.breakID = breakID;
  }

  @Override
  public Object execute(VirtualFrame frame) {
    try {
      return body.execute(frame);
    } catch (BreakException e) {
      breakProfile.enter();

      if (matchingBreakProfile.profile(e.getBreakID() == breakID)) {
        return e.getResult();
      } else {
        throw e;
      }
    }
  }
}
@NodeChildren({
  @NodeChild(value = "array", type = RubyNode.class),
  @NodeChild(value = "requiredCapacity", type = RubyNode.class)
})
@ImportStatic(ArrayGuards.class)
public abstract class EnsureCapacityArrayNode extends RubyNode {

  private final ConditionProfile allocateProfile = ConditionProfile.createCountingProfile();

  public EnsureCapacityArrayNode(RubyContext context, SourceSection sourceSection) {
    super(context, sourceSection);
  }

  public abstract Object executeEnsureCapacity(
      VirtualFrame frame, RubyBasicObject array, int requiredCapacity);

  @Specialization(guards = {"isRubyArray(array)", "isIntArray(array)"})
  public boolean ensureCapacityInt(RubyBasicObject array, int requiredCapacity) {
    final int[] store = (int[]) ArrayNodes.getStore(array);

    if (allocateProfile.profile(store.length < requiredCapacity)) {
      ArrayNodes.setStore(
          array,
          Arrays.copyOf(store, ArrayUtils.capacity(store.length, requiredCapacity)),
          ArrayNodes.getSize(array));
      return true;
    } else {
      return false;
    }
  }

  @Specialization(guards = {"isRubyArray(array)", "isLongArray(array)"})
  public boolean ensureCapacityLong(RubyBasicObject array, int requiredCapacity) {
    final long[] store = (long[]) ArrayNodes.getStore(array);

    if (allocateProfile.profile(store.length < requiredCapacity)) {
      ArrayNodes.setStore(
          array,
          Arrays.copyOf(store, ArrayUtils.capacity(store.length, requiredCapacity)),
          ArrayNodes.getSize(array));
      return true;
    } else {
      return false;
    }
  }

  @Specialization(guards = {"isRubyArray(array)", "isDoubleArray(array)"})
  public boolean ensureCapacityDouble(RubyBasicObject array, int requiredCapacity) {
    final double[] store = (double[]) ArrayNodes.getStore(array);

    if (allocateProfile.profile(store.length < requiredCapacity)) {
      ArrayNodes.setStore(
          array,
          Arrays.copyOf(store, ArrayUtils.capacity(store.length, requiredCapacity)),
          ArrayNodes.getSize(array));
      return true;
    } else {
      return false;
    }
  }

  @Specialization(guards = {"isRubyArray(array)", "isObjectArray(array)"})
  public boolean ensureCapacityObject(RubyBasicObject array, int requiredCapacity) {
    final Object[] store = (Object[]) ArrayNodes.getStore(array);

    if (allocateProfile.profile(store.length < requiredCapacity)) {
      ArrayNodes.setStore(
          array,
          Arrays.copyOf(store, ArrayUtils.capacity(store.length, requiredCapacity)),
          ArrayNodes.getSize(array));
      return true;
    } else {
      return false;
    }
  }
}