예제 #1
0
 protected long getAddressFromSymbolInfo(VirtualFrame frame, RList symbol) {
   if (addressExtract == null) {
     CompilerDirectives.transferToInterpreterAndInvalidate();
     addressExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true);
   }
   return ((RExternalPtr) addressExtract.applyAccessField(frame, symbol, "address")).getAddr();
 }
예제 #2
0
 protected String getNameFromSymbolInfo(VirtualFrame frame, RList symbol) {
   if (nameExtract == null) {
     CompilerDirectives.transferToInterpreterAndInvalidate();
     nameExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true);
   }
   return RRuntime.asString(nameExtract.applyAccessField(frame, symbol, "name"));
 }
예제 #3
0
  /**
   * Locator for "builtin" package function implementations. The "builtin" packages contain many
   * functions that are called from R code via the FFI, e.g. {@code .Call}, but implemented
   * internally in GnuR, and not necessarily following the FFI API. The value passed to {@code
   * .Call} etc., is a symbol, created when the package is loaded and stored in the namespace
   * environment of the package, that is a list-valued object. Evidently these "builtins" are
   * somewhat similar to the {@code .Primitive} and {@code .Internal} builtins and, similarly, most
   * of these are re-implemented in Java in FastR. The {@link #lookupBuiltin(RList)} method checks
   * the name in the list object and returns the {@link RExternalBuiltinNode} that implements the
   * function, or {@code null}. A {@code null} result implies that the builtin is not implemented in
   * Java, but called directly via the FFI interface, which is only possible for functions that use
   * the FFI in a way that FastR can handle.
   */
  protected abstract static class LookupAdapter extends RBuiltinNode {
    protected static class UnimplementedExternal extends RExternalBuiltinNode {
      private final String name;

      public UnimplementedExternal(String name) {
        this.name = name;
      }

      @Override
      public final Object call(RArgsValuesAndNames args) {
        throw RInternalError.unimplemented("unimplemented external builtin: " + name);
      }
    }

    protected abstract RExternalBuiltinNode lookupBuiltin(RList f);

    private static final String UNKNOWN_EXTERNAL_BUILTIN = "UNKNOWN_EXTERNAL_BUILTIN";

    protected String lookupName(RList f) {
      if (f.getNames() != null) {
        RAbstractStringVector names = f.getNames();
        for (int i = 0; i < names.getLength(); i++) {
          if (names.getDataAt(i).equals("name")) {
            String name = RRuntime.asString(f.getDataAt(i));
            return name != null ? name : UNKNOWN_EXTERNAL_BUILTIN;
          }
        }
      }
      return UNKNOWN_EXTERNAL_BUILTIN;
    }

    protected RuntimeException fallback(Object fobj) {
      String name = null;
      if (fobj instanceof RList) {
        name = lookupName((RList) fobj);
        name = name == UNKNOWN_EXTERNAL_BUILTIN ? null : name;
        if (name != null && lookupBuiltin((RList) fobj) != null) {
          /*
           * if we reach this point, then the cache saw a different value for f. the lists
           * that contain the information about native calls are never expected to change.
           */
          throw RInternalError.shouldNotReachHere(
              "fallback reached for " + getRBuiltin().name() + " " + name);
        }
      }
      throw RError.nyi(
          this,
          getRBuiltin().name() + " specialization failure: " + (name == null ? "<unknown>" : name));
    }

    @Child
    private ExtractVectorNode nameExtract =
        ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true);

    @Child
    private ExtractVectorNode addressExtract =
        ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true);

    protected String getNameFromSymbolInfo(VirtualFrame frame, RList symbol) {
      if (nameExtract == null) {
        CompilerDirectives.transferToInterpreterAndInvalidate();
        nameExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true);
      }
      return RRuntime.asString(nameExtract.applyAccessField(frame, symbol, "name"));
    }

    protected long getAddressFromSymbolInfo(VirtualFrame frame, RList symbol) {
      if (addressExtract == null) {
        CompilerDirectives.transferToInterpreterAndInvalidate();
        addressExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true);
      }
      return ((RExternalPtr) addressExtract.applyAccessField(frame, symbol, "address")).getAddr();
    }

    @Override
    public int getRlengthImpl() {
      // TODO How do we get the length of the actual arguments?
      // This suffices for accessing the "name", which is constant, e.g. .Call
      return 1;
    }

    @Override
    public Object getRelementImpl(int index) {
      if (index == 0) {
        String name = getBuiltin().getName();
        assert name == name.intern();
        return RDataFactory.createSymbol(name);
      } else {
        throw RInternalError.unimplemented();
      }
    }

    @Override
    public void deparseImpl(RDeparse.State state) {
      state.startNodeDeparse(this);
      // FIXME workaround until we can access arguments
      SourceSection ss = getSourceSection();
      assert ss != null;
      state.append(ss.getCode());
      state.endNodeDeparse(this);
    }
  }