Skip to content
Snippets Groups Projects
Commit 0f362648 authored by stepan's avatar stepan
Browse files

Serialize and push/pop callbacks for certain functions from NativeFunction

parent b23f0a08
No related branches found
No related tags found
No related merge requests found
......@@ -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();
......
......@@ -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
}
};
}
......
......@@ -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<?>) {
......
......@@ -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;
......
......@@ -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);
}
......
49
50
......@@ -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);
}
}
......@@ -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() {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment