diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c b/com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c index 0708f7b286e314ef6574acdc288d0e612f5b5515..4baebf20759b4d068a874bba6c240e998f184fbe 100644 --- a/com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c +++ b/com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c @@ -456,7 +456,7 @@ static void perror_exit(char *msg) { } // support for getting the correct classpath for the VM -// We use $R_HOME/bin/exec/Rclasspath to do this to emulate what happens +// We use $R_HOME/bin/execRextras/Rclasspath to do this to emulate what happens // during normal execution static char *get_classpath(char *r_home) { char **env = update_environ_with_java_home(); @@ -473,7 +473,7 @@ static char *get_classpath(char *r_home) { // child char path[1024]; strcpy(path, r_home); - strcat(path, "/bin/exec/Rclasspath"); + strcat(path, "/bin/execRextras/Rclasspath"); while ((dup2(pipefd[1], STDOUT_FILENO) == -1) && (errno == EINTR)) {} close(pipefd[1]); close(pipefd[0]); diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c index 629ec2aa16d41774fb68a43631c434d9364bc8bc..3837eb2cacd690839bf1df9f036623b454d3d37a 100644 --- a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c +++ b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c @@ -95,6 +95,10 @@ static jmethodID SET_RDEBUGMethodID; static jmethodID RSTEPMethodID; static jmethodID SET_RSTEPMethodID; +static jclass rErrorHandlingClass; +static jclass handlerStacksClass; +static jmethodID resetAndGetHandlerStacksMethodID; +static jmethodID restoreHandlerStacksMethodID; static jclass RExternalPtrClass; static jmethodID createExternalPtrMethodID; @@ -182,6 +186,11 @@ void init_internals(JNIEnv *env) { RSTEPMethodID = checkGetMethodID(env, CallRFFIHelperClass, "RSTEP", "(Ljava/lang/Object;)I", 1); SET_RSTEPMethodID = checkGetMethodID(env, CallRFFIHelperClass, "SET_RSTEP", "(Ljava/lang/Object;I)V", 1); + rErrorHandlingClass = checkFindClass(env, "com/oracle/truffle/r/runtime/RErrorHandling"); + handlerStacksClass = checkFindClass(env, "com/oracle/truffle/r/runtime/RErrorHandling$HandlerStacks"); + resetAndGetHandlerStacksMethodID = checkGetMethodID(env, rErrorHandlingClass, "resetAndGetHandlerStacks", "()Lcom/oracle/truffle/r/runtime/RErrorHandling$HandlerStacks;", 1); + restoreHandlerStacksMethodID = checkGetMethodID(env, rErrorHandlingClass, "restoreHandlerStacks", "(Lcom/oracle/truffle/r/runtime/RErrorHandling$HandlerStacks;)V", 1); + RExternalPtrClass = checkFindClass(env, "com/oracle/truffle/r/runtime/data/RExternalPtr"); createExternalPtrMethodID = checkGetMethodID(env, RDataFactoryClass, "createExternalPtr", "(JLjava/lang/Object;Ljava/lang/Object;)Lcom/oracle/truffle/r/runtime/data/RExternalPtr;", 1); externalPtrGetAddrMethodID = checkGetMethodID(env, RExternalPtrClass, "getAddr", "()J", 0); @@ -1309,7 +1318,12 @@ void UNSET_S4_OBJECT(SEXP x) { } Rboolean R_ToplevelExec(void (*fun)(void *), void *data) { - return (Rboolean) unimplemented("R_ToplevelExec"); + JNIEnv *env = getEnv(); + jobject handlerStacks = (*env)->CallStaticObjectMethod(env, CallRFFIHelperClass, resetAndGetHandlerStacksMethodID); + fun(data); + (*env)->CallStaticVoidMethod(env, CallRFFIHelperClass, restoreHandlerStacksMethodID, handlerStacks); + // TODO how do we detect error + return TRUE; } SEXP R_ExecWithCleanup(SEXP (*fun)(void *), void *data, diff --git a/com.oracle.truffle.r.native/run/Makefile b/com.oracle.truffle.r.native/run/Makefile index a1d290b8345d67c3fb8ce478d39c444abb5c5a1c..b445653a8b170c4f793c62fc5d44ed3e4ffc2d89 100644 --- a/com.oracle.truffle.r.native/run/Makefile +++ b/com.oracle.truffle.r.native/run/Makefile @@ -27,7 +27,7 @@ # but in FastR it is just a slight variant of "R". However, we cannot put # a FastR-specific Rscript in "exec" because the install_packages code # treats everything in there except "R" as a sub-architecture, so we put in -# execRscript. +# execRextras. # # The R script defines the R_HOME environment variable from R_HOME_DIR # which is set in the script during the GnuR build. This has to be changed. @@ -59,18 +59,18 @@ rundirs: mkdir -p $(FASTR_BIN_DIR) mkdir -p $(FASTR_DOC_DIR) mkdir -p $(FASTR_BIN_DIR)/exec - mkdir -p $(FASTR_BIN_DIR)/execRscript + mkdir -p $(FASTR_BIN_DIR)/execRextras mkdir -p $(FASTR_ETC_DIR) mkdir -p $(FASTR_SHARE_DIR) rcmds: $(FASTR_BIN_DIR)/R -$(FASTR_BIN_DIR)/R: Makefile R.sh Rscript.sh Rscript_exec.sh +$(FASTR_BIN_DIR)/R: Makefile R.sh Rscript.sh Rscript_exec.sh Rclasspath.sh cp R.sh $(FASTR_BIN_DIR)/exec/R - cp Rscript_exec.sh $(FASTR_BIN_DIR)/execRscript/Rscript + cp Rscript_exec.sh $(FASTR_BIN_DIR)/execRextras/Rscript cp Rscript.sh $(FASTR_BIN_DIR)/Rscript - cp Rclasspath.sh $(FASTR_BIN_DIR)/exec/Rclasspath - chmod +x $(FASTR_BIN_DIR)/exec/R $(FASTR_BIN_DIR)/execRscript/Rscript $(FASTR_BIN_DIR)/Rscript $(FASTR_BIN_DIR)/exec/Rclasspath + cp Rclasspath.sh $(FASTR_BIN_DIR)/execRextras/Rclasspath + chmod +x $(FASTR_BIN_DIR)/exec/R $(FASTR_BIN_DIR)/execRextras/Rscript $(FASTR_BIN_DIR)/Rscript $(FASTR_BIN_DIR)/execRextras/Rclasspath cp $(SUPPORT_SCRIPTS) $(FASTR_BIN_DIR) sed -e 's!^\(R_HOME_DIR=\)\(.*\)!\1"$(FASTR_R_HOME)"!' < $(R_SCRIPT) > $(FASTR_BIN_DIR)/R chmod +x $(FASTR_BIN_DIR)/R diff --git a/com.oracle.truffle.r.native/run/Rscript.sh b/com.oracle.truffle.r.native/run/Rscript.sh index 8098306855128274371cfda7c173533ad111a6e1..527369554d9f6dc980e07cdfc233138766c6627e 100755 --- a/com.oracle.truffle.r.native/run/Rscript.sh +++ b/com.oracle.truffle.r.native/run/Rscript.sh @@ -24,10 +24,11 @@ # In GnuR Rscript is an executable in the bin directory. # In FastR Rscript and R are combined in the same image. For consistency -# Rscript is a script in the bin directory that simply invokes bin/exec/Rscript +# Rscript is a script in the bin directory that simply invokes bin/execRextras/Rscript +# N.B. This can't be in bin/exec as then it is treated as a sub0architecture source="${BASH_SOURCE[0]}" while [ -h "$source" ] ; do source="$(readlink "$source")"; done here="$( cd -P "$( dirname "$source" )" && pwd )" -exec $here/execRscript/Rscript "$@" +exec $here/execRextras/Rscript "$@" diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java index 845d6070a18c3714e551e74fec276d616139bbfb..628267de6b93e38e04d9ba102ee6a5bc85da04e7 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java @@ -815,29 +815,39 @@ public class CallRFFIHelper { public static int RDEBUG(Object x) { RFFIUtils.traceUpCall("RDEBUG", x); - RFunction func = guaranteeInstanceOf(x, RFunction.class); - return RContext.getRRuntimeASTAccess().isDebugged(func) ? 1 : 0; + REnvironment env = guaranteeInstanceOf(x, REnvironment.class); + if (env instanceof REnvironment.Function) { + REnvironment.Function funcEnv = (REnvironment.Function) env; + RFunction func = RArguments.getFunction(funcEnv.getFrame()); + return RContext.getRRuntimeASTAccess().isDebugged(func) ? 1 : 0; + } else { + return 0; + } } public static void SET_RDEBUG(Object x, int v) { RFFIUtils.traceUpCall("SET_RDEBUG", x, v); - RFunction func = guaranteeInstanceOf(x, RFunction.class); - if (v == 1) { - RContext.getRRuntimeASTAccess().enableDebug(func, false); - } else { - RContext.getRRuntimeASTAccess().disableDebug(func); + REnvironment env = guaranteeInstanceOf(x, REnvironment.class); + if (env instanceof REnvironment.Function) { + REnvironment.Function funcEnv = (REnvironment.Function) env; + RFunction func = RArguments.getFunction(funcEnv.getFrame()); + if (v == 1) { + RContext.getRRuntimeASTAccess().enableDebug(func, false); + } else { + RContext.getRRuntimeASTAccess().disableDebug(func); + } } } public static int RSTEP(Object x) { RFFIUtils.traceUpCall("RSTEP", x); - RFunction func = guaranteeInstanceOf(x, RFunction.class); + REnvironment func = guaranteeInstanceOf(x, REnvironment.class); throw RInternalError.unimplemented("RSTEP"); } public static void SET_RSTEP(Object x, int v) { RFFIUtils.traceUpCall("SET_RSTEP", x, v); - RFunction func = guaranteeInstanceOf(x, RFunction.class); + REnvironment func = guaranteeInstanceOf(x, REnvironment.class); throw RInternalError.unimplemented("SET_RSTEP"); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java index 01acffda1dbacd00a9937820fe7afb2734e3ae78..1721878f20ebf71441f1f717bd67227b34bb67c7 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java @@ -163,12 +163,28 @@ public class RErrorHandling { } } + public static class HandlerStacks { + public final Object handlerStack; + public final Object restartStack; + + private HandlerStacks(Object handlerStack, Object restartStack) { + this.handlerStack = handlerStack; + this.restartStack = restartStack; + } + } + private static final Object RESTART_TOKEN = new Object(); private static ContextStateImpl getRErrorHandlingState() { return RContext.getInstance().stateRErrorHandling; } + public static HandlerStacks resetAndGetHandlerStacks() { + HandlerStacks result = new HandlerStacks(getRErrorHandlingState().handlerStack, getRErrorHandlingState().restartStack); + resetStacks(); + return result; + } + public static Object getHandlerStack() { return getRErrorHandlingState().handlerStack; } @@ -188,6 +204,10 @@ public class RErrorHandling { errorHandlingState.restartStack = RNull.instance; } + public static void restoreHandlerStacks(HandlerStacks handlerStacks) { + restoreStacks(handlerStacks.handlerStack, handlerStacks.restartStack); + } + public static void restoreStacks(Object savedHandlerStack, Object savedRestartStack) { ContextStateImpl errorHandlingState = getRErrorHandlingState(); errorHandlingState.handlerStack = savedHandlerStack;