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(); }
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")); }
/** * 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); } }