From eb7126cb346a5d9a076e774cc43f9fedc73b22e8 Mon Sep 17 00:00:00 2001 From: Mick Jordan <mick.jordan@oracle.com> Date: Wed, 23 Nov 2016 11:08:25 -0800 Subject: [PATCH] abstract the representation of external symbols --- .../truffle/r/library/graphics/RGraphics.java | 2 +- .../library/methods/MethodsListDispatch.java | 3 +- .../fficall/src/jni/Rinternals.c | 14 ++- .../fficall/src/jniboot/jniboot.c | 8 +- .../nodes/builtin/base/DynLoadFunctions.java | 6 +- .../builtin/base/HiddenInternalFunctions.java | 2 +- .../r/nodes/builtin/base/foreign/DotC.java | 15 +-- .../base/foreign/ForeignFunctions.java | 15 +-- .../r/runtime/ffi/generic/Generic_Grid.java | 13 ++- .../r/runtime/ffi/generic/Generic_Tools.java | 8 +- .../truffle/r/runtime/ffi/jni/JNI_C.java | 5 +- .../truffle/r/runtime/ffi/jni/JNI_Call.java | 13 ++- .../truffle/r/runtime/ffi/jni/JNI_DLL.java | 74 +++++++++++++ .../r/runtime/ffi/jni/JNI_PkgInit.java | 3 +- .../r/runtime/ffi/jni/JNI_RFFIFactory.java | 11 ++ .../truffle/r/runtime/ffi/jni/JNI_Stats.java | 21 ++-- .../r/runtime/ffi/jni/JNI_UserRng.java | 8 +- .../oracle/truffle/r/runtime/RDeparse.java | 2 +- .../oracle/truffle/r/runtime/RSerialize.java | 3 +- .../truffle/r/runtime/conn/RConnection.java | 2 +- .../truffle/r/runtime/data/RDataFactory.java | 7 +- .../truffle/r/runtime/data/RExternalPtr.java | 19 ++-- .../oracle/truffle/r/runtime/ffi/CRFFI.java | 8 +- .../truffle/r/runtime/ffi/CallRFFI.java | 8 +- .../com/oracle/truffle/r/runtime/ffi/DLL.java | 103 ++++++++++++------ .../oracle/truffle/r/runtime/ffi/DLLRFFI.java | 55 ++++++++++ .../oracle/truffle/r/runtime/ffi/RFFI.java | 3 + .../truffle/r/runtime/rng/user/UserRNG.java | 20 ++-- 28 files changed, 328 insertions(+), 123 deletions(-) create mode 100644 com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_DLL.java create mode 100644 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLLRFFI.java diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/RGraphics.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/RGraphics.java index bc7dc453e6..c87b109962 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/RGraphics.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/RGraphics.java @@ -61,7 +61,7 @@ public class RGraphics { registerBaseGraphicsSystem(); } else { DLL.RegisteredNativeSymbol rns = DLL.RegisteredNativeSymbol.any(); - long func = DLL.findSymbol("InitGraphics", null, rns); + DLL.SymbolHandle func = DLL.findSymbol("InitGraphics", null, rns); assert func != DLL.SYMBOL_NOT_FOUND; RFFIFactory.getRFFI().getCallRFFI().invokeVoidCall(func, "InitGraphics", new Object[0]); } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java index 3155f9880e..88da7a9813 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java @@ -53,6 +53,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.ffi.DLL; import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.nodes.RNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; @@ -418,7 +419,7 @@ public class MethodsListDispatch { // whose only purpose is to throw an error indicating that it shouldn't be called // TODO: finesse error handling in case a function stored in this pointer is actually // called - return RDataFactory.createExternalPtr(0, RNull.instance, RNull.instance); + return RDataFactory.createExternalPtr(new DLL.SymbolHandle(0L), RNull.instance, RNull.instance); } } } diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c index 037edd13c8..16f188e378 100644 --- a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c +++ b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c @@ -114,6 +114,9 @@ static jclass handlerStacksClass; static jmethodID resetAndGetHandlerStacksMethodID; static jmethodID restoreHandlerStacksMethodID; +static jclass SymbolHandleClass; +static jmethodID symbolHandleConsMethodID; + static jclass RExternalPtrClass; static jmethodID createExternalPtrMethodID; static jmethodID externalPtrGetAddrMethodID; @@ -217,14 +220,16 @@ void init_internals(JNIEnv *env) { restoreHandlerStacksMethodID = checkGetMethodID(env, rErrorHandlingClass, "restoreHandlerStacks", "(Lcom/oracle/truffle/r/runtime/RErrorHandling$HandlerStacks;)V", 1); RExternalPtrClass = checkFindClass(env, "com/oracle/truffle/r/runtime/data/RExternalPtr"); - createExternalPtrMethodID = checkGetMethodID(env, RDataFactoryClass, "createExternalPtr", "(JLjava/lang/Object;Ljava/lang/Object;)Lcom/oracle/truffle/r/runtime/data/RExternalPtr;", 1); - externalPtrGetAddrMethodID = checkGetMethodID(env, RExternalPtrClass, "getAddr", "()J", 0); + createExternalPtrMethodID = checkGetMethodID(env, RDataFactoryClass, "createExternalPtr", "(Lcom/oracle/truffle/r/runtime/ffi/DLL$SymbolHandle;Ljava/lang/Object;Ljava/lang/Object;)Lcom/oracle/truffle/r/runtime/data/RExternalPtr;", 1); + externalPtrGetAddrMethodID = checkGetMethodID(env, RExternalPtrClass, "getAddr", "()Lcom/oracle/truffle/r/runtime/ffi/DLL$SymbolHandle;", 0); externalPtrGetTagMethodID = checkGetMethodID(env, RExternalPtrClass, "getTag", "()Ljava/lang/Object;", 0); externalPtrGetProtMethodID = checkGetMethodID(env, RExternalPtrClass, "getProt", "()Ljava/lang/Object;", 0); - externalPtrSetAddrMethodID = checkGetMethodID(env, RExternalPtrClass, "setAddr", "(J)V", 0); + externalPtrSetAddrMethodID = checkGetMethodID(env, RExternalPtrClass, "setAddr", "(Lcom/oracle/truffle/r/runtime/ffi/DLL$SymbolHandle;)V", 0); externalPtrSetTagMethodID = checkGetMethodID(env, RExternalPtrClass, "setTag", "(Ljava/lang/Object;)V", 0); externalPtrSetProtMethodID = checkGetMethodID(env, RExternalPtrClass, "setProt", "(Ljava/lang/Object;)V", 0); + SymbolHandleClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/DLL$SymbolHandle"); + symbolHandleConsMethodID = checkGetMethodID(env, SymbolHandleClass, "<init>", "(Ljava/lang/Object;)V", 0); CharSXPWrapperClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/jni/CallRFFIHelper$CharSXPWrapper"); CharSXPWrapperContentsFieldID = checkGetFieldID(env, CharSXPWrapperClass, "contents", "Ljava/lang/String;", 0); @@ -1503,7 +1508,8 @@ SEXP R_forceAndCall(SEXP e, int n, SEXP rho) { SEXP R_MakeExternalPtr(void *p, SEXP tag, SEXP prot) { JNIEnv *thisenv = getEnv(); - SEXP result = (*thisenv)->CallStaticObjectMethod(thisenv, RDataFactoryClass, createExternalPtrMethodID, (jlong) p, tag, prot); + jobject handle = (*thisenv)->CallStaticObjectMethod(thisenv, SymbolHandleClass, symbolHandleConsMethodID, (jobject) p); + SEXP result = (*thisenv)->CallStaticObjectMethod(thisenv, RDataFactoryClass, createExternalPtrMethodID, handle, tag, prot); return checkRef(thisenv, result); } diff --git a/com.oracle.truffle.r.native/fficall/src/jniboot/jniboot.c b/com.oracle.truffle.r.native/fficall/src/jniboot/jniboot.c index aa51df6764..22aab408ee 100644 --- a/com.oracle.truffle.r.native/fficall/src/jniboot/jniboot.c +++ b/com.oracle.truffle.r.native/fficall/src/jniboot/jniboot.c @@ -48,7 +48,7 @@ static void create_dlerror_string(JNIEnv *env) { } JNIEXPORT jlong JNICALL -Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1dlopen(JNIEnv *env, jclass c, jstring jpath, jboolean local, jboolean now) { +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1DLL_native_1dlopen(JNIEnv *env, jclass c, jstring jpath, jboolean local, jboolean now) { const char *path = (*env)->GetStringUTFChars(env, jpath, NULL); int flags = (local ? RTLD_LOCAL : RTLD_GLOBAL) | (now ? RTLD_NOW : RTLD_LAZY); void *handle = dlopen(path, flags); @@ -60,7 +60,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1dlopen(JNIEnv *env, } JNIEXPORT jlong JNICALL -Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1dlsym(JNIEnv *env, jclass c, jlong handle, jstring jsymbol) { +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1DLL_native_1dlsym(JNIEnv *env, jclass c, jlong handle, jstring jsymbol) { const char *symbol = (*env)->GetStringUTFChars(env, jsymbol, NULL); void *address = dlsym((void *)handle, symbol); create_dlerror_string(env); @@ -69,13 +69,13 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1dlsym(JNIEnv *env, j } JNIEXPORT jint JNICALL -Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1dlclose(JNIEnv *env, jclass c, jlong handle) { +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1DLL_native_1dlclose(JNIEnv *env, jclass c, jlong handle) { int rc = dlclose((void *)handle); return rc; } JNIEXPORT jobject JNICALL -Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1dlerror(JNIEnv *env, jclass c) { +Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1DLL_native_1dlerror(JNIEnv *env, jclass c) { return last_dlerror; } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java index 09557dc390..6ef837a033 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java @@ -164,7 +164,7 @@ public class DynLoadFunctions { @TruffleBoundary protected Object getSymbolInfo(String symbol, String packageName, boolean withReg) { DLL.RegisteredNativeSymbol rns = DLL.RegisteredNativeSymbol.any(); - long f = DLL.findSymbol(RRuntime.asString(symbol), packageName, rns); + DLL.SymbolHandle f = DLL.findSymbol(RRuntime.asString(symbol), packageName, rns); SymbolInfo symbolInfo = null; if (f != DLL.SYMBOL_NOT_FOUND) { symbolInfo = new SymbolInfo(rns.getDllInfo(), symbol, f); @@ -175,14 +175,14 @@ public class DynLoadFunctions { @Specialization(guards = "isDLLInfo(externalPtr)") @TruffleBoundary protected Object getSymbolInfo(RAbstractStringVector symbolVec, RExternalPtr externalPtr, boolean withReg) { - DLL.DLLInfo dllInfo = DLL.getDLLInfoForId((int) externalPtr.getAddr()); + DLL.DLLInfo dllInfo = DLL.getDLLInfoForId((int) externalPtr.getAddr().asAddress()); if (dllInfo == null) { throw RError.error(this, RError.Message.REQUIRES_NAME_DLLINFO); } DLL.RegisteredNativeSymbol rns = DLL.RegisteredNativeSymbol.any(); String symbol = symbolVec.getDataAt(0); - long f = DLL.dlsym(dllInfo, RRuntime.asString(symbol), rns); + DLL.SymbolHandle f = DLL.dlsym(dllInfo, RRuntime.asString(symbol), rns); SymbolInfo symbolInfo = null; if (f != DLL.SYMBOL_NOT_FOUND) { symbolInfo = new SymbolInfo(dllInfo, symbol, f); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java index 9c2419064f..ff6b649c54 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java @@ -285,7 +285,7 @@ public class HiddenInternalFunctions { @TruffleBoundary protected RList getRegisteredRoutines(RExternalPtr externalPtr) { Object[] data = new Object[NAMES.getLength()]; - DLL.DLLInfo dllInfo = DLL.getDLLInfoForId((int) externalPtr.getAddr()); + DLL.DLLInfo dllInfo = DLL.getDLLInfoForId((int) externalPtr.getAddr().asAddress()); RInternalError.guarantee(dllInfo != null); for (DLL.NativeSymbolType nst : DLL.NativeSymbolType.values()) { DLL.DotSymbol[] symbols = dllInfo.getNativeSymbols(nst); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/DotC.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/DotC.java index 60f28c4e3c..265141a16e 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/DotC.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/DotC.java @@ -42,6 +42,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.ffi.DLL; +import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; /** @@ -75,9 +76,9 @@ public abstract class DotC extends RBuiltinNode { @SuppressWarnings("unused") @Specialization protected RList c(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, byte naok, byte dup, Object rPackage, RMissing encoding) { - long address = getAddressFromSymbolInfo(frame, symbol); + SymbolHandle handle = getAddressFromSymbolInfo(frame, symbol); String name = getNameFromSymbolInfo(frame, symbol); - return dispatch(this, address, name, naok, dup, args); + return dispatch(this, handle, name, naok, dup, args); } @SuppressWarnings("unused") @@ -93,8 +94,8 @@ public abstract class DotC extends RBuiltinNode { } } DLL.RegisteredNativeSymbol rns = new DLL.RegisteredNativeSymbol(DLL.NativeSymbolType.C, null, null); - long func = DLL.findSymbol(f.getDataAt(0), libName, rns); - if (func == -1) { + DLL.SymbolHandle func = DLL.findSymbol(f.getDataAt(0), libName, rns); + if (func == DLL.SYMBOL_NOT_FOUND) { errorProfile.enter(); throw RError.error(this, RError.Message.C_SYMBOL_NOT_IN_TABLE, f); } @@ -109,7 +110,7 @@ public abstract class DotC extends RBuiltinNode { return RRuntime.asString(nameExtract.applyAccessField(frame, symbol, "name")); } - private long getAddressFromSymbolInfo(VirtualFrame frame, RList symbol) { + private SymbolHandle getAddressFromSymbolInfo(VirtualFrame frame, RList symbol) { if (addressExtract == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); addressExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); @@ -150,7 +151,7 @@ public abstract class DotC extends RBuiltinNode { } @TruffleBoundary - protected static RList dispatch(RBuiltinNode node, long address, String name, byte naok, byte dup, RArgsValuesAndNames args) { + protected static RList dispatch(RBuiltinNode node, SymbolHandle handle, String name, byte naok, byte dup, RArgsValuesAndNames args) { @SuppressWarnings("unused") boolean dupArgs = RRuntime.fromLogical(dup); @SuppressWarnings("unused") @@ -193,7 +194,7 @@ public abstract class DotC extends RBuiltinNode { if (FastROptions.TraceNativeCalls.getBooleanValue()) { trace(name, nativeArgs); } - RFFIFactory.getRFFI().getCRFFI().invoke(address, nativeArgs); + RFFIFactory.getRFFI().getCRFFI().invoke(handle, nativeArgs); // we have to assume that the native method updated everything RStringVector listNames = validateArgNames(array.length, args.getSignature()); Object[] results = new Object[array.length]; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java index f059e6c94b..00c87f59e8 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ForeignFunctions.java @@ -96,6 +96,7 @@ import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.ffi.DLL; +import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; /** @@ -194,7 +195,7 @@ public class ForeignFunctions { return RRuntime.asString(nameExtract.applyAccessField(frame, symbol, "name")); } - protected long getAddressFromSymbolInfo(VirtualFrame frame, RList symbol) { + protected SymbolHandle getAddressFromSymbolInfo(VirtualFrame frame, RList symbol) { if (addressExtract == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); addressExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); @@ -263,7 +264,7 @@ public class ForeignFunctions { @Cached("create()") BranchProfile errorProfile) { String libName = checkPackageArg(rPackage, errorProfile); DLL.RegisteredNativeSymbol rns = new DLL.RegisteredNativeSymbol(DLL.NativeSymbolType.Fortran, null, null); - long func = DLL.findSymbol(f.getDataAt(0), libName, rns); + DLL.SymbolHandle func = DLL.findSymbol(f.getDataAt(0), libName, rns); if (func == DLL.SYMBOL_NOT_FOUND) { errorProfile.enter(); throw RError.error(this, RError.Message.C_SYMBOL_NOT_IN_TABLE, f); @@ -553,7 +554,7 @@ public class ForeignFunctions { @Specialization protected Object callNamedFunctionWithPackage(String name, RArgsValuesAndNames args, String packageName) { DLL.RegisteredNativeSymbol rns = new DLL.RegisteredNativeSymbol(DLL.NativeSymbolType.Call, null, null); - long func = DLL.findSymbol(name, packageName, rns); + DLL.SymbolHandle func = DLL.findSymbol(name, packageName, rns); if (func == DLL.SYMBOL_NOT_FOUND) { errorProfile.enter(); throw RError.error(this, RError.Message.C_SYMBOL_NOT_IN_TABLE, name); @@ -640,7 +641,7 @@ public class ForeignFunctions { @Specialization protected Object callNamedFunctionWithPackage(String name, RArgsValuesAndNames args, String packageName) { DLL.RegisteredNativeSymbol rns = new DLL.RegisteredNativeSymbol(DLL.NativeSymbolType.External, null, null); - long func = DLL.findSymbol(name, packageName, rns); + DLL.SymbolHandle func = DLL.findSymbol(name, packageName, rns); if (func == DLL.SYMBOL_NOT_FOUND) { errorProfile.enter(); throw RError.error(this, RError.Message.C_SYMBOL_NOT_IN_TABLE, name); @@ -713,7 +714,7 @@ public class ForeignFunctions { @Specialization protected Object callNamedFunctionWithPackage(String name, RArgsValuesAndNames args, String packageName) { DLL.RegisteredNativeSymbol rns = new DLL.RegisteredNativeSymbol(DLL.NativeSymbolType.External, null, null); - long func = DLL.findSymbol(name, packageName, rns); + DLL.SymbolHandle func = DLL.findSymbol(name, packageName, rns); if (func == DLL.SYMBOL_NOT_FOUND) { errorProfile.enter(); throw RError.error(this, RError.Message.C_SYMBOL_NOT_IN_TABLE, name); @@ -771,7 +772,7 @@ public class ForeignFunctions { @Specialization protected Object callNamedFunctionWithPackage(String name, RArgsValuesAndNames args, String packageName) { DLL.RegisteredNativeSymbol rns = new DLL.RegisteredNativeSymbol(DLL.NativeSymbolType.External, null, null); - long func = DLL.findSymbol(name, packageName, rns); + DLL.SymbolHandle func = DLL.findSymbol(name, packageName, rns); if (func == DLL.SYMBOL_NOT_FOUND) { errorProfile.enter(); throw RError.error(this, RError.Message.C_SYMBOL_NOT_IN_TABLE, name); @@ -827,7 +828,7 @@ public class ForeignFunctions { @TruffleBoundary protected Object callNamedFunctionWithPackage(String name, RArgsValuesAndNames args, String packageName) { DLL.RegisteredNativeSymbol rns = new DLL.RegisteredNativeSymbol(DLL.NativeSymbolType.Call, null, null); - long func = DLL.findSymbol(name, packageName, rns); + DLL.SymbolHandle func = DLL.findSymbol(name, packageName, rns); if (func == DLL.SYMBOL_NOT_FOUND) { errorProfile.enter(); throw RError.error(this, RError.Message.C_SYMBOL_NOT_IN_TABLE, name); diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Grid.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Grid.java index a5fdc39ac4..5abe50b8ca 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Grid.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Grid.java @@ -28,12 +28,13 @@ import com.oracle.truffle.r.runtime.ffi.DLL; import com.oracle.truffle.r.runtime.ffi.GridRFFI; import com.oracle.truffle.r.runtime.ffi.LibPaths; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; +import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; public class Generic_Grid implements GridRFFI { private static final class GridProvider { private static GridProvider grid; - private static long initGrid; - private static long killGrid; + private static DLL.SymbolHandle initGrid; + private static DLL.SymbolHandle killGrid; @TruffleBoundary private GridProvider() { @@ -52,24 +53,24 @@ public class Generic_Grid implements GridRFFI { @SuppressWarnings("static-method") long getInitGrid() { - return initGrid; + return initGrid.asAddress(); } @SuppressWarnings("static-method") long getKillGrid() { - return killGrid; + return killGrid.asAddress(); } } @Override public Object initGrid(REnvironment gridEvalEnv) { long initGrid = GridProvider.gridProvider().getInitGrid(); - return RFFIFactory.getRFFI().getCallRFFI().invokeCall(initGrid, "L_initGrid", new Object[]{gridEvalEnv}); + return RFFIFactory.getRFFI().getCallRFFI().invokeCall(new SymbolHandle(initGrid), "L_initGrid", new Object[]{gridEvalEnv}); } @Override public Object killGrid() { long killGrid = GridProvider.gridProvider().getKillGrid(); - return RFFIFactory.getRFFI().getCallRFFI().invokeCall(killGrid, "L_killGrid", new Object[0]); + return RFFIFactory.getRFFI().getCallRFFI().invokeCall(new SymbolHandle(killGrid), "L_killGrid", new Object[0]); } } diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Tools.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Tools.java index d8504e0c04..a97616f45f 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Tools.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Tools.java @@ -31,6 +31,7 @@ import com.oracle.truffle.r.runtime.data.RLogicalVector; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.ffi.DLL; +import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; import com.oracle.truffle.r.runtime.ffi.LibPaths; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; import com.oracle.truffle.r.runtime.ffi.ToolsRFFI; @@ -39,7 +40,7 @@ public class Generic_Tools implements ToolsRFFI { private static final class ToolsProvider { private static final String C_PARSE_RD = "C_parseRd"; private static ToolsProvider tools; - private static long parseRd; + private static DLL.SymbolHandle parseRd; @TruffleBoundary private ToolsProvider() { @@ -57,7 +58,7 @@ public class Generic_Tools implements ToolsRFFI { @SuppressWarnings("static-method") long getParseRd() { - return parseRd; + return parseRd.asAddress(); } } @@ -70,7 +71,8 @@ public class Generic_Tools implements ToolsRFFI { try { parseRdCritical.acquire(); long parseRd = ToolsProvider.toolsProvider().getParseRd(); - return RFFIFactory.getRFFI().getCallRFFI().invokeCall(parseRd, ToolsProvider.C_PARSE_RD, new Object[]{con, srcfile, verbose, fragment, basename, warningCalls, macros, warndups}); + return RFFIFactory.getRFFI().getCallRFFI().invokeCall(new SymbolHandle(parseRd), ToolsProvider.C_PARSE_RD, + new Object[]{con, srcfile, verbose, fragment, basename, warningCalls, macros, warndups}); } catch (Throwable ex) { throw RInternalError.shouldNotReachHere(ex, "error during Rd parsing"); } finally { diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_C.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_C.java index 160d050b37..174ad3844f 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_C.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_C.java @@ -24,6 +24,7 @@ package com.oracle.truffle.r.runtime.ffi.jni; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.ffi.CRFFI; +import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; public class JNI_C implements CRFFI { @@ -35,8 +36,8 @@ public class JNI_C implements CRFFI { */ @Override @TruffleBoundary - public synchronized void invoke(long address, Object[] args) { - c(address, args); + public synchronized void invoke(SymbolHandle symbolHandle, Object[] args) { + c(symbolHandle.asAddress(), args); } private static native void c(long address, Object[] args); diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java index 3d3fb55004..16aabaea92 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java @@ -28,10 +28,11 @@ import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceEnabled; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.RInternalError; -import com.oracle.truffle.r.runtime.ffi.BaseRFFI; import com.oracle.truffle.r.runtime.ffi.CallRFFI; import com.oracle.truffle.r.runtime.ffi.DLL; import com.oracle.truffle.r.runtime.ffi.DLL.DLLException; +import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; +import com.oracle.truffle.r.runtime.ffi.DLLRFFI; import com.oracle.truffle.r.runtime.ffi.LibPaths; import com.oracle.truffle.r.runtime.ffi.RFFIUtils; import com.oracle.truffle.r.runtime.ffi.RFFIVariables; @@ -46,7 +47,7 @@ import com.oracle.truffle.r.runtime.ffi.RFFIVariables; */ public class JNI_Call implements CallRFFI { - JNI_Call() { + protected JNI_Call() { loadLibrary(); } @@ -60,7 +61,7 @@ public class JNI_Call implements CallRFFI { * so we have to do an additional {@code System.load} to achieve that. * * Before we do that we must load {@code libjniboot} because the implementation of - * {@link BaseRFFI#dlopen} is called by {@link DLL#load} which uses JNI! + * {@link DLLRFFI#dlopen} is called by {@link DLL#load} which uses JNI! */ @TruffleBoundary private static void loadLibrary() { @@ -90,7 +91,8 @@ public class JNI_Call implements CallRFFI { @Override @TruffleBoundary - public synchronized Object invokeCall(long address, String name, Object[] args) { + public synchronized Object invokeCall(SymbolHandle handleArg, String name, Object[] args) { + long address = handleArg.asAddress(); Object result = null; if (traceEnabled()) { traceDownCall(name, args); @@ -150,10 +152,11 @@ public class JNI_Call implements CallRFFI { @Override @TruffleBoundary - public synchronized void invokeVoidCall(long address, String name, Object[] args) { + public synchronized void invokeVoidCall(SymbolHandle handle, String name, Object[] args) { if (traceEnabled()) { traceDownCall(name, args); } + long address = handle.asAddress(); try { switch (args.length) { case 0: diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_DLL.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_DLL.java new file mode 100644 index 0000000000..236b81e004 --- /dev/null +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_DLL.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014, 2016, 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.jni; + +import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; +import com.oracle.truffle.r.runtime.ffi.DLLRFFI; + +public class JNI_DLL implements DLLRFFI { + + @Override + public Object dlopen(String path, boolean local, boolean now) { + long handle = native_dlopen(path, local, now); + if (handle == 0) { + return null; + } else { + return new Long(handle); + } + } + + @Override + public SymbolHandle dlsym(Object handle, String symbol) { + long nativeHandle = (Long) handle; + long symv = native_dlsym(nativeHandle, symbol); + if (symv == 0) { + // symbol might actually be zero + if (dlerror() != null) { + return null; + } + } + return new SymbolHandle(symv); + } + + @Override + public int dlclose(Object handle) { + long nativeHandle = (Long) handle; + return native_dlclose(nativeHandle); + } + + @Override + public String dlerror() { + return native_dlerror(); + } + + // Checkstyle: stop method name check + + private static native long native_dlopen(String path, boolean local, boolean now); + + private static native int native_dlclose(long handle); + + private static native String native_dlerror(); + + private static native long native_dlsym(long handle, String symbol); + +} diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PkgInit.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PkgInit.java index a93b6008d6..d5c2450edf 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PkgInit.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PkgInit.java @@ -26,6 +26,7 @@ import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.ffi.DLL; import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo; import com.oracle.truffle.r.runtime.ffi.DLL.DotSymbol; +import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; /** * The JNI-based implementation of the package init code. This is only up-called from JNI. @@ -55,7 +56,7 @@ final class JNI_PkgInit { * Upcall from native to create a {@link DotSymbol} value. */ private static DotSymbol setDotSymbolValues(String name, long fun, int numArgs) { - return new DotSymbol(name, fun, numArgs); + return new DotSymbol(name, new SymbolHandle(fun), numArgs); } private static native DotSymbol setSymbol(int nstOrd, long routines, int index); diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RFFIFactory.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RFFIFactory.java index af726e7ecd..546352c06e 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RFFIFactory.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RFFIFactory.java @@ -29,6 +29,7 @@ import com.oracle.truffle.r.runtime.context.RContext.ContextState; import com.oracle.truffle.r.runtime.ffi.BaseRFFI; import com.oracle.truffle.r.runtime.ffi.CRFFI; import com.oracle.truffle.r.runtime.ffi.CallRFFI; +import com.oracle.truffle.r.runtime.ffi.DLLRFFI; import com.oracle.truffle.r.runtime.ffi.GridRFFI; import com.oracle.truffle.r.runtime.ffi.LapackRFFI; import com.oracle.truffle.r.runtime.ffi.MiscRFFI; @@ -195,6 +196,16 @@ public class JNI_RFFIFactory extends RFFIFactory implements RFFI { return pcreRFFI; } + private DLLRFFI dllRFFI; + + @Override + public DLLRFFI getDLLRFFI() { + if (dllRFFI == null) { + dllRFFI = new JNI_DLL(); + } + return dllRFFI; + } + private REmbedRFFI rEmbedRFFI; @Override diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Stats.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Stats.java index 460515618e..1f0564d90b 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Stats.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Stats.java @@ -26,6 +26,7 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.ffi.DLL; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo; +import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; import com.oracle.truffle.r.runtime.ffi.StatsRFFI; // Checkstyle: stop method name @@ -33,31 +34,31 @@ public class JNI_Stats implements StatsRFFI { @Override @TruffleBoundary public void fft_factor(int n, int[] pmaxf, int[] pmaxp) { - native_fft_factor(fft_factor_address(), n, pmaxf, pmaxp); + native_fft_factor(fft_factor_address().asAddress(), n, pmaxf, pmaxp); } @Override @TruffleBoundary public int fft_work(double[] a, int nseg, int n, int nspn, int isn, double[] work, int[] iwork) { - return native_fft_work(fft_work_address(), a, nseg, n, nspn, isn, work, iwork); + return native_fft_work(fft_work_address().asAddress(), a, nseg, n, nspn, isn, work, iwork); } - private long fft_factor_address; - private long fft_work_address; + private SymbolHandle fft_factor_address; + private SymbolHandle fft_work_address; - private long fft_factor_address() { - if (fft_factor_address == 0) { + private SymbolHandle fft_factor_address() { + if (fft_factor_address == null) { DLLInfo dllInfo = DLL.findLibrary("stats"); - fft_factor_address = RFFIFactory.getRFFI().getBaseRFFI().dlsym(dllInfo.handle, "fft_factor"); + fft_factor_address = RFFIFactory.getRFFI().getDLLRFFI().dlsym(dllInfo.handle, "fft_factor"); assert fft_factor_address != DLL.SYMBOL_NOT_FOUND; } return fft_factor_address; } - private long fft_work_address() { - if (fft_work_address == 0) { + private SymbolHandle fft_work_address() { + if (fft_work_address == null) { DLLInfo dllInfo = DLL.findLibrary("stats"); - fft_work_address = RFFIFactory.getRFFI().getBaseRFFI().dlsym(dllInfo.handle, "fft_work"); + fft_work_address = RFFIFactory.getRFFI().getDLLRFFI().dlsym(dllInfo.handle, "fft_work"); assert fft_work_address != DLL.SYMBOL_NOT_FOUND; } return fft_work_address; diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_UserRng.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_UserRng.java index bc935d7b32..1387cb869a 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_UserRng.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_UserRng.java @@ -30,26 +30,26 @@ public class JNI_UserRng implements UserRngRFFI { @Override @TruffleBoundary public void init(int seed) { - init(Function.Init.getAddress(), seed); + init(Function.Init.getSymbolHandle().asAddress(), seed); } @Override @TruffleBoundary public double rand() { - return rand(Function.Rand.getAddress()); + return rand(Function.Rand.getSymbolHandle().asAddress()); } @Override @TruffleBoundary public int nSeed() { - return nSeed(Function.NSeed.getAddress()); + return nSeed(Function.NSeed.getSymbolHandle().asAddress()); } @Override @TruffleBoundary public void seeds(int[] n) { - seeds(Function.Seedloc.getAddress(), n); + seeds(Function.Seedloc.getSymbolHandle().asAddress(), n); } private static native void init(long address, int seed); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java index 0eb828df88..d7339d4988 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java @@ -681,7 +681,7 @@ public class RDeparse { } append(')'); } else if (value instanceof RExternalPtr) { - append("<pointer: 0x").append(Long.toHexString(((RExternalPtr) value).getAddr())).append('>'); + append("<pointer: 0x").append(Long.toHexString(((RExternalPtr) value).getAddr().asAddress())).append('>'); } else if (value instanceof REnvironment) { append("<environment>"); } else if (value instanceof TruffleObject) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java index 5d7fa9e540..544a6136ab 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java @@ -76,6 +76,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; +import com.oracle.truffle.r.runtime.ffi.DLL; import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; import com.oracle.truffle.r.runtime.nodes.RCodeBuilder; import com.oracle.truffle.r.runtime.nodes.RSyntaxCall; @@ -787,7 +788,7 @@ public class RSerialize { Object prot = readItem(); long addr = 0; Object tag = readItem(); - result = RDataFactory.createExternalPtr(addr, tag, prot); + result = RDataFactory.createExternalPtr(new DLL.SymbolHandle(addr), tag, prot); addReadRef(result); break; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java index 8717d9a2d7..8bb9e8e877 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java @@ -54,7 +54,7 @@ public abstract class RConnection implements AutoCloseable { RStringVector classVector = RDataFactory.createStringVector(classes, RDataFactory.COMPLETE_VECTOR); // it's important to put "this" into the externalptr, so that it doesn't get collected - RExternalPtr connectionId = RDataFactory.createExternalPtr(0, this, RDataFactory.createSymbol("connection"), RNull.instance); + RExternalPtr connectionId = RDataFactory.createExternalPtr(null, this, RDataFactory.createSymbol("connection"), RNull.instance); result.initAttributes(RAttributes.createInitialized(new String[]{RRuntime.CLASS_ATTR_KEY, "conn_id"}, new Object[]{classVector, connectionId})); return result; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java index 3ecd606d1a..a510e07cfe 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java @@ -43,6 +43,7 @@ import com.oracle.truffle.r.runtime.data.RPromise.Closure; import com.oracle.truffle.r.runtime.data.RPromise.EagerFeedback; import com.oracle.truffle.r.runtime.data.RPromise.PromiseState; import com.oracle.truffle.r.runtime.env.REnvironment; +import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; import com.oracle.truffle.r.runtime.nodes.RBaseNode; @@ -495,19 +496,19 @@ public final class RDataFactory { return traceDataCreated(new RS4Object()); } - public static RExternalPtr createExternalPtr(long value, Object externalObject, Object tag, Object prot) { + public static RExternalPtr createExternalPtr(SymbolHandle value, Object externalObject, Object tag, Object prot) { assert tag != null : "null tag, use RNull.instance instead"; assert prot != null : "null prot, use RNull.instance instead"; return traceDataCreated(new RExternalPtr(value, externalObject, tag, prot)); } - public static RExternalPtr createExternalPtr(long value, Object tag, Object prot) { + public static RExternalPtr createExternalPtr(SymbolHandle value, Object tag, Object prot) { assert tag != null : "null tag, use RNull.instance instead"; assert prot != null : "null prot, use RNull.instance instead"; return traceDataCreated(new RExternalPtr(value, null, tag, prot)); } - public static RExternalPtr createExternalPtr(long value, Object tag) { + public static RExternalPtr createExternalPtr(SymbolHandle value, Object tag) { assert tag != null : "null tag, use RNull.instance instead"; return traceDataCreated(new RExternalPtr(value, null, tag, RNull.instance)); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExternalPtr.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExternalPtr.java index 1d4124eaab..2932ecbe2b 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExternalPtr.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExternalPtr.java @@ -23,29 +23,30 @@ package com.oracle.truffle.r.runtime.data; import com.oracle.truffle.r.runtime.RType; +import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; /** * The rarely seen {@code externalptr} type. */ -public class RExternalPtr extends RAttributeStorage { - private long addr; +public class RExternalPtr extends RAttributeStorage implements RTypedValue { + private SymbolHandle handle; private Object tag; private Object prot; private Object externalObject; - RExternalPtr(long addr, Object externalObject, Object tag, Object prot) { - this.addr = addr; + RExternalPtr(SymbolHandle handle, Object externalObject, Object tag, Object prot) { + this.handle = handle; this.externalObject = externalObject; this.tag = tag; this.prot = prot; } public RExternalPtr copy() { - return RDataFactory.createExternalPtr(addr, externalObject, tag, prot); + return RDataFactory.createExternalPtr(handle, externalObject, tag, prot); } - public long getAddr() { - return addr; + public SymbolHandle getAddr() { + return handle; } public Object getExternalObject() { @@ -60,8 +61,8 @@ public class RExternalPtr extends RAttributeStorage { return prot; } - public void setAddr(long value) { - this.addr = value; + public void setAddr(SymbolHandle value) { + this.handle = value; } public void setExternalObject(Object externalObject) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CRFFI.java index 2ccb32e90b..a1b7d4fc55 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CRFFI.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CRFFI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, 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 @@ -22,6 +22,8 @@ */ package com.oracle.truffle.r.runtime.ffi; +import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; + /** * Support for the {.C} and {.Fortran} calls. */ @@ -31,8 +33,8 @@ public interface CRFFI { * {@code args}. The values in {@code args} should be native types,e.g., {@code double[]} not * {@code RDoubleVector}. * - * @param address the target address of the native method + * @param handle of the native method * @param args native arguments */ - void invoke(long address, Object[] args); + void invoke(SymbolHandle handle, Object[] args); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CallRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CallRFFI.java index 76c8f10cd0..6baeebaae6 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CallRFFI.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CallRFFI.java @@ -22,6 +22,8 @@ */ package com.oracle.truffle.r.runtime.ffi; +import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; + /** * Support for the {.Call} and {.External} calls. */ @@ -31,16 +33,16 @@ public interface CallRFFI { * {@code args}. The values in {@code args} can be any of the types used to represent {@code R} * values in the implementation. * - * @param address the address of the native function + * @param handle the address of the native function * @param name the name of the native function * @param args arguments */ - Object invokeCall(long address, String name, Object[] args); + Object invokeCall(SymbolHandle handle, String name, Object[] args); /** * Variant that does not return a result (primarily for library "init" methods). */ - void invokeVoidCall(long address, String name, Object[] args); + void invokeVoidCall(SymbolHandle handle, String name, Object[] args); /** * This interface is instantiated very early and sets the FFI global variables as part of that diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java index 28b50af8c8..5b3af3bb9d 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java @@ -19,8 +19,10 @@ import java.util.concurrent.atomic.AtomicInteger; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RError.RErrorException; +import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.ReturnException; import com.oracle.truffle.r.runtime.Utils; @@ -30,6 +32,7 @@ import com.oracle.truffle.r.runtime.data.RExternalPtr; import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RSymbol; +import com.oracle.truffle.r.runtime.data.RTruffleObject; /** * Support for Dynamically Loaded Libraries. @@ -52,8 +55,6 @@ import com.oracle.truffle.r.runtime.data.RSymbol; */ public class DLL { - public static final long SYMBOL_NOT_FOUND = -1; - /** * The list of loaded DLLs. */ @@ -64,6 +65,14 @@ public class DLL { */ private static final AtomicInteger ID = new AtomicInteger(); + public static Deque<DLLInfo> getList() { + return list; + } + + public static void addDLL(DLLInfo dllInfo) { + list.add(dllInfo); + } + public enum NativeSymbolType { C, Call, @@ -77,16 +86,17 @@ public class DLL { * Denotes info in registered native routines. GnuR has "subclasses" for C/Fortran, which is TBD * for FastR. */ - public static class DotSymbol { + public static class DotSymbol implements RTruffleObject { public final String name; - public final long fun; + public final SymbolHandle fun; public final int numArgs; - public DotSymbol(String name, long fun, int numArgs) { + public DotSymbol(String name, SymbolHandle fun, int numArgs) { this.name = name; this.fun = fun; this.numArgs = numArgs; } + } public static class RegisteredNativeSymbol { @@ -110,7 +120,7 @@ public class DLL { } - public static final class DLLInfo { + public static final class DLLInfo implements RTruffleObject { private static final RStringVector NAMES = RDataFactory.createStringVector(new String[]{"name", "path", "dynamicLookup", "handle", "info"}, RDataFactory.COMPLETE_VECTOR); public static final String DLL_INFO_REFERENCE = "DLLInfoReference"; private static final RStringVector INFO_REFERENCE_CLASS = RDataFactory.createStringVectorFromScalar(DLL_INFO_REFERENCE); @@ -178,13 +188,13 @@ public class DLL { data[0] = name; data[1] = path; data[2] = RRuntime.asLogical(dynamicLookup); - data[3] = createExternalPtr(System.identityHashCode(handle), HANDLE_CLASS); + data[3] = createExternalPtr(new SymbolHandle(new Long(System.identityHashCode(handle))), HANDLE_CLASS); /* * GnuR sets the info member to an externalptr whose value is the DllInfo structure * itself. We can't do that, but we need a way to get back to it from R code that uses * the value, e.g. getRegisteredRoutines. So we use the id value. */ - data[4] = createExternalPtr(id, INFO_REFERENCE_CLASS); + data[4] = createExternalPtr(new SymbolHandle(new Long(id)), INFO_REFERENCE_CLASS); RList dllInfo = RDataFactory.createList(data, DLLInfo.NAMES); dllInfo.setClassAttr(RDataFactory.createStringVectorFromScalar(DLLINFO_CLASS)); return dllInfo; @@ -194,14 +204,15 @@ public class DLL { public String toString() { return String.format("name: %s, path: %s, dynamicLookup: %b, forceSymbols %b", name, path, dynamicLookup, forceSymbols); } + } public static class SymbolInfo { public final DLLInfo libInfo; public final String symbol; - public final long address; + public final SymbolHandle address; - public SymbolInfo(DLLInfo libInfo, String symbol, long address) { + public SymbolInfo(DLLInfo libInfo, String symbol, SymbolHandle address) { this.libInfo = libInfo; this.symbol = symbol; this.address = address; @@ -245,6 +256,37 @@ public class DLL { } } + /** + * Abstracts the way that DLL function symbols are represented, either as a machine address ( + * {@link Long}) or a {@link TruffleObject}. + */ + public static class SymbolHandle { + public final Object value; + + public SymbolHandle(Object value) { + assert value instanceof Long || value instanceof TruffleObject; + this.value = value; + } + + public long asAddress() { + if (value instanceof Long) { + return (Long) value; + } else { + throw RInternalError.shouldNotReachHere(); + } + } + + public TruffleObject asTruffleObject() { + if (value instanceof TruffleObject) { + return (TruffleObject) value; + } else { + throw RInternalError.shouldNotReachHere(); + } + } + } + + public static final SymbolHandle SYMBOL_NOT_FOUND = null; + public static synchronized DLLInfo getDLLInfoForId(int id) { for (DLLInfo dllInfo : list) { if (dllInfo.id == id) { @@ -259,7 +301,7 @@ public class DLL { return tag.getName().equals(DLLInfo.DLL_INFO_REFERENCE); } - public static RExternalPtr createExternalPtr(long value, RStringVector rClass) { + public static RExternalPtr createExternalPtr(SymbolHandle value, RStringVector rClass) { CompilerAsserts.neverPartOfCompilation(); // for interning RExternalPtr result = RDataFactory.createExternalPtr(value, RDataFactory.createSymbolInterned(rClass.getDataAt(0))); result.setClassAttr(rClass); @@ -269,7 +311,7 @@ public class DLL { public static class DLLException extends RErrorException { private static final long serialVersionUID = 1L; - DLLException(RError.Message msg, Object... args) { + public DLLException(RError.Message msg, Object... args) { super(msg, args); } } @@ -292,9 +334,9 @@ public class DLL { } } File file = new File(absPath); - Object handle = RFFIFactory.getRFFI().getBaseRFFI().dlopen(absPath, local, now); + Object handle = RFFIFactory.getRFFI().getDLLRFFI().dlopen(path, local, now); if (handle == null) { - String dlError = RFFIFactory.getRFFI().getBaseRFFI().dlerror(); + String dlError = RFFIFactory.getRFFI().getDLLRFFI().dlerror(); if (RContext.isInitialContextInitialized()) { throw new DLLException(RError.Message.DLL_LOAD_ERROR, path, dlError); } else { @@ -316,8 +358,8 @@ public class DLL { DLLInfo dllInfo = load(path, local, now); // Search for init method String pkgInit = R_INIT_PREFIX + dllInfo.name; - long initFunc = RFFIFactory.getRFFI().getBaseRFFI().dlsym(dllInfo.handle, pkgInit); - if (initFunc != 0) { + SymbolHandle initFunc = RFFIFactory.getRFFI().getDLLRFFI().dlsym(dllInfo.handle, pkgInit); + if (initFunc != SYMBOL_NOT_FOUND) { synchronized (DLL.class) { try { RFFIFactory.getRFFI().getCallRFFI().invokeVoidCall(initFunc, pkgInit, new Object[]{dllInfo}); @@ -342,7 +384,7 @@ public class DLL { String absPath = Utils.tildeExpand(path); for (DLLInfo info : list) { if (info.path.equals(absPath)) { - int rc = RFFIFactory.getRFFI().getBaseRFFI().dlclose(info.handle); + int rc = RFFIFactory.getRFFI().getDLLRFFI().dlclose(info.handle); if (rc != 0) { throw new DLLException(RError.Message.DLL_LOAD_ERROR, path, ""); } @@ -369,7 +411,7 @@ public class DLL { * @param rns if not {@code null} may limit the search to a specific {@link NativeSymbolType} * @return the address of the (function) symbol or {@code 0} if not found. */ - public static long getDLLRegisteredSymbol(DLLInfo dllInfo, String name, RegisteredNativeSymbol rns) { + public static SymbolHandle getDLLRegisteredSymbol(DLLInfo dllInfo, String name, RegisteredNativeSymbol rns) { NativeSymbolType rnsNst = rns == null ? NativeSymbolType.Any : rns.nst; for (NativeSymbolType nst : NativeSymbolType.values()) { if (rnsNst == NativeSymbolType.Any || rnsNst == nst) { @@ -398,9 +440,9 @@ public class DLL { * disabled, looks up the symbol using the {@code dlopen} machinery. */ @TruffleBoundary - public static long dlsym(DLLInfo dllInfo, String name, RegisteredNativeSymbol rns) { - long f = getDLLRegisteredSymbol(dllInfo, name, rns); - if (f != -1) { + public static SymbolHandle dlsym(DLLInfo dllInfo, String name, RegisteredNativeSymbol rns) { + SymbolHandle f = getDLLRegisteredSymbol(dllInfo, name, rns); + if (f != SYMBOL_NOT_FOUND) { return f; } @@ -413,16 +455,11 @@ public class DLL { if (rns != null && rns.nst == NativeSymbolType.Fortran) { mName = name + "_"; } - f = RFFIFactory.getRFFI().getBaseRFFI().dlsym(dllInfo.handle, mName); - if (f != 0) { - return f; + SymbolHandle symValue = RFFIFactory.getRFFI().getDLLRFFI().dlsym(dllInfo.handle, mName); + if (symValue != null) { + return symValue; } else { - // symbol might actually be zero - if (RFFIFactory.getRFFI().getBaseRFFI().dlerror() == null) { - return f; - } else { - return SYMBOL_NOT_FOUND; - } + return SYMBOL_NOT_FOUND; } } @@ -435,14 +472,14 @@ public class DLL { * {@code null}) */ @TruffleBoundary - public static synchronized long findSymbol(String name, String libName, RegisteredNativeSymbol rns) { + public static synchronized SymbolHandle findSymbol(String name, String libName, RegisteredNativeSymbol rns) { boolean all = libName == null || libName.length() == 0; for (DLLInfo dllInfo : list) { if (dllInfo.forceSymbols) { continue; } if (all || dllInfo.name.equals(libName)) { - long func = dlsym(dllInfo, name, rns); + SymbolHandle func = dlsym(dllInfo, name, rns); if (func != SYMBOL_NOT_FOUND) { if (rns != null) { rns.dllInfo = dllInfo; @@ -469,7 +506,7 @@ public class DLL { @TruffleBoundary public static DLLInfo findLibraryContainingSymbol(String symbol) { RegisteredNativeSymbol rns = RegisteredNativeSymbol.any(); - long func = findSymbol(symbol, null, rns); + SymbolHandle func = findSymbol(symbol, null, rns); if (func == SYMBOL_NOT_FOUND) { return null; } else { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLLRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLLRFFI.java new file mode 100644 index 0000000000..3659d2f7e2 --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLLRFFI.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2014, 2016, 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 com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; + +public interface DLLRFFI { + /** + * Open a DLL. + * + * @return {@code null} on error, opaque handle for following calls otherwise. + */ + Object dlopen(String path, boolean local, boolean now); + + /** + * Search for {@code symbol} in DLL specified by {@code handle}. To accommodate differing + * implementations of this interface the result is {@link SymbolHandle}. For the standard OS + * implementation this will encapsulate a {@link Long} or {@code null} if an error occurred. + * + */ + SymbolHandle dlsym(Object handle, String symbol); + + /** + * Close DLL specified by {@code handle}. + */ + int dlclose(Object handle); + + /** + * Get any error message. + * + * @return {@code null} if no error, message otherwise. + */ + String dlerror(); + +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFI.java index a88e98267e..99378fa1af 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFI.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFI.java @@ -39,6 +39,7 @@ package com.oracle.truffle.r.runtime.ffi; * <li>{@link UserRngRFFI}: specific interface to user-supplied random number generator.</li> * <li>{@link PCRERFFI}: interface to PCRE library (Perl regexp).</li> * <li>{@link ZipRFFI}: interface to zip compression</li> + * <li>{@link DLLRFFI}: interface to dll functions, e.g., {@code dlopen}</li> * <li>{@link REmbedRFFI}: interface to embedded support</li> * <li>{@link MiscRFFI}: interface to miscellaneous native functions</li> * </ul> @@ -69,6 +70,8 @@ public interface RFFI { ZipRFFI getZipRFFI(); + DLLRFFI getDLLRFFI(); + REmbedRFFI getREmbedRFFI(); MiscRFFI getMiscRFFI(); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/user/UserRNG.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/user/UserRNG.java index 9e1f745d76..994950b30f 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/user/UserRNG.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/user/UserRNG.java @@ -43,7 +43,7 @@ public final class UserRNG extends RNGInitAdapter { NSeed(OPTIONAL), Seedloc(OPTIONAL); - private long address; + private DLL.SymbolHandle symbolHandle; private final String symbol; private final boolean optional; @@ -53,15 +53,15 @@ public final class UserRNG extends RNGInitAdapter { } private boolean isDefined() { - return address != 0; + return symbolHandle != null; } - public long getAddress() { - return address; + public DLL.SymbolHandle getSymbolHandle() { + return symbolHandle; } - private void setAddress(DLLInfo dllInfo) { - this.address = findSymbol(symbol, dllInfo, optional); + private void setSymbolHandle(DLLInfo dllInfo) { + this.symbolHandle = findSymbol(symbol, dllInfo, optional); } } @@ -77,7 +77,7 @@ public final class UserRNG extends RNGInitAdapter { throw RError.error(RError.NO_CALLER, RError.Message.RNG_SYMBOL, Function.Rand.symbol); } for (Function f : Function.values()) { - f.setAddress(dllInfo); + f.setSymbolHandle(dllInfo); } userRngRFFI = RFFIFactory.getRFFI().getUserRngRFFI(); if (Function.Init.isDefined()) { @@ -100,13 +100,13 @@ public final class UserRNG extends RNGInitAdapter { } } - private static long findSymbol(String symbol, DLLInfo dllInfo, boolean optional) { - long func = DLL.findSymbol(symbol, dllInfo.name, DLL.RegisteredNativeSymbol.any()); + private static DLL.SymbolHandle findSymbol(String symbol, DLLInfo dllInfo, boolean optional) { + DLL.SymbolHandle func = DLL.findSymbol(symbol, dllInfo.name, DLL.RegisteredNativeSymbol.any()); if (func == DLL.SYMBOL_NOT_FOUND) { if (!optional) { throw RError.error(RError.NO_CALLER, RError.Message.RNG_SYMBOL, symbol); } else { - return 0; + return null; } } else { return func; -- GitLab