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 c87b109962beea40b11379625d435d8f2d306083..728a1efd4b830abf09db8db075cd947356ce93ed 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 @@ -26,6 +26,7 @@ import com.oracle.truffle.r.runtime.data.RPairList; 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.NativeCallInfo; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; /** @@ -63,7 +64,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(new NativeCallInfo("InitGraphics", func, 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 6ef837a03377c39f4a01d04bac0fda92dc9f8f01..9edab7fbd30972db49f6a3a5f47d2996403c446e 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 ff6b649c54db7750cb1d0cfdb83207c2db2e2006..7b1275c1b1d5ffbe7a3539868b2d97a1a451e9a4 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 1b416abe220f39e0cec57644a8eeef84eb4e6884..8009ea798359a524bc8b59bd25bdd0408fbe1d0e 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 @@ -14,26 +14,19 @@ package com.oracle.truffle.r.nodes.builtin.base.foreign; import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; -import java.util.Arrays; - 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.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; 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; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; -import com.oracle.truffle.r.runtime.FastROptions; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; 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.RMissing; import com.oracle.truffle.r.runtime.data.RStringVector; @@ -42,8 +35,8 @@ 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; +import com.oracle.truffle.r.runtime.ffi.NativeCallInfo; /** * {@code .C} functions. @@ -65,8 +58,11 @@ public abstract class DotC extends RBuiltinNode { private static final int VECTOR_LOGICAL = 12; @SuppressWarnings("unused") private static final int VECTOR_STRING = 12; - @Child private ExtractVectorNode nameExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); - @Child private ExtractVectorNode addressExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); + @Child private ExtractNativeCallInfoNode extractSymbolInfoNode = ExtractNativeCallInfoNodeGen.create(); + + protected NativeCallInfo extractSymbolInfo(VirtualFrame frame, RList symbol) { + return (NativeCallInfo) extractSymbolInfoNode.execute(frame, symbol); + } @Override public Object[] getDefaultParameterValues() { @@ -76,9 +72,8 @@ 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) { - SymbolHandle handle = getAddressFromSymbolInfo(frame, symbol); - String name = getNameFromSymbolInfo(frame, symbol); - return dispatch(this, handle, name, naok, dup, args); + NativeCallInfo nativeCallInfo = extractSymbolInfo(frame, symbol); + return dispatch(this, nativeCallInfo, naok, dup, args); } @SuppressWarnings("unused") @@ -99,23 +94,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); - } - - private String getNameFromSymbolInfo(VirtualFrame frame, RList symbol) { - if (nameExtract == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - nameExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); - } - return RRuntime.asString(nameExtract.applyAccessField(frame, symbol, "name")); - } - - private SymbolHandle getAddressFromSymbolInfo(VirtualFrame frame, RList symbol) { - if (addressExtract == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - addressExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); - } - return ((RExternalPtr) addressExtract.applyAccessField(frame, symbol, "address")).getAddr(); + return dispatch(this, new NativeCallInfo(f.getDataAt(0), func, rns.getDllInfo()), naok, dup, args); } private static int[] checkNAs(RBuiltinNode node, int argIndex, int[] data) { @@ -151,7 +130,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, NativeCallInfo nativeCallInfo, byte naok, byte dup, RArgsValuesAndNames args) { @SuppressWarnings("unused") boolean dupArgs = RRuntime.fromLogical(dup); @SuppressWarnings("unused") @@ -191,10 +170,7 @@ public abstract class DotC extends RBuiltinNode { throw RError.error(node, RError.Message.UNIMPLEMENTED_ARG_TYPE, i + 1); } } - if (FastROptions.TraceNativeCalls.getBooleanValue()) { - trace(name, nativeArgs); - } - RFFIFactory.getRFFI().getCRFFI().invoke(handle, nativeArgs); + RFFIFactory.getRFFI().getCRFFI().invoke(nativeCallInfo, nativeArgs); // we have to assume that the native method updated everything RStringVector listNames = validateArgNames(array.length, args.getSignature()); Object[] results = new Object[array.length]; @@ -236,8 +212,4 @@ public abstract class DotC extends RBuiltinNode { return RDataFactory.createList(results, listNames); } - @TruffleBoundary - private static void trace(String name, Object[] nativeArgs) { - System.out.println("calling " + name + ": " + Arrays.toString(nativeArgs)); - } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ExtractNativeCallInfoNode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ExtractNativeCallInfoNode.java new file mode 100644 index 0000000000000000000000000000000000000000..47d1f4a19c04070de6ce485cc2b780ee8f2bca86 --- /dev/null +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ExtractNativeCallInfoNode.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2016, 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.nodes.builtin.base.foreign; + +import com.oracle.truffle.api.CompilerDirectives; +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.nodes.access.vector.ElementAccessMode; +import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode; +import com.oracle.truffle.r.runtime.RRuntime; +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.ffi.NativeCallInfo; +import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo; +import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; + +/** + * Extracts the salient information needed for a native call from the {@link RList} value provided + * from R. + */ +public abstract 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 Object execute(VirtualFrame frame, RList symbol); + + @Specialization + protected Object extractNativeCallInfo(VirtualFrame frame, RList symbol) { + if (nameExtract == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + nameExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); + } + if (addressExtract == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + addressExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); + } + if (packageExtract == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + packageExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); + } + String name = RRuntime.asString(nameExtract.applyAccessField(frame, symbol, "name")); + SymbolHandle address = ((RExternalPtr) addressExtract.applyAccessField(frame, symbol, "address")).getAddr(); + // 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); + DLLInfo dllInfo = (DLLInfo) ((RExternalPtr) addressExtract.applyAccessField(frame, packageList, "info")).getExternalObject(); + return new NativeCallInfo(name, address, dllInfo); + + } + +} 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 eb498d9e37e77a4be870105a079948f5334602fd..5af4eaa4c4ebf20741417d091c2001dca1ac4737 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 @@ -16,7 +16,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; 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.Cached; import com.oracle.truffle.api.dsl.Fallback; @@ -84,8 +83,6 @@ import com.oracle.truffle.r.library.utils.ObjectSizeNodeGen; import com.oracle.truffle.r.library.utils.RprofNodeGen; import com.oracle.truffle.r.library.utils.RprofmemNodeGen; import com.oracle.truffle.r.library.utils.TypeConvertNodeGen; -import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode; -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; @@ -100,14 +97,13 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.context.RContext; 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.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; +import com.oracle.truffle.r.runtime.ffi.NativeCallInfo; /** * {@code .Call} {@code .Fortran}, {@code .External}, {@code .External2}, {@code External.graphics} @@ -194,23 +190,10 @@ public class ForeignFunctions { throw RError.nyi(this, getRBuiltin().name() + " specialization failure: " + (name == null ? "<unknown>" : name)); } - @Child private ExtractVectorNode nameExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); - @Child private ExtractVectorNode addressExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); + @Child private ExtractNativeCallInfoNode extractSymbolInfoNode = ExtractNativeCallInfoNodeGen.create(); - protected String getNameFromSymbolInfo(VirtualFrame frame, RList symbol) { - if (nameExtract == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - nameExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); - } - return RRuntime.asString(nameExtract.applyAccessField(frame, symbol, "name")); - } - - protected SymbolHandle getAddressFromSymbolInfo(VirtualFrame frame, RList symbol) { - if (addressExtract == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - addressExtract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true); - } - return ((RExternalPtr) addressExtract.applyAccessField(frame, symbol, "address")).getAddr(); + protected NativeCallInfo extractSymbolInfo(VirtualFrame frame, RList symbol) { + return (NativeCallInfo) extractSymbolInfoNode.execute(frame, symbol); } protected String checkPackageArg(Object rPackage, BranchProfile errorProfile) { @@ -266,7 +249,8 @@ 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); + NativeCallInfo nativeCallInfo = extractSymbolInfo(frame, symbol); + return DotC.dispatch(this, nativeCallInfo, naok, dup, args); } @Specialization @@ -279,7 +263,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, new NativeCallInfo(f.getDataAt(0), func, rns.getDllInfo()), naok, dup, args); } @SuppressWarnings("unused") @@ -570,7 +554,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()); + NativeCallInfo nativeCallInfo = extractSymbolInfo(frame, symbol); + return RFFIFactory.getRFFI().getCallRFFI().invokeCall(nativeCallInfo, args.getArguments()); } @Specialization @@ -586,7 +571,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(new NativeCallInfo(name, func, rns.getDllInfo()), args.getArguments()); } @Fallback @@ -655,9 +640,9 @@ public class ForeignFunctions { @Specialization 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}); + NativeCallInfo nativeCallInfo = extractSymbolInfo(frame, symbol); + Object list = encodeArgumentPairList(args, nativeCallInfo.name); + return RFFIFactory.getRFFI().getCallRFFI().invokeCall(nativeCallInfo, new Object[]{list}); } @Specialization @@ -674,7 +659,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(new NativeCallInfo(name, func, rns.getDllInfo()), new Object[]{list}); } @Fallback @@ -727,10 +712,10 @@ public class ForeignFunctions { @Specialization protected Object callNamedFunction(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, @SuppressWarnings("unused") Object packageName) { - String name = getNameFromSymbolInfo(frame, symbol); - Object list = encodeArgumentPairList(args, name); + NativeCallInfo nativeCallInfo = extractSymbolInfo(frame, symbol); + Object list = encodeArgumentPairList(args, nativeCallInfo.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(nativeCallInfo, new Object[]{CALL, OP, list, RHO}); } @Specialization @@ -748,7 +733,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(new NativeCallInfo(name, func, rns.getDllInfo()), new Object[]{CALL, OP, list, RHO}); } @Fallback @@ -786,9 +771,9 @@ public class ForeignFunctions { @Specialization 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}); + NativeCallInfo nativeCallInfo = extractSymbolInfo(frame, symbol); + Object list = encodeArgumentPairList(args, nativeCallInfo.name); + return RFFIFactory.getRFFI().getCallRFFI().invokeCall(nativeCallInfo, new Object[]{list}); } @Specialization @@ -805,7 +790,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(new NativeCallInfo(name, func, rns.getDllInfo()), new Object[]{list}); } @Fallback @@ -843,7 +828,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()); + NativeCallInfo nativeCallInfo = extractSymbolInfo(frame, symbol); + return RFFIFactory.getRFFI().getCallRFFI().invokeCall(nativeCallInfo, args.getArguments()); } @Specialization @@ -860,7 +846,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(new NativeCallInfo(name, func, 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 5abe50b8ca4352f2df4438e4c29968208b36480e..4b79d033cce8889333b8b758dd31c16793a9f3a2 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 @@ -25,10 +25,11 @@ package com.oracle.truffle.r.runtime.ffi.generic; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; 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.GridRFFI; import com.oracle.truffle.r.runtime.ffi.LibPaths; +import com.oracle.truffle.r.runtime.ffi.NativeCallInfo; 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 { @@ -65,12 +66,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 NativeCallInfo("L_initGrid", new SymbolHandle(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 NativeCallInfo("L_killGrid", new SymbolHandle(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 a97616f45fb2bed16b716055223c688bd046dcb9..fedd559f04c17749c46c8744e7379ad5b360870e 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 @@ -33,6 +33,7 @@ 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.NativeCallInfo; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; import com.oracle.truffle.r.runtime.ffi.ToolsRFFI; @@ -71,7 +72,7 @@ public class Generic_Tools implements ToolsRFFI { try { parseRdCritical.acquire(); long parseRd = ToolsProvider.toolsProvider().getParseRd(); - return RFFIFactory.getRFFI().getCallRFFI().invokeCall(new SymbolHandle(parseRd), ToolsProvider.C_PARSE_RD, + return RFFIFactory.getRFFI().getCallRFFI().invokeCall(new NativeCallInfo("parseRd", new SymbolHandle(parseRd), DLL.findLibrary("tools")), new Object[]{con, srcfile, verbose, fragment, basename, warningCalls, macros, warndups}); } catch (Throwable ex) { throw RInternalError.shouldNotReachHere(ex, "error during Rd parsing"); 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 174ad3844f5924b609eb0e6a860e3b964e9ac95c..1928c09f73d4053f518cb777a1c8257b78451ae6 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 @@ -22,9 +22,12 @@ */ package com.oracle.truffle.r.runtime.ffi.jni; +import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceDownCall; +import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceEnabled; + import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.ffi.CRFFI; -import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; +import com.oracle.truffle.r.runtime.ffi.NativeCallInfo; public class JNI_C implements CRFFI { @@ -36,8 +39,11 @@ public class JNI_C implements CRFFI { */ @Override @TruffleBoundary - public synchronized void invoke(SymbolHandle symbolHandle, Object[] args) { - c(symbolHandle.asAddress(), args); + public synchronized void invoke(NativeCallInfo nativeCallInfo, Object[] args) { + if (traceEnabled()) { + traceDownCall(nativeCallInfo.name, args); + } + c(nativeCallInfo.address.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 16aabaea923d0440f3edb434c60f8a28d246897a..8ea6fac033712f9b115c3e191aef0d82a5b8b606 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,9 +31,9 @@ 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.SymbolHandle; import com.oracle.truffle.r.runtime.ffi.DLLRFFI; import com.oracle.truffle.r.runtime.ffi.LibPaths; +import com.oracle.truffle.r.runtime.ffi.NativeCallInfo; import com.oracle.truffle.r.runtime.ffi.RFFIUtils; import com.oracle.truffle.r.runtime.ffi.RFFIVariables; @@ -91,11 +91,11 @@ public class JNI_Call implements CallRFFI { @Override @TruffleBoundary - public synchronized Object invokeCall(SymbolHandle handleArg, String name, Object[] args) { - long address = handleArg.asAddress(); + public synchronized Object invokeCall(NativeCallInfo nativeCallInfo, Object[] args) { + long address = nativeCallInfo.address.asAddress(); Object result = null; if (traceEnabled()) { - traceDownCall(name, args); + traceDownCall(nativeCallInfo.name, args); } try { switch (args.length) { @@ -117,7 +117,7 @@ public class JNI_Call implements CallRFFI { return result; } finally { if (traceEnabled()) { - traceDownCallReturn(name, result); + traceDownCallReturn(nativeCallInfo.name, result); } } } @@ -152,11 +152,11 @@ public class JNI_Call implements CallRFFI { @Override @TruffleBoundary - public synchronized void invokeVoidCall(SymbolHandle handle, String name, Object[] args) { + public synchronized void invokeVoidCall(NativeCallInfo nativeCallInfo, Object[] args) { if (traceEnabled()) { - traceDownCall(name, args); + traceDownCall(nativeCallInfo.name, args); } - long address = handle.asAddress(); + long address = nativeCallInfo.address.asAddress(); try { switch (args.length) { case 0: @@ -170,7 +170,7 @@ public class JNI_Call implements CallRFFI { } } finally { if (traceEnabled()) { - traceDownCallReturn(name, null); + traceDownCallReturn(nativeCallInfo.name, null); } } } 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 2932ecbe2b7370e072093700217529e960a6a3c1..eddf195c7b72b93340f887cd8441f302b5ddebf0 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 a1b7d4fc55642302da0272f420c31208cb96f289..24cdcd702ad4a17447951e0f3aff6fbf9f5267fc 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,8 +22,6 @@ */ package com.oracle.truffle.r.runtime.ffi; -import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; - /** * Support for the {.C} and {.Fortran} calls. */ @@ -32,9 +30,6 @@ public interface CRFFI { * Invoke the native method identified by {@code symbolInfo} passing it the arguments in * {@code args}. The values in {@code args} should be native types,e.g., {@code double[]} not * {@code RDoubleVector}. - * - * @param handle of the native method - * @param args native arguments */ - void invoke(SymbolHandle handle, Object[] args); + void invoke(NativeCallInfo nativeCallInfo, 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 6baeebaae6ed0b53e3d4f3d831458c8183eb6030..3029ffce07e33bfd27552919f3916437fb3a93d3 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,8 +22,6 @@ */ package com.oracle.truffle.r.runtime.ffi; -import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; - /** * Support for the {.Call} and {.External} calls. */ @@ -32,17 +30,13 @@ public interface CallRFFI { * Invoke the native function identified by {@code symbolInfo} passing it the arguments in * {@code args}. The values in {@code args} can be any of the types used to represent {@code R} * values in the implementation. - * - * @param handle the address of the native function - * @param name the name of the native function - * @param args arguments */ - Object invokeCall(SymbolHandle handle, String name, Object[] args); + Object invokeCall(NativeCallInfo nativeCallInfo, Object[] args); /** * Variant that does not return a result (primarily for library "init" methods). */ - void invokeVoidCall(SymbolHandle handle, String name, Object[] args); + void invokeVoidCall(NativeCallInfo nativeCallInfo, 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 ec74693d7f5d5723b403d4a722dbb2a58efa47a0..bceaacfbd4e212370d6dd05252803756e897201e 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(new NativeCallInfo(pkgInit, initFunc, dllInfo), new Object[]{dllInfo}); } catch (ReturnException ex) { // An error call can, due to condition handling, throw this which we must // propogate diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/NativeCallInfo.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/NativeCallInfo.java new file mode 100644 index 0000000000000000000000000000000000000000..b2559c719ee30f9e3880a1016448c05b851d2f01 --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/NativeCallInfo.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016, 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.api.CompilerDirectives.ValueType; +import com.oracle.truffle.r.runtime.data.RList; +import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo; +import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle; + +/** + * The salient information needed for a native call extracted from the {@link RList} object passed + * by R. + */ +@ValueType +public final class NativeCallInfo { + public final String name; + public final SymbolHandle address; + public final DLLInfo dllInfo; + + public NativeCallInfo(String name, SymbolHandle address, DLLInfo dllInfo) { + this.name = name; + this.address = address; + this.dllInfo = dllInfo; + } +}