Skip to content
Snippets Groups Projects
Commit 5d738127 authored by Lukas Stadler's avatar Lukas Stadler Committed by stepan
Browse files

intermediate

parent 8a4f468e
No related branches found
No related tags found
No related merge requests found
Showing
with 477 additions and 391 deletions
......@@ -41,7 +41,7 @@ class TruffleLLVM_C implements CRFFI {
private int numArgs;
@Override
public synchronized void execute(NativeCallInfo nativeCallInfo, Object[] args, boolean hasStrings) {
public synchronized void execute(NativeCallInfo nativeCallInfo, Object[] args) {
Object[] wargs = wrap(args);
try {
if (messageNode == null) {
......
......@@ -22,122 +22,39 @@
*/
package com.oracle.truffle.r.ffi.impl.nfi;
import java.nio.charset.StandardCharsets;
import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.interop.CanResolve;
import com.oracle.truffle.api.interop.ForeignAccess;
import com.oracle.truffle.api.interop.InteropException;
import com.oracle.truffle.api.interop.Message;
import com.oracle.truffle.api.interop.MessageResolution;
import com.oracle.truffle.api.interop.Resolve;
import com.oracle.truffle.api.interop.TruffleObject;
import com.oracle.truffle.api.interop.java.JavaInterop;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.r.ffi.impl.interop.UnsafeAdapter;
import com.oracle.truffle.r.ffi.impl.nfi.TruffleNFI_CFactory.TruffleNFI_InvokeCNodeGen;
import com.oracle.truffle.r.runtime.RInternalError;
import com.oracle.truffle.r.runtime.data.RDataFactory;
import com.oracle.truffle.r.runtime.data.RStringVector;
import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
import com.oracle.truffle.r.runtime.ffi.CRFFI;
import com.oracle.truffle.r.runtime.ffi.NativeCallInfo;
import sun.misc.Unsafe;
public class TruffleNFI_C implements CRFFI {
@MessageResolution(receiverType = StringWrapper.class)
public static class StringWrapperMR {
@Resolve(message = "IS_POINTER")
public abstract static class StringWrapperNativeIsPointerNode extends Node {
protected Object access(@SuppressWarnings("unused") StringWrapper receiver) {
return true;
}
}
@Resolve(message = "AS_POINTER")
public abstract static class StringWrapperNativeAsPointerNode extends Node {
protected Object access(StringWrapper receiver) {
return receiver.asPointer();
}
}
@CanResolve
public abstract static class StringWrapperCheck extends Node {
protected static boolean test(TruffleObject receiver) {
return receiver instanceof StringWrapper;
}
}
}
public static final class StringWrapper implements TruffleObject {
private final RAbstractStringVector vector;
private long address;
public StringWrapper(RAbstractStringVector vector) {
this.vector = vector;
}
@Override
public ForeignAccess getForeignAccess() {
return StringWrapperMRForeign.ACCESS;
}
private static final String[] SIGNATURES = new String[32];
public long asPointer() {
if (address == 0) {
address = allocate();
}
return address;
}
@TruffleBoundary
private long allocate() {
int length = vector.getLength();
int size = length * 8;
byte[][] bytes = new byte[length][];
for (int i = 0; i < length; i++) {
String element = vector.getDataAt(i);
bytes[i] = element.getBytes(StandardCharsets.US_ASCII);
size += bytes[i].length + 1;
private static String getSignatureForArity(int arity) {
CompilerAsserts.neverPartOfCompilation();
if (arity >= SIGNATURES.length || SIGNATURES[arity] == null) {
StringBuilder str = new StringBuilder().append('(');
for (int i = 0; i < arity; i++) {
str.append(i > 0 ? ", " : "");
str.append("pointer");
}
long memory = UnsafeAdapter.UNSAFE.allocateMemory(size);
long ptr = memory + length * 8; // start of the actual character data
for (int i = 0; i < length; i++) {
UnsafeAdapter.UNSAFE.putLong(memory + i * 8, ptr);
UnsafeAdapter.UNSAFE.copyMemory(bytes[i], Unsafe.ARRAY_BYTE_BASE_OFFSET, null, ptr, bytes[i].length);
ptr += bytes[i].length;
UnsafeAdapter.UNSAFE.putByte(ptr++, (byte) 0);
}
assert ptr == memory + size : "should have filled everything";
return memory;
}
public RAbstractStringVector copyBack(RAbstractStringVector original) {
if (address == 0) {
return original;
} else {
RStringVector result = original.materialize();
String[] data = result.isTemporary() ? result.getDataWithoutCopying() : result.getDataCopy();
for (int i = 0; i < data.length; i++) {
long ptr = UnsafeAdapter.UNSAFE.getLong(address + i * 8);
int length = 0;
while (UnsafeAdapter.UNSAFE.getByte(ptr + length) != 0) {
length++;
}
byte[] bytes = new byte[length];
UnsafeAdapter.UNSAFE.copyMemory(null, ptr, bytes, Unsafe.ARRAY_BYTE_BASE_OFFSET, length);
data[i] = new String(bytes, StandardCharsets.US_ASCII);
}
UnsafeAdapter.UNSAFE.freeMemory(address);
return RDataFactory.createStringVector(data, true);
String signature = str.append("): void").toString();
if (arity < SIGNATURES.length) {
SIGNATURES[arity] = signature;
}
return signature;
} else {
return SIGNATURES[arity];
}
}
......@@ -145,31 +62,25 @@ public class TruffleNFI_C implements CRFFI {
@Child private Node bindNode = Message.createInvoke(1).createNode();
@Override
protected Object getNativeArgument(int index, ArgumentType type, RAbstractAtomicVector vector) {
if (type == ArgumentType.VECTOR_STRING) {
return new StringWrapper((RAbstractStringVector) vector);
} else {
return super.getNativeArgument(index, type, vector);
}
}
@Override
protected Object postProcessArgument(ArgumentType type, RAbstractAtomicVector vector, Object nativeArgument) {
if (type == ArgumentType.VECTOR_STRING) {
return ((StringWrapper) nativeArgument).copyBack((RAbstractStringVector) vector);
} else {
return super.postProcessArgument(type, vector, nativeArgument);
@TruffleBoundary
protected TruffleObject getFunction(TruffleObject address, int arity) {
// cache signatures
try {
return (TruffleObject) ForeignAccess.sendInvoke(bindNode, address, "bind", getSignatureForArity(arity));
} catch (InteropException ex) {
throw RInternalError.shouldNotReachHere(ex);
}
}
@Specialization(guards = "args.length == 0")
protected void invokeCall0(NativeCallInfo nativeCallInfo, @SuppressWarnings("unused") Object[] args, @SuppressWarnings("unused") boolean hasStrings,
@Cached("createExecute(args.length)") Node executeNode) {
@Specialization(guards = {"args.length == cachedArgsLength", "nativeCallInfo.address.asTruffleObject() == cachedAddress"})
protected void invokeCallCached(@SuppressWarnings("unused") NativeCallInfo nativeCallInfo, Object[] args,
@SuppressWarnings("unused") @Cached("args.length") int cachedArgsLength,
@Cached("createExecute(cachedArgsLength)") Node executeNode,
@SuppressWarnings("unused") @Cached("nativeCallInfo.address.asTruffleObject()") TruffleObject cachedAddress,
@Cached("getFunction(cachedAddress, cachedArgsLength)") TruffleObject cachedFunction) {
synchronized (TruffleNFI_Call.class) {
try {
TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, nativeCallInfo.address.asTruffleObject(), "bind", "(): void");
ForeignAccess.sendExecute(executeNode, callFunction);
ForeignAccess.sendExecute(executeNode, cachedFunction, args);
} catch (InteropException ex) {
throw RInternalError.shouldNotReachHere(ex);
}
......@@ -177,14 +88,12 @@ public class TruffleNFI_C implements CRFFI {
}
@Specialization(limit = "99", guards = "args.length == cachedArgsLength")
protected void invokeCall1(NativeCallInfo nativeCallInfo, Object[] args, @SuppressWarnings("unused") boolean hasStrings,
protected void invokeCallCachedLength(NativeCallInfo nativeCallInfo, Object[] args,
@Cached("args.length") int cachedArgsLength,
@Cached("createExecute(cachedArgsLength)") Node executeNode) {
synchronized (TruffleNFI_Call.class) {
try {
Object[] nargs = new Object[cachedArgsLength];
TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode, nativeCallInfo.address.asTruffleObject(), "bind", getSignature(args, nargs));
ForeignAccess.sendExecute(executeNode, callFunction, nargs);
ForeignAccess.sendExecute(executeNode, getFunction(nativeCallInfo.address.asTruffleObject(), cachedArgsLength), args);
} catch (InteropException ex) {
throw RInternalError.shouldNotReachHere(ex);
}
......@@ -196,30 +105,6 @@ public class TruffleNFI_C implements CRFFI {
}
}
@TruffleBoundary
private static String getSignature(Object[] args, Object[] nargs) {
StringBuilder sb = new StringBuilder();
sb.append('(');
for (int i = 0; i < args.length; i++) {
Object arg = args[i];
if (arg instanceof int[]) {
sb.append("[sint32]");
} else if (arg instanceof double[]) {
sb.append("[double]");
} else if (arg instanceof StringWrapper) {
sb.append("pointer");
} else {
throw RInternalError.unimplemented(".C type: " + arg.getClass().getSimpleName());
}
nargs[i] = JavaInterop.asTruffleObject(arg);
if (i < args.length - 1) {
sb.append(", ");
}
}
sb.append("): void");
return sb.toString();
}
@Override
public InvokeCNode createInvokeCNode() {
return TruffleNFI_InvokeCNodeGen.create();
......
......@@ -235,32 +235,36 @@ public class TruffleNFI_Call implements CallRFFI {
}
}
private static final String[] SIGNATURES = new String[32];
private static String getSignatureForArity(int arity) {
CompilerAsserts.neverPartOfCompilation();
if (arity >= SIGNATURES.length || SIGNATURES[arity] == null) {
StringBuilder str = new StringBuilder().append('(');
for (int i = 0; i < arity; i++) {
str.append(i > 0 ? ", " : "");
str.append("pointer");
}
String signature = str.append("): pointer").toString();
if (arity < SIGNATURES.length) {
SIGNATURES[arity] = signature;
}
return signature;
} else {
return SIGNATURES[arity];
}
}
@ImportStatic(FFIWrapNode.class)
public abstract static class TruffleNFI_InvokeCallNode extends Node implements InvokeCallNode {
private static final String[] SIGNATURES = new String[32];
@Child private Node bindNode = Message.createInvoke(1).createNode();
@TruffleBoundary
protected TruffleObject getFunction(TruffleObject address, int arity) {
// cache signatures
String signature;
if (arity >= SIGNATURES.length || SIGNATURES[arity] == null) {
StringBuilder str = new StringBuilder().append('(');
for (int i = 0; i < arity; i++) {
str.append(i > 0 ? ", " : "");
str.append("pointer");
}
str.append("): pointer");
signature = str.toString();
if (arity < SIGNATURES.length) {
SIGNATURES[arity] = signature;
}
} else {
signature = SIGNATURES[arity];
}
try {
return (TruffleObject) ForeignAccess.sendInvoke(bindNode, address, "bind", signature);
return (TruffleObject) ForeignAccess.sendInvoke(bindNode, address, "bind", getSignatureForArity(arity));
} catch (InteropException ex) {
throw RInternalError.shouldNotReachHere(ex);
}
......
......@@ -24,8 +24,6 @@ package com.oracle.truffle.r.ffi.impl.nfi;
import static com.oracle.truffle.r.ffi.impl.common.RFFIUtils.guaranteeInstanceOf;
import java.nio.charset.StandardCharsets;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.interop.CanResolve;
import com.oracle.truffle.api.interop.ForeignAccess;
......@@ -37,18 +35,12 @@ import com.oracle.truffle.api.interop.TruffleObject;
import com.oracle.truffle.api.interop.UnsupportedMessageException;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.r.ffi.impl.common.JavaUpCallsRFFIImpl;
import com.oracle.truffle.r.ffi.impl.common.RFFIUtils;
import com.oracle.truffle.r.ffi.impl.interop.UnsafeAdapter;
import com.oracle.truffle.r.ffi.impl.nfi.TruffleNFI_C.StringWrapper;
import com.oracle.truffle.r.ffi.impl.upcalls.FFIUnwrapNode;
import com.oracle.truffle.r.runtime.RError;
import com.oracle.truffle.r.runtime.RInternalError;
import com.oracle.truffle.r.runtime.data.RDataFactory;
import com.oracle.truffle.r.runtime.data.RIntVector;
import com.oracle.truffle.r.runtime.data.RLogicalVector;
import com.oracle.truffle.r.runtime.data.RStringVector;
import com.oracle.truffle.r.runtime.data.RVector;
import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper;
import com.oracle.truffle.r.runtime.ffi.DLL;
import com.oracle.truffle.r.runtime.ffi.DLL.CEntry;
......@@ -57,8 +49,6 @@ import com.oracle.truffle.r.runtime.ffi.DLL.DotSymbol;
import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
import sun.misc.Unsafe;
public class TruffleNFI_UpCallsRFFIImpl extends JavaUpCallsRFFIImpl {
private static final String SETSYMBOL_SIGNATURE = "(pointer, sint32, pointer, sint32): pointer";
......
......@@ -70,6 +70,7 @@ import com.oracle.truffle.r.library.utils.TypeConvertNodeGen;
import com.oracle.truffle.r.library.utils.UnzipNodeGen;
import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
import com.oracle.truffle.r.nodes.builtin.RInternalCodeBuiltinNode;
import com.oracle.truffle.r.nodes.builtin.base.foreign.LookupAdapter.ExtractNativeCallInfoNode;
import com.oracle.truffle.r.nodes.objects.GetPrimNameNodeGen;
import com.oracle.truffle.r.nodes.objects.NewObjectNodeGen;
import com.oracle.truffle.r.runtime.FastROptions;
......@@ -653,10 +654,11 @@ public class CallAndExternalFunctions {
*/
@SuppressWarnings("unused")
@Specialization(limit = "2", guards = {"cached == symbol", "builtin == null"})
protected Object callNamedFunction(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, Object packageName,
protected Object callNamedFunction(RList symbol, RArgsValuesAndNames args, Object packageName,
@Cached("symbol") RList cached,
@Cached("lookupBuiltin(symbol)") RExternalBuiltinNode builtin,
@Cached("extractSymbolInfo.execute(frame, symbol)") NativeCallInfo nativeCallInfo) {
@Cached("new()") ExtractNativeCallInfoNode extractSymbolInfo,
@Cached("extractSymbolInfo.execute(symbol)") NativeCallInfo nativeCallInfo) {
return callRFFINode.execute(nativeCallInfo, args.getArguments());
}
......@@ -666,12 +668,13 @@ public class CallAndExternalFunctions {
*/
@SuppressWarnings("unused")
@Specialization(replaces = {"callNamedFunction", "doExternal"})
protected Object callNamedFunctionGeneric(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, Object packageName) {
protected Object callNamedFunctionGeneric(RList symbol, RArgsValuesAndNames args, Object packageName,
@Cached("new()") ExtractNativeCallInfoNode extractSymbolInfo) {
RExternalBuiltinNode builtin = lookupBuiltin(symbol);
if (builtin != null) {
throw RInternalError.shouldNotReachHere("Cache for .Calls with FastR reimplementation (lookupBuiltin(...) != null) exceeded the limit");
}
NativeCallInfo nativeCallInfo = extractSymbolInfo.execute(frame, symbol);
NativeCallInfo nativeCallInfo = extractSymbolInfo.execute(symbol);
return callRFFINode.execute(nativeCallInfo, args.getArguments());
}
......@@ -786,9 +789,10 @@ public class CallAndExternalFunctions {
@SuppressWarnings("unused")
@Specialization(limit = "1", guards = {"cached == symbol"})
protected Object callNamedFunction(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, Object packageName,
protected Object callNamedFunction(RList symbol, RArgsValuesAndNames args, Object packageName,
@Cached("symbol") RList cached,
@Cached("extractSymbolInfo.execute(frame, symbol)") NativeCallInfo nativeCallInfo) {
@Cached("new()") ExtractNativeCallInfoNode extractSymbolInfo,
@Cached("extractSymbolInfo.execute(symbol)") NativeCallInfo nativeCallInfo) {
Object list = encodeArgumentPairList(args, nativeCallInfo.name);
return callRFFINode.execute(nativeCallInfo, new Object[]{list});
}
......@@ -882,9 +886,10 @@ public class CallAndExternalFunctions {
@SuppressWarnings("unused")
@Specialization(limit = "1", guards = {"cached == symbol"})
protected Object callNamedFunction(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, Object packageName,
protected Object callNamedFunction(RList symbol, RArgsValuesAndNames args, Object packageName,
@Cached("symbol") RList cached,
@Cached("extractSymbolInfo.execute(frame, symbol)") NativeCallInfo nativeCallInfo) {
@Cached("new()") ExtractNativeCallInfoNode extractSymbolInfo,
@Cached("extractSymbolInfo.execute(symbol)") NativeCallInfo nativeCallInfo) {
Object list = encodeArgumentPairList(args, nativeCallInfo.name);
return callRFFINode.execute(nativeCallInfo, new Object[]{CALL, getOp(), list, RHO});
}
......@@ -938,8 +943,9 @@ public class CallAndExternalFunctions {
}
@Specialization
protected Object callNamedFunction(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, @SuppressWarnings("unused") Object packageName) {
NativeCallInfo nativeCallInfo = extractSymbolInfo.execute(frame, symbol);
protected Object callNamedFunction(RList symbol, RArgsValuesAndNames args, @SuppressWarnings("unused") Object packageName,
@Cached("new()") ExtractNativeCallInfoNode extractSymbolInfo) {
NativeCallInfo nativeCallInfo = extractSymbolInfo.execute(symbol);
Object list = encodeArgumentPairList(args, nativeCallInfo.name);
return callRFFINode.execute(nativeCallInfo, new Object[]{list});
}
......@@ -1000,8 +1006,9 @@ public class CallAndExternalFunctions {
}
@Specialization
protected Object callNamedFunction(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, @SuppressWarnings("unused") Object packageName) {
NativeCallInfo nativeCallInfo = extractSymbolInfo.execute(frame, symbol);
protected Object callNamedFunction(RList symbol, RArgsValuesAndNames args, @SuppressWarnings("unused") Object packageName,
@Cached("new()") ExtractNativeCallInfoNode extractSymbolInfo) {
NativeCallInfo nativeCallInfo = extractSymbolInfo.execute(symbol);
return callRFFINode.execute(nativeCallInfo, args.getArguments());
}
......
......@@ -27,7 +27,6 @@ import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
import com.oracle.truffle.r.nodes.builtin.base.foreign.FortranAndCFunctionsFactory.FortranResultNamesSetterNodeGen;
import com.oracle.truffle.r.nodes.builtin.base.foreign.LookupAdapter.ExtractNativeCallInfoNode;
import com.oracle.truffle.r.nodes.builtin.base.foreign.LookupAdapterFactory.ExtractNativeCallInfoNodeGen;
import com.oracle.truffle.r.runtime.ArgumentsSignature;
import com.oracle.truffle.r.runtime.RError;
import com.oracle.truffle.r.runtime.RRuntime;
......@@ -56,7 +55,6 @@ public class FortranAndCFunctions {
protected abstract static class CRFFIAdapter extends RBuiltinNode.Arg6 {
@Child protected ExtractNativeCallInfoNode extractSymbolInfo = ExtractNativeCallInfoNodeGen.create();
@Child protected CRFFI.InvokeCNode invokeCNode = RFFIFactory.getCRFFI().createInvokeCNode();
@Override
......@@ -101,16 +99,15 @@ public class FortranAndCFunctions {
@SuppressWarnings("unused")
@Specialization(limit = "1", guards = {"cached == symbol", "builtin != null"})
protected Object doExternal(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, byte naok, byte dup, Object rPackage, RMissing encoding,
@Cached("symbol") RList cached,
protected Object doExternal(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, byte naok, byte dup, Object rPackage, RMissing encoding, @Cached("symbol") RList cached,
@Cached("lookupBuiltin(symbol)") RExternalBuiltinNode builtin) {
return resNamesSetter.execute(builtin.call(frame, args), args);
}
@Specialization(guards = "lookupBuiltin(symbol) == null")
protected RList c(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, byte naok, byte dup, @SuppressWarnings("unused") Object rPackage,
@SuppressWarnings("unused") RMissing encoding) {
NativeCallInfo nativeCallInfo = extractSymbolInfo.execute(frame, symbol);
protected RList c(RList symbol, RArgsValuesAndNames args, byte naok, byte dup, @SuppressWarnings("unused") Object rPackage, @SuppressWarnings("unused") RMissing encoding,
@Cached("new()") ExtractNativeCallInfoNode extractSymbolInfo) {
NativeCallInfo nativeCallInfo = extractSymbolInfo.execute(symbol);
return invokeCNode.dispatch(nativeCallInfo, naok, dup, args);
}
......@@ -179,8 +176,9 @@ public class FortranAndCFunctions {
}
@Specialization
protected RList c(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, byte naok, byte dup, @SuppressWarnings("unused") Object rPackage, @SuppressWarnings("unused") RMissing encoding) {
NativeCallInfo nativeCallInfo = extractSymbolInfo.execute(frame, symbol);
protected RList c(RList symbol, RArgsValuesAndNames args, byte naok, byte dup, @SuppressWarnings("unused") Object rPackage, @SuppressWarnings("unused") RMissing encoding,
@Cached("new()") ExtractNativeCallInfoNode extractSymbolInfo) {
NativeCallInfo nativeCallInfo = extractSymbolInfo.execute(symbol);
return invokeCNode.dispatch(nativeCallInfo, naok, dup, args);
}
......
......@@ -23,10 +23,7 @@
package com.oracle.truffle.r.nodes.builtin.base.foreign;
import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.r.library.stats.RandFunctionsNodes;
import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
......@@ -34,7 +31,6 @@ import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
import com.oracle.truffle.r.nodes.builtin.RInternalCodeBuiltinNode;
import com.oracle.truffle.r.nodes.builtin.base.foreign.LookupAdapterFactory.ExtractNativeCallInfoNodeGen;
import com.oracle.truffle.r.runtime.RError;
import com.oracle.truffle.r.runtime.RInternalCode;
import com.oracle.truffle.r.runtime.RInternalError;
......@@ -72,7 +68,6 @@ interface Lookup {
* still implemented by native code.
*/
abstract class LookupAdapter extends RBuiltinNode.Arg3 implements Lookup {
@Child protected ExtractNativeCallInfoNode extractSymbolInfo = ExtractNativeCallInfoNodeGen.create();
protected static class UnimplementedExternal extends RExternalBuiltinNode {
private final String name;
......@@ -139,35 +134,19 @@ abstract class LookupAdapter extends RBuiltinNode.Arg3 implements Lookup {
* Extracts the salient information needed for a native call from the {@link RList} value
* provided from R.
*/
public abstract static class ExtractNativeCallInfoNode extends Node {
public static final class ExtractNativeCallInfoNode extends Node {
@Child private ExtractVectorNode nameExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true);
@Child private ExtractVectorNode addressExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true);
@Child private ExtractVectorNode packageExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true);
@Child private ExtractVectorNode infoExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true);
protected abstract NativeCallInfo execute(VirtualFrame frame, RList symbol);
@Specialization
protected NativeCallInfo extractNativeCallInfo(RList symbol) {
if (nameExtract == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
nameExtract = insert(ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true));
}
if (addressExtract == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
addressExtract = insert(ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true));
}
if (packageExtract == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
packageExtract = insert(ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true));
}
protected NativeCallInfo execute(RList symbol) {
String name = RRuntime.asString(nameExtract.applyAccessField(symbol, "name"));
SymbolHandle address = ((RExternalPtr) addressExtract.applyAccessField(symbol, "address")).getAddr();
// field name may be "package" or "dll", but always at (R) index 3
RList packageList = (RList) packageExtract.apply(symbol, new Object[]{3}, RLogical.valueOf(false), RMissing.instance);
DLLInfo dllInfo = (DLLInfo) ((RExternalPtr) addressExtract.applyAccessField(packageList, "info")).getExternalObject();
DLLInfo dllInfo = (DLLInfo) ((RExternalPtr) infoExtract.applyAccessField(packageList, "info")).getExternalObject();
return new NativeCallInfo(name, address, dllInfo);
}
}
......
......@@ -13,6 +13,7 @@ package com.oracle.truffle.r.runtime.ffi;
import java.io.File;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.concurrent.atomic.AtomicInteger;
import com.oracle.truffle.api.CompilerAsserts;
......@@ -190,6 +191,7 @@ public class DLL {
private boolean forceSymbols;
private final DotSymbol[][] nativeSymbols = new DotSymbol[NativeSymbolType.values().length][];
private ArrayList<CEntry> cEntryTable = null;
private final HashSet<String> unsuccessfulLookups = new HashSet<>();
private DLLInfo(String name, String path, boolean dynamicLookup, Object handle) {
this.id = ID.getAndIncrement();
......@@ -581,7 +583,7 @@ public class DLL {
}
public static final class RFindSymbolNode extends Node {
@Child RdlsymNode rdlsymNode = new RdlsymNode();
@Child private RdlsymNode rdlsymNode = new RdlsymNode();
/**
* Directly analogous to the GnuR function {@code R_FindSymbol}.
......@@ -681,9 +683,13 @@ public class DLL {
mName = name + "_";
}
try {
if (dllInfo.unsuccessfulLookups.contains(mName)) {
return SYMBOL_NOT_FOUND;
}
SymbolHandle symValue = dlSymNode.execute(dllInfo.handle, mName);
return symValue;
} catch (UnsatisfiedLinkError ex) {
dllInfo.unsuccessfulLookups.add(mName);
return SYMBOL_NOT_FOUND;
}
}
......
/*
* Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.truffle.r.runtime.ffi;
import java.lang.reflect.Field;
import sun.misc.Unsafe;
public class UnsafeAdapter {
public static final Unsafe UNSAFE = initUnsafe();
private static Unsafe initUnsafe() {
try {
return Unsafe.getUnsafe();
} catch (SecurityException se) {
try {
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
return (Unsafe) theUnsafe.get(Unsafe.class);
} catch (Exception e) {
throw new RuntimeException("exception while trying to get Unsafe", e);
}
}
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment