예제 #1
0
  /**
   * Given a packed descriptor listing methods and their type, populate the call site cache.
   *
   * <p>The format of the methods portion of the descriptor is name1;type1;name2;type2 where type1
   * and type2 are a single capital letter N, F, V, or S for the four main call types. After the
   * method portion, the other cache sizes are provided as a packed String of char values
   * representing the numeric sizes. @see RuntimeCache#initOthers.
   *
   * @param descriptor The descriptor to use for populating call sites and caches
   */
  public final void initFromDescriptor(String descriptor) {
    String[] pieces = descriptor.split("\uFFFF");
    CallSite[] sites = new CallSite[pieces.length - 1 / 2];

    // if there's no call sites, don't process it
    if (pieces[0].length() != 0) {
      for (int i = 0; i < pieces.length - 1; i += 2) {
        switch (pieces[i + 1].charAt(0)) {
          case 'N':
            sites[i / 2] = MethodIndex.getCallSite(pieces[i]);
            break;
          case 'F':
            sites[i / 2] = MethodIndex.getFunctionalCallSite(pieces[i]);
            break;
          case 'V':
            sites[i / 2] = MethodIndex.getVariableCallSite(pieces[i]);
            break;
          case 'S':
            sites[i / 2] = MethodIndex.getSuperCallSite();
            break;
          default:
            throw new RuntimeException(
                "Unknown call type: " + pieces[i + 1] + " for method " + pieces[i]);
        }
      }

      this.callSites = sites;
    }

    initOthers(pieces[pieces.length - 1]);
  }
예제 #2
0
  private static CallSite getCallSiteFor(CallType callType, MethAddr methAddr) {
    assert callType != null : "Calltype should never be null";

    String name = methAddr.toString();

    switch (callType) {
      case NORMAL:
        return MethodIndex.getCallSite(name);
      case FUNCTIONAL:
        return MethodIndex.getFunctionalCallSite(name);
      case VARIABLE:
        return MethodIndex.getVariableCallSite(name);
      case SUPER:
        return MethodIndex.getSuperCallSite();
      case UNKNOWN:
    }

    return null; // fallthrough for unknown
  }
예제 #3
0
/**
 * A 'for' statement. This is implemented using iter and that is how MRI does things, but 'for's do
 * not have their own stack, so doing this way is mildly painful.
 *
 * @see IterNode
 */
public class ForNode extends IterNode {
  public final CallSite callAdapter = MethodIndex.getCallSite("each");

  private Node iterNode;

  public ForNode(
      ISourcePosition position, Node varNode, Node bodyNode, Node iterNode, StaticScope scope) {
    // For nodes do not have their own scope so we pass null to indicate this.
    // 'For's are implemented as blocks in evaluation, but they have no scope so we
    // just deal with this lack of scope throughout its lifespan.  We should probably
    // change the way this works to get rid of multiple null checks.
    super(position, varNode, scope, bodyNode);

    assert iterNode != null : "iterNode is not null";

    this.iterNode = iterNode;
  }

  @Override
  public NodeType getNodeType() {
    return NodeType.FORNODE;
  }

  public Node getIterNode() {
    return iterNode;
  }

  /**
   * Accept for the visitor pattern.
   *
   * @param iVisitor the visitor
   */
  @Override
  public Object accept(NodeVisitor iVisitor) {
    return iVisitor.visitForNode(this);
  }

  @Override
  public List<Node> childNodes() {
    return Node.createList(getVarNode(), getBodyNode(), iterNode);
  }

  @Override
  public IRubyObject interpret(
      Ruby runtime, ThreadContext context, IRubyObject self, Block aBlock) {
    Block block =
        SharedScopeBlock.newInterpretedSharedScopeClosure(
            context, this, context.getCurrentScope(), self);

    try {
      while (true) {
        try {
          String savedFile = context.getFile();
          int savedLine = context.getLine();

          IRubyObject recv = null;
          try {
            recv = iterNode.interpret(runtime, context, self, aBlock);
          } finally {
            context.setFileAndLine(savedFile, savedLine);
          }

          return callAdapter.call(context, self, recv, block);
        } catch (JumpException.RetryJump rj) {
          // do nothing, allow loop to retry
        }
      }
    } catch (JumpException.BreakJump bj) {
      return (IRubyObject) bj.getValue();
    }
  }
}