diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_DownCallNodeFactory.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_DownCallNodeFactory.java index 348720b931b57f4a067b9fa3d307f770ffc4719d..722f0a242cc963a2ee2a412ca4562e7c409ed212 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_DownCallNodeFactory.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_DownCallNodeFactory.java @@ -69,7 +69,7 @@ final class TruffleLLVM_DownCallNodeFactory extends DownCallNodeFactory { @Override @ExplodeLoop - protected void wrapArguments(TruffleObject function, Object[] args) { + protected long beforeCall(NativeFunction nativeFunction, TruffleObject function, Object[] args) { for (int i = 0; i < args.length; i++) { Object obj = args[i]; if (obj instanceof double[]) { @@ -82,6 +82,7 @@ final class TruffleLLVM_DownCallNodeFactory extends DownCallNodeFactory { args[i] = new NativeCharArray(getStringBytes((String) obj)); } } + return 0; } @TruffleBoundary @@ -91,7 +92,7 @@ final class TruffleLLVM_DownCallNodeFactory extends DownCallNodeFactory { @Override @ExplodeLoop - protected void finishArguments(Object[] args) { + protected void afterCall(long before, NativeFunction function, TruffleObject target, Object[] args) { for (Object obj : args) { if (obj instanceof NativeNACheck<?>) { ((NativeNACheck<?>) obj).close(); diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/Managed_DownCallNodeFactory.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/Managed_DownCallNodeFactory.java index c30daa85b3ea71834a82c902e0204a81da1c5fde..13eb6601ce8a4908d412362f3b9261621aa06d2d 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/Managed_DownCallNodeFactory.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/Managed_DownCallNodeFactory.java @@ -70,7 +70,7 @@ public final class Managed_DownCallNodeFactory extends DownCallNodeFactory { } @Override - protected void wrapArguments(TruffleObject function, Object[] args) { + protected long beforeCall(NativeFunction nativeFunction, TruffleObject function, Object[] args) { // Report unsupported functions at invocation time if (function instanceof DummyFunctionObject) { throw Managed_RFFIFactory.unsupported(((DummyFunctionObject) function).function.getCallName()); @@ -79,8 +79,8 @@ public final class Managed_DownCallNodeFactory extends DownCallNodeFactory { } @Override - protected void finishArguments(Object[] args) { - throw RInternalError.shouldNotReachHere(); + protected void afterCall(long before, NativeFunction function, TruffleObject target, Object[] args) { + // nop } }; } diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_DownCallNodeFactory.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_DownCallNodeFactory.java index efa57394f1d3dcdd67a843231c04eeeeee6f7ac6..60eea1dfb8dcce3dd65a2cc61e1ad3ee1b658f19 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_DownCallNodeFactory.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_DownCallNodeFactory.java @@ -27,6 +27,7 @@ import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.interop.java.JavaInterop; import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.r.ffi.impl.interop.NativeNACheck; +import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.ffi.DownCallNodeFactory; import com.oracle.truffle.r.runtime.ffi.NativeFunction; import com.oracle.truffle.r.runtime.ffi.interop.NativeUInt8Array; @@ -49,7 +50,7 @@ public final class TruffleNFI_DownCallNodeFactory extends DownCallNodeFactory { @SuppressWarnings("cast") @Override @ExplodeLoop - protected void wrapArguments(TruffleObject function, Object[] args) { + protected long beforeCall(NativeFunction function, TruffleObject target, Object[] args) { for (int i = 0; i < args.length; i++) { Object obj = args[i]; if (obj instanceof double[]) { @@ -71,6 +72,11 @@ public final class TruffleNFI_DownCallNodeFactory extends DownCallNodeFactory { args[i] = JavaInterop.asTruffleObject(data); } } + + if (function.hasComplexInteraction()) { + return ((TruffleNFI_Context) RContext.getInstance().getRFFI()).beforeDowncall(); + } + return 0; } @TruffleBoundary @@ -83,7 +89,11 @@ public final class TruffleNFI_DownCallNodeFactory extends DownCallNodeFactory { @Override @ExplodeLoop - protected void finishArguments(Object[] args) { + protected void afterCall(long before, NativeFunction function, TruffleObject target, Object[] args) { + if (function.hasComplexInteraction()) { + RContext.getInstance().getRFFI().afterDowncall(before); + } + for (Object obj : args) { // TODO: can this ever happen in NFI? if (obj instanceof NativeNACheck<?>) { diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_common/base_rffi.c b/com.oracle.truffle.r.native/fficall/src/truffle_common/base_rffi.c index db79b2215ba6b5029038ba6705ce42c0bb802a79..73fc274caa466d2c1e57c5d868bebe252520076c 100644 --- a/com.oracle.truffle.r.native/fficall/src/truffle_common/base_rffi.c +++ b/com.oracle.truffle.r.native/fficall/src/truffle_common/base_rffi.c @@ -46,10 +46,6 @@ int call_base_chdir(char *dir) { return chdir(dir); } -int call_base_mkdir(char *dir, int mode) { - return mkdir(dir, mode); -} - int call_base_mkdtemp(char *template) { char *r = mkdtemp(template); if (r == NULL) { @@ -59,10 +55,6 @@ int call_base_mkdtemp(char *template) { } } -int call_base_chmod(char *path, int mode) { - return chmod(path, mode); -} - void call_base_uname(void (*call_uname_setfields)(char *sysname, char *release, char *version, char *machine, char *nodename)) { struct utsname name; diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rembedded.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rembedded.c index 147982d7a0f0fb133b2a6ef6eb354b9f4ac199eb..21214ae229252fa78034d2e6714096e7ec3acb20 100644 --- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rembedded.c +++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rembedded.c @@ -503,23 +503,16 @@ void R_runHandlers(InputHandler *handlers, fd_set *mask) { // ----------------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------------- -// Downcalls from Java. We invoke these functions via .Call interface so that the callbacks -// variable gets properly initialized and in general the R API is available. These functions -// delegate to user provided C routines that may want to access the R API. -// NOTE: those two functions are looked up by name! +// Downcalls from Java. We invoke these functions via REmbedRFFI -SEXP invokeCleanUp(SEXP x, SEXP y, SEXP z) { - ptr_R_CleanUp(Rf_asInteger(x), Rf_asInteger(y), Rf_asInteger(z)); - return R_NilValue; +void invokeCleanUp(int x, int y, int z) { + ptr_R_CleanUp(x, y, z); } -SEXP invokeSuicide(SEXP msg) { - ptr_R_Suicide(R_CHAR(STRING_ELT(msg, 0))); - return R_NilValue; +void invokeSuicide(char* msg) { + ptr_R_Suicide(msg); } -// TODO: these 3 are not yet invoked via .Call - void rembedded_write_console(char *cbuf, int len) { writeConsoleImpl(cbuf, len, 0); } diff --git a/com.oracle.truffle.r.native/version.source b/com.oracle.truffle.r.native/version.source index 95f9650f0151d7c0d3aecf40355d88effbd5b7a7..e373ee695f6e76d7d3f8f8c4e92d1d60995352e5 100644 --- a/com.oracle.truffle.r.native/version.source +++ b/com.oracle.truffle.r.native/version.source @@ -1 +1 @@ -49 +50 diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DownCallNodeFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DownCallNodeFactory.java index ad69b9cfe7e4119ab4585784b09a8e8f0849f688..af484e9aeee40bfe2225c722bcae3ca0569b6dfd 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DownCallNodeFactory.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DownCallNodeFactory.java @@ -65,6 +65,7 @@ public abstract class DownCallNodeFactory { * NFI where the array should be passed as Java array, not as Truffle Object. */ public final Object call(Object... args) { + long before = -1; try { if (message == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); @@ -74,12 +75,12 @@ public abstract class DownCallNodeFactory { CompilerDirectives.transferToInterpreterAndInvalidate(); target = getTarget(function); } - wrapArguments(target, args); + before = beforeCall(function, target, args); return ForeignAccess.sendExecute(message, target, args); } catch (InteropException e) { throw RInternalError.shouldNotReachHere(e); } finally { - finishArguments(args); + afterCall(before, function, target, args); } } @@ -91,14 +92,16 @@ public abstract class DownCallNodeFactory { /** * Allows to transform the arguments before the execute message is sent to the result of - * {@link #getTarget(NativeFunction)}. Allways invoked even if {@code args.length == 0}. + * {@link #getTarget(NativeFunction)}. */ - protected abstract void wrapArguments(TruffleObject function, Object[] args); + protected abstract long beforeCall(NativeFunction nativeFunction, TruffleObject function, Object[] args); /** * Allows to post-process the arguments after the execute message was sent to the result of - * {@link #getTarget(NativeFunction)}. + * {@link #getTarget(NativeFunction)}. If the call to + * {@link #beforeCall(NativeFunction, TruffleObject, Object[])} was not successfull, the + * {@code before} parameter will have value {@code -1}. */ - protected abstract void finishArguments(Object[] args); + protected abstract void afterCall(long before, NativeFunction function, TruffleObject target, Object[] args); } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/NativeFunction.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/NativeFunction.java index ba0908f9efec11a6f2141d2c150961187c9a1c7d..de1d47a0f6518e4c141c5b6a3a70459e7cae8ba5 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/NativeFunction.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/NativeFunction.java @@ -82,11 +82,11 @@ public enum NativeFunction { // FastR helpers set_exception_flag("(): void"), // FastR internal helper for R embedded mode - rembedded_write_console("(string, sint32):void"), - rembedded_write_err_console("(string, sint32):void"), - rembedded_read_console("(string):string"), - rembedded_native_clean_up("(sint32, sint32, sint32):void"), - rembedded_native_suicide("(string):void"), + rembedded_write_console("(string, sint32):void", "", anyLibrary(), true), + rembedded_write_err_console("(string, sint32):void", "", anyLibrary(), true), + rembedded_read_console("(string):string", "", anyLibrary(), true), + rembedded_native_clean_up("(sint32, sint32, sint32):void", "", anyLibrary(), true), + rembedded_native_suicide("(string):void", "", anyLibrary(), true), // user-defined RNG unif_init("(sint32): void", "user_", anyLibrary()), norm_rand("(): pointer", "user_", anyLibrary()), @@ -94,6 +94,7 @@ public enum NativeFunction { unif_nseed("(): pointer", "user_", anyLibrary()), unif_seedloc("(): pointer", "user_", anyLibrary()), // memory access helper functions + // TODO: these could use Unsafe instead read_pointer_int("(pointer): sint32", "caccess_"), read_array_int("(pointer, sint64): sint32", "caccess_"), read_pointer_double("(pointer): double", "caccess_"), @@ -109,12 +110,18 @@ public enum NativeFunction { private final String signature; private final int argumentCount; private final String library; + private final boolean complexInteraction; - NativeFunction(String signature, String prefix, String library) { + NativeFunction(String signature, String prefix, String library, boolean complexInteraction) { this.callName = prefix + name(); this.signature = signature; this.argumentCount = getArgCount(signature); this.library = library; + this.complexInteraction = complexInteraction; + } + + NativeFunction(String signature, String prefix, String library) { + this(signature, prefix, library, false); } NativeFunction(String signature, String prefix) { @@ -141,6 +148,15 @@ public enum NativeFunction { return library; } + /** + * Returns {@code true} if the function has complex interaction with its environment, including + * that it is not reentrant, uses R API (e.g. {@code allocVector}), or may invoke arbitrary user + * code. + */ + public boolean hasComplexInteraction() { + return complexInteraction; + } + // Functions because the enum constants cannot refer to static final fields: public static String anyLibrary() {