From ef762bd69205d383b8908dcc41f302bfc2868d17 Mon Sep 17 00:00:00 2001 From: Mick Jordan <mick.jordan@oracle.com> Date: Wed, 30 Nov 2016 15:01:53 -0800 Subject: [PATCH] forward dll info to CallRFFI/CRFFI --- .../truffle/r/library/graphics/RGraphics.java | 2 +- .../nodes/builtin/base/DynLoadFunctions.java | 2 +- .../builtin/base/HiddenInternalFunctions.java | 3 +- .../r/nodes/builtin/base/foreign/DotC.java | 24 +++++++++-- .../base/foreign/ForeignFunctions.java | 40 +++++++++++++------ .../r/runtime/ffi/generic/Generic_Grid.java | 4 +- .../r/runtime/ffi/generic/Generic_Tools.java | 2 +- .../truffle/r/runtime/ffi/jni/JNI_C.java | 3 +- .../truffle/r/runtime/ffi/jni/JNI_Call.java | 5 ++- .../truffle/r/runtime/data/RExternalPtr.java | 12 +++++- .../oracle/truffle/r/runtime/ffi/CRFFI.java | 4 +- .../truffle/r/runtime/ffi/CallRFFI.java | 7 +++- .../com/oracle/truffle/r/runtime/ffi/DLL.java | 38 +++++++----------- 13 files changed, 94 insertions(+), 52 deletions(-) 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 c87b109962..4ebff81208 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 @@ -63,7 +63,7 @@ public class RGraphics { DLL.RegisteredNativeSymbol rns = DLL.RegisteredNativeSymbol.any(); DLL.SymbolHandle func = DLL.findSymbol("InitGraphics", null, rns); assert func != DLL.SYMBOL_NOT_FOUND; - RFFIFactory.getRFFI().getCallRFFI().invokeVoidCall(func, "InitGraphics", new Object[0]); + RFFIFactory.getRFFI().getCallRFFI().invokeVoidCall(func, "InitGraphics", DLL.findLibrary("graphics"), new Object[0]); } } } 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 6ef837a033..9edab7fbd3 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 @@ -175,7 +175,7 @@ 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().asAddress()); + DLL.DLLInfo dllInfo = (DLLInfo) externalPtr.getExternalObject(); if (dllInfo == null) { throw RError.error(this, RError.Message.REQUIRES_NAME_DLLINFO); } 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 ff6b649c54..7b1275c1b1 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 @@ -66,6 +66,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.env.REnvironment.PutException; import com.oracle.truffle.r.runtime.ffi.DLL; +import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo; /** * Private, undocumented, {@code .Internal} and {@code .Primitive} functions transcribed from GnuR, @@ -285,7 +286,7 @@ public class HiddenInternalFunctions { @TruffleBoundary protected RList getRegisteredRoutines(RExternalPtr externalPtr) { Object[] data = new Object[NAMES.getLength()]; - DLL.DLLInfo dllInfo = DLL.getDLLInfoForId((int) externalPtr.getAddr().asAddress()); + DLL.DLLInfo dllInfo = (DLLInfo) externalPtr.getExternalObject(); 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 1b416abe22..cc241faf9f 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 @@ -22,6 +22,7 @@ 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.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.Node.Child; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode; import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode; @@ -35,6 +36,7 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RExternalPtr; import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RLogical; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; @@ -42,6 +44,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.DLLInfo; import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; @@ -67,6 +70,8 @@ public abstract class DotC extends RBuiltinNode { @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); @Override public Object[] getDefaultParameterValues() { @@ -78,7 +83,8 @@ public abstract class DotC extends RBuiltinNode { protected RList c(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, byte naok, byte dup, Object rPackage, RMissing encoding) { SymbolHandle handle = getAddressFromSymbolInfo(frame, symbol); String name = getNameFromSymbolInfo(frame, symbol); - return dispatch(this, handle, name, naok, dup, args); + DLLInfo dllInfo = getDLLInfoFromSymbolInfo(frame, symbol); + return dispatch(this, handle, name, dllInfo, naok, dup, args); } @SuppressWarnings("unused") @@ -99,7 +105,7 @@ public abstract class DotC extends RBuiltinNode { errorProfile.enter(); throw RError.error(this, RError.Message.C_SYMBOL_NOT_IN_TABLE, f); } - return dispatch(this, func, f.getDataAt(0), naok, dup, args); + return dispatch(this, func, f.getDataAt(0), rns.getDllInfo(), naok, dup, args); } private String getNameFromSymbolInfo(VirtualFrame frame, RList symbol) { @@ -118,6 +124,16 @@ public abstract class DotC extends RBuiltinNode { return ((RExternalPtr) addressExtract.applyAccessField(frame, symbol, "address")).getAddr(); } + protected DLLInfo getDLLInfoFromSymbolInfo(VirtualFrame frame, RList symbol) { + if (packageExtract == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + packageExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); + } + // field name may be "package" or "dll", but always at (R) index 3 + RList packageList = (RList) packageExtract.apply(frame, symbol, new Object[]{3}, RLogical.valueOf(false), RMissing.instance); + return (DLLInfo) ((RExternalPtr) addressExtract.applyAccessField(frame, packageList, "info")).getExternalObject(); + } + private static int[] checkNAs(RBuiltinNode node, int argIndex, int[] data) { CompilerAsserts.neverPartOfCompilation(); for (int i = 0; i < data.length; i++) { @@ -151,7 +167,7 @@ public abstract class DotC extends RBuiltinNode { } @TruffleBoundary - protected static RList dispatch(RBuiltinNode node, SymbolHandle handle, String name, byte naok, byte dup, RArgsValuesAndNames args) { + protected static RList dispatch(RBuiltinNode node, SymbolHandle handle, String name, DLLInfo dllInfo, byte naok, byte dup, RArgsValuesAndNames args) { @SuppressWarnings("unused") boolean dupArgs = RRuntime.fromLogical(dup); @SuppressWarnings("unused") @@ -194,7 +210,7 @@ public abstract class DotC extends RBuiltinNode { if (FastROptions.TraceNativeCalls.getBooleanValue()) { trace(name, nativeArgs); } - RFFIFactory.getRFFI().getCRFFI().invoke(handle, nativeArgs); + RFFIFactory.getRFFI().getCRFFI().invoke(handle, nativeArgs, dllInfo); // 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 78711bb74f..4fefa3e956 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 @@ -95,10 +95,12 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RExternalPtr; import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RLogical; 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.DLLInfo; import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; @@ -189,6 +191,8 @@ public class ForeignFunctions { @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 String getNameFromSymbolInfo(VirtualFrame frame, RList symbol) { if (nameExtract == null) { @@ -206,6 +210,16 @@ public class ForeignFunctions { return ((RExternalPtr) addressExtract.applyAccessField(frame, symbol, "address")).getAddr(); } + protected DLLInfo getDLLInfoFromSymbolInfo(VirtualFrame frame, RList symbol) { + if (packageExtract == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + packageExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); + } + // field name may be "package" or "dll", but always at (R) index 3 + RList packageList = (RList) packageExtract.apply(frame, symbol, new Object[]{3}, RLogical.valueOf(false), RMissing.instance); + return (DLLInfo) ((RExternalPtr) addressExtract.applyAccessField(frame, packageList, "info")).getExternalObject(); + } + protected String checkPackageArg(Object rPackage, BranchProfile errorProfile) { String libName = null; if (!(rPackage instanceof RMissing)) { @@ -259,7 +273,7 @@ public class ForeignFunctions { @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) { - return DotC.dispatch(this, getAddressFromSymbolInfo(frame, symbol), getNameFromSymbolInfo(frame, symbol), naok, dup, args); + return DotC.dispatch(this, getAddressFromSymbolInfo(frame, symbol), getNameFromSymbolInfo(frame, symbol), getDLLInfoFromSymbolInfo(frame, symbol), naok, dup, args); } @Specialization @@ -272,7 +286,7 @@ public class ForeignFunctions { errorProfile.enter(); throw RError.error(this, RError.Message.C_SYMBOL_NOT_IN_TABLE, f); } - return DotC.dispatch(this, func, f.getDataAt(0), naok, dup, args); + return DotC.dispatch(this, func, f.getDataAt(0), rns.getDllInfo(), naok, dup, args); } @SuppressWarnings("unused") @@ -549,7 +563,8 @@ public class ForeignFunctions { @Specialization protected Object callNamedFunction(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, @SuppressWarnings("unused") Object packageName) { - return RFFIFactory.getRFFI().getCallRFFI().invokeCall(getAddressFromSymbolInfo(frame, symbol), getNameFromSymbolInfo(frame, symbol), args.getArguments()); + return RFFIFactory.getRFFI().getCallRFFI().invokeCall(getAddressFromSymbolInfo(frame, symbol), getNameFromSymbolInfo(frame, symbol), getDLLInfoFromSymbolInfo(frame, symbol), + args.getArguments()); } @Specialization @@ -565,7 +580,7 @@ public class ForeignFunctions { errorProfile.enter(); throw RError.error(this, RError.Message.C_SYMBOL_NOT_IN_TABLE, name); } - return RFFIFactory.getRFFI().getCallRFFI().invokeCall(func, name, args.getArguments()); + return RFFIFactory.getRFFI().getCallRFFI().invokeCall(func, name, rns.getDllInfo(), args.getArguments()); } @Fallback @@ -636,7 +651,7 @@ public class ForeignFunctions { protected Object callNamedFunction(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, @SuppressWarnings("unused") Object packageName) { String name = getNameFromSymbolInfo(frame, symbol); Object list = encodeArgumentPairList(args, name); - return RFFIFactory.getRFFI().getCallRFFI().invokeCall(getAddressFromSymbolInfo(frame, symbol), name, new Object[]{list}); + return RFFIFactory.getRFFI().getCallRFFI().invokeCall(getAddressFromSymbolInfo(frame, symbol), name, getDLLInfoFromSymbolInfo(frame, symbol), new Object[]{list}); } @Specialization @@ -653,7 +668,7 @@ public class ForeignFunctions { throw RError.error(this, RError.Message.C_SYMBOL_NOT_IN_TABLE, name); } Object list = encodeArgumentPairList(args, name); - return RFFIFactory.getRFFI().getCallRFFI().invokeCall(func, name, new Object[]{list}); + return RFFIFactory.getRFFI().getCallRFFI().invokeCall(func, name, rns.getDllInfo(), new Object[]{list}); } @Fallback @@ -709,7 +724,7 @@ public class ForeignFunctions { String name = getNameFromSymbolInfo(frame, symbol); Object list = encodeArgumentPairList(args, name); // TODO: provide proper values for the CALL, OP and RHO parameters - return RFFIFactory.getRFFI().getCallRFFI().invokeCall(getAddressFromSymbolInfo(frame, symbol), name, new Object[]{CALL, OP, list, RHO}); + return RFFIFactory.getRFFI().getCallRFFI().invokeCall(getAddressFromSymbolInfo(frame, symbol), name, getDLLInfoFromSymbolInfo(frame, symbol), new Object[]{CALL, OP, list, RHO}); } @Specialization @@ -727,7 +742,7 @@ public class ForeignFunctions { } Object list = encodeArgumentPairList(args, name); // TODO: provide proper values for the CALL, OP and RHO parameters - return RFFIFactory.getRFFI().getCallRFFI().invokeCall(func, name, new Object[]{CALL, OP, list, RHO}); + return RFFIFactory.getRFFI().getCallRFFI().invokeCall(func, name, rns.getDllInfo(), new Object[]{CALL, OP, list, RHO}); } @Fallback @@ -767,7 +782,7 @@ public class ForeignFunctions { protected Object callNamedFunction(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, @SuppressWarnings("unused") Object packageName) { String name = getNameFromSymbolInfo(frame, symbol); Object list = encodeArgumentPairList(args, name); - return RFFIFactory.getRFFI().getCallRFFI().invokeCall(getAddressFromSymbolInfo(frame, symbol), name, new Object[]{list}); + return RFFIFactory.getRFFI().getCallRFFI().invokeCall(getAddressFromSymbolInfo(frame, symbol), name, getDLLInfoFromSymbolInfo(frame, symbol), new Object[]{list}); } @Specialization @@ -784,7 +799,7 @@ public class ForeignFunctions { throw RError.error(this, RError.Message.C_SYMBOL_NOT_IN_TABLE, name); } Object list = encodeArgumentPairList(args, name); - return RFFIFactory.getRFFI().getCallRFFI().invokeCall(func, name, new Object[]{list}); + return RFFIFactory.getRFFI().getCallRFFI().invokeCall(func, name, rns.getDllInfo(), new Object[]{list}); } @Fallback @@ -822,7 +837,8 @@ public class ForeignFunctions { @Specialization protected Object callNamedFunction(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, @SuppressWarnings("unused") Object packageName) { - return RFFIFactory.getRFFI().getCallRFFI().invokeCall(getAddressFromSymbolInfo(frame, symbol), getNameFromSymbolInfo(frame, symbol), args.getArguments()); + return RFFIFactory.getRFFI().getCallRFFI().invokeCall(getAddressFromSymbolInfo(frame, symbol), getNameFromSymbolInfo(frame, symbol), getDLLInfoFromSymbolInfo(frame, symbol), + args.getArguments()); } @Specialization @@ -839,7 +855,7 @@ public class ForeignFunctions { errorProfile.enter(); throw RError.error(this, RError.Message.C_SYMBOL_NOT_IN_TABLE, name); } - return RFFIFactory.getRFFI().getCallRFFI().invokeCall(func, name, args.getArguments()); + return RFFIFactory.getRFFI().getCallRFFI().invokeCall(func, name, rns.getDllInfo(), args.getArguments()); } @Fallback 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 5abe50b8ca..13caad9845 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 @@ -65,12 +65,12 @@ public class Generic_Grid implements GridRFFI { @Override public Object initGrid(REnvironment gridEvalEnv) { long initGrid = GridProvider.gridProvider().getInitGrid(); - return RFFIFactory.getRFFI().getCallRFFI().invokeCall(new SymbolHandle(initGrid), "L_initGrid", new Object[]{gridEvalEnv}); + return RFFIFactory.getRFFI().getCallRFFI().invokeCall(new SymbolHandle(initGrid), "L_initGrid", DLL.findLibrary("grid"), new Object[]{gridEvalEnv}); } @Override public Object killGrid() { long killGrid = GridProvider.gridProvider().getKillGrid(); - return RFFIFactory.getRFFI().getCallRFFI().invokeCall(new SymbolHandle(killGrid), "L_killGrid", new Object[0]); + return RFFIFactory.getRFFI().getCallRFFI().invokeCall(new SymbolHandle(killGrid), "L_killGrid", DLL.findLibrary("grid"), 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 a97616f45f..58d17f87c5 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 @@ -72,7 +72,7 @@ public class Generic_Tools implements ToolsRFFI { parseRdCritical.acquire(); long parseRd = ToolsProvider.toolsProvider().getParseRd(); return RFFIFactory.getRFFI().getCallRFFI().invokeCall(new SymbolHandle(parseRd), ToolsProvider.C_PARSE_RD, - new Object[]{con, srcfile, verbose, fragment, basename, warningCalls, macros, warndups}); + DLL.findLibrary("tools"), 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 174ad3844f..a5bf3fa3a7 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.DLLInfo; import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; public class JNI_C implements CRFFI { @@ -36,7 +37,7 @@ public class JNI_C implements CRFFI { */ @Override @TruffleBoundary - public synchronized void invoke(SymbolHandle symbolHandle, Object[] args) { + public synchronized void invoke(SymbolHandle symbolHandle, Object[] args, DLLInfo dllInfo) { c(symbolHandle.asAddress(), 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 16aabaea92..d09ff0ab62 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 @@ -31,6 +31,7 @@ import com.oracle.truffle.r.runtime.RInternalError; 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.DLLInfo; 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; @@ -91,7 +92,7 @@ public class JNI_Call implements CallRFFI { @Override @TruffleBoundary - public synchronized Object invokeCall(SymbolHandle handleArg, String name, Object[] args) { + public synchronized Object invokeCall(SymbolHandle handleArg, String name, DLLInfo dllInfo, Object[] args) { long address = handleArg.asAddress(); Object result = null; if (traceEnabled()) { @@ -152,7 +153,7 @@ public class JNI_Call implements CallRFFI { @Override @TruffleBoundary - public synchronized void invokeVoidCall(SymbolHandle handle, String name, Object[] args) { + public synchronized void invokeVoidCall(SymbolHandle handle, String name, DLLInfo dllInfo, Object[] args) { if (traceEnabled()) { traceDownCall(name, args); } 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 2932ecbe2b..eddf195c7b 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 @@ -26,12 +26,22 @@ import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; /** - * The rarely seen {@code externalptr} type. + * The rarely seen {@code externalptr} type used in native code. */ public class RExternalPtr extends RAttributeStorage implements RTypedValue { + /** + * In GNU R, typically the address of some C structure, so a {@code void*}. Represented here as + * our abstraction of a "native symbol" (even though there may not actually be a symbol + * associated with the address). + */ private SymbolHandle handle; private Object tag; private Object prot; + /** + * Has no GNU R counterpart. Used internally to store a Java object that, for example, + * corresponds to the C state in {@link #handle}. Evidently, the R FFI never accesses this + * field. + */ private Object externalObject; RExternalPtr(SymbolHandle handle, Object externalObject, Object tag, Object prot) { 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 a1b7d4fc55..0097b0f92e 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 @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.runtime.ffi; +import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo; import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; /** @@ -35,6 +36,7 @@ public interface CRFFI { * * @param handle of the native method * @param args native arguments + * @param dllInfo info on the library containing {@code handle} */ - void invoke(SymbolHandle handle, Object[] args); + void invoke(SymbolHandle handle, Object[] args, DLLInfo dllInfo); } 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 6baeebaae6..84890a85b5 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,7 @@ */ package com.oracle.truffle.r.runtime.ffi; +import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo; import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; /** @@ -35,14 +36,16 @@ public interface CallRFFI { * * @param handle the address of the native function * @param name the name of the native function + * @param dllInfo TODO * @param args arguments */ - Object invokeCall(SymbolHandle handle, String name, Object[] args); + Object invokeCall(SymbolHandle handle, String name, DLLInfo dllInfo, Object[] args); /** * Variant that does not return a result (primarily for library "init" methods). + * @param dllInfo TODO */ - void invokeVoidCall(SymbolHandle handle, String name, Object[] args); + void invokeVoidCall(SymbolHandle handle, String name, DLLInfo dllInfo, 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 ec74693d7f..46d8d64749 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 @@ -30,6 +30,7 @@ import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RExternalPtr; import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RSymbol; import com.oracle.truffle.r.runtime.data.RTruffleObject; @@ -188,16 +189,16 @@ public class DLL { data[0] = name; data[1] = path; data[2] = RRuntime.asLogical(dynamicLookup); - data[3] = createExternalPtr(new SymbolHandle(new Long(System.identityHashCode(handle))), HANDLE_CLASS); + data[3] = createExternalPtr(new SymbolHandle(new Long(System.identityHashCode(handle))), HANDLE_CLASS, handle); /* - * 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. + * GnuR sets the info member to an externalptr whose value is the C DllInfo structure + * itself. We use the internal "externalObject" slot instead, and we use the "id" for + * the "addr" slot. */ - 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; + data[4] = createExternalPtr(new SymbolHandle(new Long(id)), INFO_REFERENCE_CLASS, this); + RList result = RDataFactory.createList(data, DLLInfo.NAMES); + result.setClassAttr(RDataFactory.createStringVectorFromScalar(DLLINFO_CLASS)); + return result; } @Override @@ -241,11 +242,11 @@ public class DLL { /* * GnuR stores this as an externalptr whose value is the C RegisteredNativeType * struct. We can't do that, and it's not clear any code uses that fact, so we - * stored the registered address. + * stored the registered address. TODO use externalObject slot? */ - data[1] = DLL.createExternalPtr(rnt.dotSymbol.fun, REGISTERED_NATIVE_SYMBOL_CLASS); + data[1] = DLL.createExternalPtr(rnt.dotSymbol.fun, REGISTERED_NATIVE_SYMBOL_CLASS, null); } else { - data[1] = DLL.createExternalPtr(address, NATIVE_SYMBOL_CLASS); + data[1] = DLL.createExternalPtr(address, NATIVE_SYMBOL_CLASS, null); } data[2] = libInfo.toRList(); if (n > 3) { @@ -288,23 +289,14 @@ public class DLL { public static final SymbolHandle SYMBOL_NOT_FOUND = null; - public static synchronized DLLInfo getDLLInfoForId(int id) { - for (DLLInfo dllInfo : list) { - if (dllInfo.id == id) { - return dllInfo; - } - } - return null; - } - public static boolean isDLLInfo(RExternalPtr info) { RSymbol tag = (RSymbol) info.getTag(); return tag.getName().equals(DLLInfo.DLL_INFO_REFERENCE); } - public static RExternalPtr createExternalPtr(SymbolHandle value, RStringVector rClass) { + public static RExternalPtr createExternalPtr(SymbolHandle value, RStringVector rClass, Object externalObject) { CompilerAsserts.neverPartOfCompilation(); // for interning - RExternalPtr result = RDataFactory.createExternalPtr(value, RDataFactory.createSymbolInterned(rClass.getDataAt(0))); + RExternalPtr result = RDataFactory.createExternalPtr(value, externalObject, RDataFactory.createSymbolInterned(rClass.getDataAt(0)), RNull.instance); result.setClassAttr(rClass); return result; } @@ -363,7 +355,7 @@ public class DLL { if (initFunc != SYMBOL_NOT_FOUND) { synchronized (DLL.class) { try { - RFFIFactory.getRFFI().getCallRFFI().invokeVoidCall(initFunc, pkgInit, new Object[]{dllInfo}); + RFFIFactory.getRFFI().getCallRFFI().invokeVoidCall(initFunc, pkgInit, dllInfo, new Object[]{dllInfo}); } catch (ReturnException ex) { // An error call can, due to condition handling, throw this which we must // propogate -- GitLab