From 0760e1bc799e2a2743144ea9d267e46ee82d27ea Mon Sep 17 00:00:00 2001 From: Mick Jordan <mick.jordan@oracle.com> Date: Wed, 22 Jun 2016 08:28:14 -0700 Subject: [PATCH] Improve native call tracing Implement FFI DEBUG calls --- .gitignore | 4 +- .../r/engine/RRuntimeASTAccessImpl.java | 20 +++- .../truffle/r/engine/TruffleRLanguage.java | 2 +- .../fficall/src/jni/Rembedded.c | 76 +++++++++++-- .../fficall/src/jni/Rinternals.c | 23 ++-- .../instrumentation/RInstrumentation.java | 2 +- .../truffle/r/runtime/ffi/RFFIUtils.java | 76 ++++++++++--- .../r/runtime/ffi/jnr/CallRFFIHelper.java | 102 ++++++++++++++++++ .../r/runtime/ffi/jnr/JNI_CallRFFI.java | 12 +-- .../truffle/r/runtime/RRuntimeASTAccess.java | 11 +- 10 files changed, 283 insertions(+), 45 deletions(-) diff --git a/.gitignore b/.gitignore index e988817cdb..d39a0a4a07 100644 --- a/.gitignore +++ b/.gitignore @@ -81,6 +81,7 @@ scratch/ bin/ share/ etc/ +doc/ src_gen/ /local/ /.hgtip @@ -113,4 +114,5 @@ test_gnur test_fastr lib.install.cran* package.blacklist -com.oracle.truffle.r.test.native/embedded/main +com.oracle.truffle.r.test.native/embedded/lib + diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java index 0727968f1c..abd98ab841 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java @@ -575,11 +575,6 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess { return RASTUtils.unwrap(promise.getRep()).asRSyntaxNode(); } - @Override - public void enableDebug(RFunction func) { - DebugHandling.enableDebug(func, "", RNull.instance, false); - } - @Override public boolean isTaggedWith(Node node, Class<?> tag) { if (!(node instanceof RSyntaxNode)) { @@ -642,4 +637,19 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess { return ConstantNode.create(o); } + @Override + public boolean enableDebug(RFunction func, boolean once) { + return DebugHandling.enableDebug(func, "", RNull.instance, once); + } + + @Override + public boolean isDebugged(RFunction func) { + return DebugHandling.isDebugged(func); + } + + @Override + public boolean disableDebug(RFunction func) { + return DebugHandling.undebug(func); + } + } diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java index ce068b4847..a3196da63f 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java @@ -76,7 +76,7 @@ public final class TruffleRLanguage extends TruffleLanguage<RContext> { RPackageSource.initialize(); RContext.initialize(new RASTBuilder(), new RRuntimeASTAccessImpl(), RBuiltinPackages.getInstance(), new RForeignAccessFactoryImpl()); } catch (Throwable t) { - System.out.println("error during engine initialization:"); + System.err.println("error during engine initialization: " + t); t.printStackTrace(); System.exit(-1); } 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 af0a6d0093..0708f7b286 100644 --- a/com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c +++ b/com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c @@ -11,14 +11,17 @@ */ #include <dlfcn.h> #include <sys/utsname.h> +#include <sys/stat.h> #include <rffiutils.h> #include <R_ext/RStartup.h> #include <Rinterface.h> +extern char **environ; static JavaVM *javaVM; static jobject engine; static int initialized = 0; +static char *java_home; static jclass rembeddedClass; static jclass rStartParamsClass; @@ -51,7 +54,7 @@ static int process_vmargs(int argc, char *argv[], char *vmargv[], char *uargv[]) int ucount = 0; for (int i = 0; i < argc; i++) { char *arg = argv[i]; - if (arg[0] == '-' && arg[1] == 'X') { + if ((arg[0] == '-' && arg[1] == 'X') || (arg[0] == '-' && arg[1] == 'D')) { vmargv[vcount++] = arg; } else { uargv[ucount++] = arg; @@ -60,13 +63,16 @@ static int process_vmargs(int argc, char *argv[], char *vmargv[], char *uargv[]) return vcount; } -char *get_classpath(char *r_home); +static char **update_environ_with_java_home(void); +static void print_environ(char **env); +static char *get_classpath(char *r_home); int Rf_initialize_R(int argc, char *argv[]) { if (initialized) { fprintf(stderr, "%s", "R is already initialized\n"); exit(1); } + // print_environ(environ); char *r_home = getenv("R_HOME"); if (r_home == NULL) { printf("R_HOME must be set\n"); @@ -75,10 +81,19 @@ int Rf_initialize_R(int argc, char *argv[]) { struct utsname utsname; uname(&utsname); char jvmlib_path[256]; - char *java_home = getenv("JAVA_HOME"); + java_home = getenv("JAVA_HOME"); if (java_home == NULL) { - printf("Rf_initialize_R: can't find JAVA_HOME"); - exit(1); + if (strcmp(utsname.sysname, "Linux") == 0) { + char *jvmdir = "/usr/java/latest"; + struct stat statbuf; + if (stat(jvmdir, &statbuf) == 0) { + java_home = jvmdir; + } + } + if (java_home == NULL) { + printf("Rf_initialize_R: can't find a JAVA_HOME\n"); + exit(1); + } } strcpy(jvmlib_path, java_home); if (strcmp(utsname.sysname, "Linux") == 0) { @@ -435,7 +450,7 @@ int R_wait_usec; #include <unistd.h> #include <errno.h> -void perror_exit(char *msg) { +static void perror_exit(char *msg) { perror(msg); exit(1); } @@ -443,7 +458,9 @@ 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 // during normal execution -char *get_classpath(char *r_home) { +static char *get_classpath(char *r_home) { + char **env = update_environ_with_java_home(); + //print_environ(env); int pipefd[2]; if (pipe(pipefd) == -1) { perror_exit("pipe"); @@ -460,7 +477,7 @@ char *get_classpath(char *r_home) { while ((dup2(pipefd[1], STDOUT_FILENO) == -1) && (errno == EINTR)) {} close(pipefd[1]); close(pipefd[0]); - int rc = execl(path, (char *)NULL); + int rc = execle(path, path, (char *)NULL, env); if (rc == -1) { perror_exit("exec"); } @@ -498,3 +515,46 @@ char *get_classpath(char *r_home) { return buf; } } + +// debugging +static void print_environ(char **env) { + printf("## Environment variables at %p\n", env); + char **e = env; + while (*e != NULL) { + printf("%s\n", *e); + e++; + } +} + +static char **update_environ(char *def) { + int count = 0; + char **e = environ; + while (*e != NULL) { + e++; + count++; + } + char **new_env = malloc(sizeof(char *) * (count + 2)); + e = environ; + char **ne = new_env; + while (*e != NULL) { + *ne++ = *e++; + } + *ne++ = def; + *ne = (char*) NULL; + return new_env; +} + +static char **update_environ_with_java_home(void) { + char **e = environ; + while (*e != NULL) { + if (strstr(*e, "JAVA_HOME=")) { + return environ; + } + e++; + } + char *java_home_env = malloc(strlen(java_home) + 10); + strcpy(java_home_env, "JAVA_HOME="); + strcat(java_home_env, java_home); + return update_environ(java_home_env); +} + 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 7893e1e94a..629ec2aa16 100644 --- a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c +++ b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c @@ -90,6 +90,11 @@ static jmethodID DUPLICATE_ATTRIB_MethodID; static jmethodID isS4ObjectMethodID; static jmethodID logObject_MethodID; static jmethodID R_tryEvalMethodID; +static jmethodID RDEBUGMethodID; +static jmethodID SET_RDEBUGMethodID; +static jmethodID RSTEPMethodID; +static jmethodID SET_RSTEPMethodID; + static jclass RExternalPtrClass; static jmethodID createExternalPtrMethodID; @@ -172,6 +177,10 @@ void init_internals(JNIEnv *env) { isS4ObjectMethodID = checkGetMethodID(env, CallRFFIHelperClass, "isS4Object", "(Ljava/lang/Object;)I", 1); logObject_MethodID = checkGetMethodID(env, CallRFFIHelperClass, "logObject", "(Ljava/lang/Object;)V", 1); R_tryEvalMethodID = checkGetMethodID(env, CallRFFIHelperClass, "R_tryEval", "(Ljava/lang/Object;Ljava/lang/Object;Z)Ljava/lang/Object;", 1); + RDEBUGMethodID = checkGetMethodID(env, CallRFFIHelperClass, "RDEBUG", "(Ljava/lang/Object;)I", 1); + SET_RDEBUGMethodID = checkGetMethodID(env, CallRFFIHelperClass, "SET_RDEBUG", "(Ljava/lang/Object;I)V", 1); + RSTEPMethodID = checkGetMethodID(env, CallRFFIHelperClass, "RSTEP", "(Ljava/lang/Object;)I", 1); + SET_RSTEPMethodID = checkGetMethodID(env, CallRFFIHelperClass, "SET_RSTEP", "(Ljava/lang/Object;I)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); @@ -854,13 +863,13 @@ SEXP CLOENV(SEXP x) { } int RDEBUG(SEXP x) { - unimplemented("RDEBUG"); - return 0; + JNIEnv *thisenv = getEnv(); + return (*thisenv)->CallStaticIntMethod(thisenv, CallRFFIHelperClass, RDEBUGMethodID, x); } int RSTEP(SEXP x) { - unimplemented("RSTEP"); - return 0; + JNIEnv *thisenv = getEnv(); + return (*thisenv)->CallStaticIntMethod(thisenv, CallRFFIHelperClass, RSTEPMethodID, x); } int RTRACE(SEXP x) { @@ -869,11 +878,13 @@ int RTRACE(SEXP x) { } void SET_RDEBUG(SEXP x, int v) { - unimplemented("SET_RDEBUG"); + JNIEnv *thisenv = getEnv(); + (*thisenv)->CallStaticVoidMethod(thisenv, CallRFFIHelperClass, SET_RDEBUGMethodID, x, v); } void SET_RSTEP(SEXP x, int v) { - unimplemented("SET_RSTEP"); + JNIEnv *thisenv = getEnv(); + (*thisenv)->CallStaticVoidMethod(thisenv, CallRFFIHelperClass, SET_RSTEPMethodID, x, v); } void SET_RTRACE(SEXP x, int v) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RInstrumentation.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RInstrumentation.java index efeab31d46..33264d6fd0 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RInstrumentation.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RInstrumentation.java @@ -223,7 +223,7 @@ public class RInstrumentation { FunctionDefinitionNode fdn = (FunctionDefinitionNode) func.getRootNode(); for (String debugFunctionName : debugFunctionNames) { if (debugFunctionName.equals(fdn.toString())) { - RContext.getRRuntimeASTAccess().enableDebug(func); + RContext.getRRuntimeASTAccess().enableDebug(func, false); } } } diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/RFFIUtils.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/RFFIUtils.java index ea8c579410..137427c09f 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/RFFIUtils.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/RFFIUtils.java @@ -22,14 +22,22 @@ */ package com.oracle.truffle.r.runtime.ffi; +import java.io.FileWriter; import java.io.IOException; +import java.io.PrintWriter; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.FastROptions; import com.oracle.truffle.r.runtime.data.RPairList; +import com.oracle.truffle.r.runtime.data.RSymbol; import com.oracle.truffle.r.runtime.data.RTypedValue; public class RFFIUtils { + /** + * Set this to {@code true} when it is not possible to set {@link FastROptions}. + */ + private static boolean alwaysTrace; + public static byte[] wrapChar(char v) { return new byte[]{(byte) v}; } @@ -47,25 +55,69 @@ public class RFFIUtils { throw new IOException(errMsg); } - public static void traceCall(String name, Object... args) { - if (FastROptions.TraceNativeCalls.getBooleanValue()) { - System.out.print("CallRFFI " + name + ": "); - printArgs(args); - System.out.println(); + /** + * Places in /tmp because in embedded mode can't trust that cwd is writeable. Also, tag with + * time in event of multiple concurrent instances. + */ + private static final String tracePathPrefix = "/tmp/fastr_trace_nativecalls.log-"; + private static PrintWriter traceWriter; + + private static void initialize() { + if (traceWriter == null) { + String tracePath = tracePathPrefix + Long.toString(System.currentTimeMillis()); + try { + traceWriter = new PrintWriter(new FileWriter(tracePath)); + } catch (IOException ex) { + System.err.println(ex.getMessage()); + System.exit(1); + } + } + } + + public static void traceUpCall(String name, Object... args) { + traceCall(false, name, args); + } + + public static void traceDownCall(String name, Object... args) { + traceCall(true, name, args); + } + + private static void traceCall(boolean down, String name, Object... args) { + if (alwaysTrace || FastROptions.TraceNativeCalls.getBooleanValue()) { + initialize(); + StringBuffer sb = new StringBuffer(); + sb.append("CallRFFI["); + sb.append(down ? "Down" : "Up"); + sb.append(']'); + sb.append(name); + sb.append('('); + printArgs(sb, args); + sb.append(')'); + traceWriter.println(sb.toString()); + traceWriter.flush(); } } - private static void printArgs(Object[] args) { + private static void printArgs(StringBuffer sb, Object[] args) { + boolean first = true; for (Object arg : args) { - System.out.print(" "); - System.out.print(arg == null ? "" : arg.getClass().getSimpleName()); + if (first) { + first = false; + } else { + sb.append(", "); + } + sb.append(arg == null ? "" : arg.getClass().getSimpleName()); if (arg instanceof RPairList) { - System.out.print("["); - printArgs(((RPairList) arg).toRList().getDataCopy()); - System.out.print("]"); + sb.append("["); + printArgs(sb, ((RPairList) arg).toRList().getDataCopy()); + sb.append("]"); + } + if (arg instanceof RSymbol) { + RSymbol symbol = (RSymbol) arg; + sb.append("\"" + symbol.getName() + "\")"); } if (!(arg instanceof RTypedValue)) { - System.out.print("(" + arg + ")"); + sb.append("(" + arg + ")"); } } } 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 32ddbbeebf..845d6070a1 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 @@ -68,6 +68,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.env.REnvironment.PutException; +import com.oracle.truffle.r.runtime.ffi.RFFIUtils; import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; import com.oracle.truffle.r.runtime.nodes.DuplicationHelper; import com.oracle.truffle.r.runtime.rng.RRNG; @@ -142,23 +143,28 @@ public class CallRFFIHelper { // Checkstyle: stop method name check public static RIntVector Rf_ScalarInteger(int value) { + RFFIUtils.traceUpCall("Rf_ScalarInteger", value); return RDataFactory.createIntVectorFromScalar(value); } public static RLogicalVector Rf_ScalarLogical(int value) { + RFFIUtils.traceUpCall("Rf_ScalarLogical", value); return RDataFactory.createLogicalVectorFromScalar(value != 0); } public static RDoubleVector Rf_ScalarDouble(double value) { + RFFIUtils.traceUpCall("Rf_ScalarDouble", value); return RDataFactory.createDoubleVectorFromScalar(value); } public static RStringVector Rf_ScalarString(Object value) { + RFFIUtils.traceUpCall("Rf_ScalarString", value); CharSXPWrapper chars = guaranteeInstanceOf(value, CharSXPWrapper.class); return RDataFactory.createStringVectorFromScalar(chars.getContents()); } public static int Rf_asInteger(Object x) { + RFFIUtils.traceUpCall("Rf_asInteger", x); if (x instanceof Integer) { return ((Integer) x).intValue(); } else if (x instanceof Double) { @@ -172,6 +178,7 @@ public class CallRFFIHelper { } public static double Rf_asReal(Object x) { + RFFIUtils.traceUpCall("Rf_asReal", x); if (x instanceof Double) { return ((Double) x).doubleValue(); } else if (x instanceof Byte) { @@ -183,6 +190,7 @@ public class CallRFFIHelper { } public static int Rf_asLogical(Object x) { + RFFIUtils.traceUpCall("Rf_asLogical", x); if (x instanceof Byte) { return ((Byte) x).intValue(); } else { @@ -192,6 +200,7 @@ public class CallRFFIHelper { } public static Object Rf_asChar(Object x) { + RFFIUtils.traceUpCall("Rf_asChar", x); if (x instanceof CharSXPWrapper) { return x; } else if (x instanceof RSymbol) { @@ -214,15 +223,18 @@ public class CallRFFIHelper { } public static Object Rf_mkCharLenCE(byte[] bytes, @SuppressWarnings("unused") int encoding) { + RFFIUtils.traceUpCall("Rf_mkCharLenCE", bytes); // TODO: handle encoding properly return new CharSXPWrapper(new String(bytes, StandardCharsets.UTF_8)); } public static Object Rf_cons(Object car, Object cdr) { + RFFIUtils.traceUpCall("Rf_cons", car, cdr); return RDataFactory.createPairList(car, cdr); } public static void Rf_defineVar(Object symbolArg, Object value, Object envArg) { + RFFIUtils.traceUpCall("Rf_defineVar", symbolArg, value, envArg); REnvironment env = (REnvironment) envArg; RSymbol name = (RSymbol) symbolArg; try { @@ -233,10 +245,12 @@ public class CallRFFIHelper { } public static Object Rf_findVar(Object symbolArg, Object envArg) { + RFFIUtils.traceUpCall("Rf_findVar", symbolArg, envArg); return findVarInFrameHelper(symbolArg, envArg, true); } public static Object Rf_findVarInFrame(Object symbolArg, Object envArg) { + RFFIUtils.traceUpCall("Rf_findVarInFrame", symbolArg, envArg); return findVarInFrameHelper(symbolArg, envArg, false); } @@ -264,6 +278,7 @@ public class CallRFFIHelper { } public static Object Rf_getAttrib(Object obj, Object name) { + RFFIUtils.traceUpCall("Rf_getAttrib", obj, name); Object result = RNull.instance; if (obj instanceof RAttributable) { RAttributable attrObj = (RAttributable) obj; @@ -280,6 +295,7 @@ public class CallRFFIHelper { } public static void Rf_setAttrib(Object obj, Object name, Object val) { + RFFIUtils.traceUpCall("Rf_setAttrib", obj, name); if (obj instanceof RAttributable) { RAttributable attrObj = (RAttributable) obj; String nameAsString; @@ -301,6 +317,7 @@ public class CallRFFIHelper { } public static RStringVector getClassHr(Object v) { + RFFIUtils.traceUpCall("getClassHr", v); if (v instanceof RAttributable) { return ((RAttributable) v).getClassHierarchy(); } else if (v instanceof Byte) { @@ -322,6 +339,7 @@ public class CallRFFIHelper { } public static int Rf_inherits(Object x, String clazz) { + RFFIUtils.traceUpCall("Rf_inherits", x, clazz); RStringVector hierarchy = getClassHr(x); for (int i = 0; i < hierarchy.getLength(); i++) { if (hierarchy.getDataAt(i).equals(clazz)) { @@ -332,19 +350,23 @@ public class CallRFFIHelper { } public static Object Rf_lengthgets(Object x, int newSize) { + RFFIUtils.traceUpCall("Rf_lengthgets", x, newSize); RAbstractVector vec = (RAbstractVector) RRuntime.asAbstractVector(x); return vec.resize(newSize); } public static int Rf_isString(Object x) { + RFFIUtils.traceUpCall("Rf_isString", x); return RRuntime.checkType(x, RType.Character) ? 1 : 0; } public static int Rf_isNull(Object x) { + RFFIUtils.traceUpCall("Rf_isNull", x); return x == RNull.instance ? 1 : 0; } public static Object Rf_PairToVectorList(Object x) { + RFFIUtils.traceUpCall("Rf_PairToVectorList", x); if (x == RNull.instance) { return RDataFactory.createList(); } @@ -353,18 +375,22 @@ public class CallRFFIHelper { } public static void Rf_error(String msg) { + RFFIUtils.traceUpCall("Rf_error", msg); throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, msg); } public static void Rf_warning(String msg) { + RFFIUtils.traceUpCall("Rf_warning", msg); RError.warning(RError.SHOW_CALLER2, RError.Message.GENERIC, msg); } public static void Rf_warningcall(Object call, String msg) { + RFFIUtils.traceUpCall("Rf_warningcall", call, msg); RErrorHandling.warningcallRFFI(call, msg); } public static Object Rf_allocateVector(int mode, int n) { + RFFIUtils.traceUpCall("Rf_allocateVector", mode, n); SEXPTYPE type = SEXPTYPE.mapInt(mode); if (n < 0) { throw RError.error(RError.SHOW_CALLER2, RError.Message.NEGATIVE_LENGTH_VECTORS_NOT_ALLOWED); @@ -391,6 +417,7 @@ public class CallRFFIHelper { } public static Object Rf_allocateArray(int mode, Object dimsObj) { + RFFIUtils.traceUpCall("Rf_allocateArray", mode, dimsObj); RIntVector dims = (RIntVector) dimsObj; int n = 1; int[] newDims = new int[dims.getLength()]; @@ -406,6 +433,7 @@ public class CallRFFIHelper { } public static Object Rf_allocateMatrix(int mode, int ncol, int nrow) { + RFFIUtils.traceUpCall("Rf_allocateMatrix", mode, ncol, nrow); SEXPTYPE type = SEXPTYPE.mapInt(mode); if (nrow < 0 || ncol < 0) { throw RError.error(RError.SHOW_CALLER2, RError.Message.NEGATIVE_EXTENTS_TO_MATRIX); @@ -429,6 +457,7 @@ public class CallRFFIHelper { } public static int LENGTH(Object x) { + RFFIUtils.traceUpCall("LENGTH", x); if (x instanceof RAbstractContainer) { return ((RAbstractContainer) x).getLength(); } else if (x == RNull.instance) { @@ -443,17 +472,20 @@ public class CallRFFIHelper { } public static void SET_STRING_ELT(Object x, int i, Object v) { + RFFIUtils.traceUpCall("SET_STRING_ELT", x, i, v); RStringVector vector = guaranteeInstanceOf(x, RStringVector.class); CharSXPWrapper element = guaranteeInstanceOf(v, CharSXPWrapper.class); vector.setElement(i, element.getContents()); } public static void SET_VECTOR_ELT(Object x, int i, Object v) { + RFFIUtils.traceUpCall("SET_VECTOR_ELT", i, v); RList list = guaranteeInstanceOf(x, RList.class); list.setElement(i, v); } public static byte[] RAW(Object x) { + RFFIUtils.traceUpCall("RAW", x); if (x instanceof RRawVector) { return ((RRawVector) x).getDataWithoutCopying(); } else if (x instanceof RRaw) { @@ -464,6 +496,7 @@ public class CallRFFIHelper { } public static byte[] LOGICAL(Object x) { + RFFIUtils.traceUpCall("LOGICAL", x); if (x instanceof RLogicalVector) { return ((RLogicalVector) x).getDataWithoutCopying(); } else if (x instanceof Byte) { @@ -474,6 +507,7 @@ public class CallRFFIHelper { } public static int[] INTEGER(Object x) { + RFFIUtils.traceUpCall("INTEGER", x); if (x instanceof RIntVector) { return ((RIntVector) x).getDataWithoutCopying(); } else if (x instanceof RIntSequence) { @@ -494,6 +528,7 @@ public class CallRFFIHelper { } public static double[] REAL(Object x) { + RFFIUtils.traceUpCall("REAL", x); if (x instanceof RDoubleVector) { return ((RDoubleVector) x).getDataWithoutCopying(); } else if (x instanceof RDoubleSequence) { @@ -510,17 +545,20 @@ public class CallRFFIHelper { } public static Object STRING_ELT(Object x, int i) { + RFFIUtils.traceUpCall("STRING_ELT", x, i); RAbstractStringVector vector = guaranteeInstanceOf(RRuntime.asAbstractVector(x), RAbstractStringVector.class); return new CharSXPWrapper(vector.getDataAt(i)); } public static Object VECTOR_ELT(Object x, int i) { + RFFIUtils.traceUpCall("VECTOR_ELT", x, i); Object vec = x; RAbstractListVector list = guaranteeInstanceOf(RRuntime.asAbstractVector(vec), RAbstractListVector.class); return list.getDataAt(i); } public static int NAMED(Object x) { + RFFIUtils.traceUpCall("NAMED", x); if (x instanceof RShareable) { return ((RShareable) x).isShared() ? 1 : 0; } else { @@ -529,6 +567,7 @@ public class CallRFFIHelper { } public static Object SET_TYPEOF_FASTR(Object x, int v) { + RFFIUtils.traceUpCall("SET_TYPEOF_FASTR", x, v); int code = SEXPTYPE.gnuRCodeForObject(x); if (code == SEXPTYPE.LISTSXP.code && v == SEXPTYPE.LANGSXP.code) { RList l; @@ -544,6 +583,7 @@ public class CallRFFIHelper { } public static int TYPEOF(Object x) { + RFFIUtils.traceUpCall("TYPEOF", x); if (x instanceof CharSXPWrapper) { return SEXPTYPE.CHARSXP.code; } else { @@ -552,6 +592,7 @@ public class CallRFFIHelper { } public static int OBJECT(Object x) { + RFFIUtils.traceUpCall("OBJECT", x); if (x instanceof RAttributable) { return ((RAttributable) x).getAttr(RRuntime.CLASS_ATTR_KEY) == null ? 0 : 1; } else { @@ -560,11 +601,13 @@ public class CallRFFIHelper { } public static Object Rf_duplicate(Object x) { + RFFIUtils.traceUpCall("Rf_duplicate", x); guaranteeInstanceOf(x, RAbstractVector.class); return ((RAbstractVector) x).copy(); } public static int Rf_anyDuplicated(Object x, int fromLast) { + RFFIUtils.traceUpCall("Rf_anyDuplicated", x, fromLast); RAbstractVector vec = (RAbstractVector) x; if (vec.getLength() == 0) { return 0; @@ -574,11 +617,13 @@ public class CallRFFIHelper { } public static Object PRINTNAME(Object x) { + RFFIUtils.traceUpCall("PRINTNAME", x); guaranteeInstanceOf(x, RSymbol.class); return new CharSXPWrapper(((RSymbol) x).getName()); } public static Object TAG(Object e) { + RFFIUtils.traceUpCall("TAG", e); if (e instanceof RPairList) { return ((RPairList) e).getTag(); } else { @@ -589,24 +634,28 @@ public class CallRFFIHelper { } public static Object CAR(Object e) { + RFFIUtils.traceUpCall("CAR", e); guaranteeInstanceOf(e, RPairList.class); Object car = ((RPairList) e).car(); return car; } public static Object CDR(Object e) { + RFFIUtils.traceUpCall("CDR", e); guaranteeInstanceOf(e, RPairList.class); Object cdr = ((RPairList) e).cdr(); return cdr; } public static Object CADR(Object e) { + RFFIUtils.traceUpCall("CADR", e); guaranteeInstanceOf(e, RPairList.class); Object cadr = ((RPairList) e).cadr(); return cadr; } public static Object SET_TAG(Object x, Object y) { + RFFIUtils.traceUpCall("SET_TAG", x, y); if (x instanceof RPairList) { ((RPairList) x).setTag(y); } else { @@ -618,18 +667,21 @@ public class CallRFFIHelper { } public static Object SETCAR(Object x, Object y) { + RFFIUtils.traceUpCall("SETCAR", x, y); guaranteeInstanceOf(x, RPairList.class); ((RPairList) x).setCar(y); return x; // TODO check or y? } public static Object SETCDR(Object x, Object y) { + RFFIUtils.traceUpCall("SETCDR", x, y); guaranteeInstanceOf(x, RPairList.class); ((RPairList) x).setCdr(y); return x; // TODO check or y? } public static Object SYMVALUE(Object x) { + RFFIUtils.traceUpCall("SYMVALUE", x); if (!(x instanceof RSymbol)) { throw RInternalError.shouldNotReachHere(); } @@ -642,6 +694,7 @@ public class CallRFFIHelper { } public static void SET_SYMVALUE(Object x, Object v) { + RFFIUtils.traceUpCall("SET_SYMVALUE", x, v); if (!(x instanceof RSymbol)) { throw RInternalError.shouldNotReachHere(); } @@ -649,11 +702,13 @@ public class CallRFFIHelper { } public static Object R_FindNamespace(Object name) { + RFFIUtils.traceUpCall("R_FindNamespace", name); Object result = RContext.getInstance().stateREnvironment.getNamespaceRegistry().get(RRuntime.asString(name)); return result; } public static Object Rf_eval(Object expr, Object env) { + RFFIUtils.traceUpCall("Rf_eval", expr, env); guarantee(env instanceof REnvironment); Object result; if (expr instanceof RPromise) { @@ -670,6 +725,7 @@ public class CallRFFIHelper { } public static Object Rf_findfun(Object symbolObj, Object envObj) { + RFFIUtils.traceUpCall("Rf_findfun", symbolObj, envObj); guarantee(envObj instanceof REnvironment); REnvironment env = (REnvironment) envObj; guarantee(symbolObj instanceof RSymbol); @@ -685,12 +741,14 @@ public class CallRFFIHelper { } public static Object Rf_GetOption1(Object tag) { + RFFIUtils.traceUpCall("Rf_GetOption1", tag); guarantee(tag instanceof RSymbol); Object result = RContext.getInstance().stateROptions.getValue(((RSymbol) tag).getName()); return result; } public static void Rf_gsetVar(Object symbol, Object value, Object rho) { + RFFIUtils.traceUpCall("Rf_gsetVar", symbol, value, rho); guarantee(symbol instanceof RSymbol); REnvironment baseEnv = RContext.getInstance().stateREnvironment.getBaseEnv(); guarantee(rho == baseEnv); @@ -702,6 +760,7 @@ public class CallRFFIHelper { } public static void DUPLICATE_ATTRIB(Object to, Object from) { + RFFIUtils.traceUpCall("DUPLICATE_ATTRIB", to, from); if (from instanceof RAttributable) { guaranteeInstanceOf(to, RAttributable.class); RAttributes attributes = ((RAttributable) from).getAttributes(); @@ -711,12 +770,14 @@ public class CallRFFIHelper { } public static REnvironment Rf_createNewEnv(REnvironment parent, String name, boolean hashed, int initialSize) { + RFFIUtils.traceUpCall("Rf_createNewEnv", parent, name, hashed, initialSize); REnvironment env = RDataFactory.createNewEnv(name, hashed, initialSize); RArguments.initializeEnclosingFrame(env.getFrame(), parent.getFrame()); return env; } public static int R_computeIdentical(Object x, Object y, int flags) { + RFFIUtils.traceUpCall("R_computeIdentical", x, y, flags); RFunction indenticalBuiltin = RContext.lookupBuiltin("identical"); Object res = RContext.getEngine().evalFunction(indenticalBuiltin, null, null, x, y, RRuntime.asLogical((!((flags & 1) == 0))), RRuntime.asLogical((!((flags & 2) == 0))), RRuntime.asLogical((!((flags & 4) == 0))), RRuntime.asLogical((!((flags & 8) == 0))), RRuntime.asLogical((!((flags & 16) == 0)))); @@ -725,16 +786,19 @@ public class CallRFFIHelper { @SuppressWarnings("unused") public static void Rf_copyListMatrix(Object s, Object t, int byrow) { + RFFIUtils.traceUpCall("Rf_copyListMatrix", t, byrow); throw unimplemented(); } @SuppressWarnings("unused") public static void Rf_copyMatrix(Object s, Object t, int byrow) { + RFFIUtils.traceUpCall("Rf_copyMatrix", t, byrow); throw unimplemented(); } @SuppressWarnings("unused") public static Object R_tryEval(Object expr, Object env, boolean silent) { + RFFIUtils.traceUpCall("R_tryEval", expr, env, silent); Object handlerStack = RErrorHandling.getHandlerStack(); Object restartStack = RErrorHandling.getRestartStack(); try { @@ -749,8 +813,37 @@ 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; + } + + 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); + } + } + + public static int RSTEP(Object x) { + RFFIUtils.traceUpCall("RSTEP", x); + RFunction func = guaranteeInstanceOf(x, RFunction.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); + throw RInternalError.unimplemented("SET_RSTEP"); + } + @SuppressWarnings("unused") private static String R_HomeDir() { + RFFIUtils.traceUpCall("R_HomeDir"); return REnvVars.rHome(); } @@ -766,26 +859,32 @@ public class CallRFFIHelper { } public static Object getGlobalEnv() { + RFFIUtils.traceUpCall("getGlobalEnv"); return RContext.getInstance().stateREnvironment.getGlobalEnv(); } public static Object getBaseEnv() { + RFFIUtils.traceUpCall("getBaseEnv"); return RContext.getInstance().stateREnvironment.getBaseEnv(); } public static Object getBaseNamespace() { + RFFIUtils.traceUpCall("getBaseNamespace"); return RContext.getInstance().stateREnvironment.getBaseNamespace(); } public static Object getNamespaceRegistry() { + RFFIUtils.traceUpCall("getNamespaceRegistry"); return RContext.getInstance().stateREnvironment.getNamespaceRegistry(); } public static int isInteractive() { + RFFIUtils.traceUpCall("isInteractive"); return RContext.getInstance().isInteractive() ? 1 : 0; } public static int isS4Object(Object x) { + RFFIUtils.traceUpCall("isS4Object"); return x instanceof RS4Object ? 1 : 0; } @@ -794,14 +893,17 @@ public class CallRFFIHelper { } public static void getRNGstate() { + RFFIUtils.traceUpCall("getRNGstate"); RRNG.getRNGState(); } public static void putRNGstate() { + RFFIUtils.traceUpCall("putRNGstate"); RRNG.updateDotRandomSeed(); } public static double unifRand() { + RFFIUtils.traceUpCall("unifRand"); return RRNG.unifRand(); } } diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_CallRFFI.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_CallRFFI.java index 83957a8d90..0964f60ebd 100644 --- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_CallRFFI.java +++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_CallRFFI.java @@ -22,7 +22,7 @@ */ package com.oracle.truffle.r.runtime.ffi.jnr; -import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceCall; +import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceDownCall; import java.util.concurrent.Semaphore; @@ -66,7 +66,7 @@ public class JNI_CallRFFI implements CallRFFI { throw new RInternalError(ex, "error while loading " + librffiPath); } System.load(librffiPath); - traceCall("initialize"); + traceDownCall("initialize"); initialize(RFFIVariables.values()); } @@ -74,7 +74,7 @@ public class JNI_CallRFFI implements CallRFFI { @Override public Object invokeCall(long address, String name, Object[] args) { - traceCall(name, args); + traceDownCall(name, args); try { inCritical.acquire(); switch (args.length) { @@ -130,7 +130,7 @@ public class JNI_CallRFFI implements CallRFFI { @Override public void invokeVoidCall(long address, String name, Object[] args) { - traceCall(name, args); + traceDownCall(name, args); try { inCritical.acquire(); switch (args.length) { @@ -155,7 +155,7 @@ public class JNI_CallRFFI implements CallRFFI { @Override public void setTempDir(String tempDir) { - traceCall("setTempDir", tempDir); + traceDownCall("setTempDir", tempDir); try { inCritical.acquire(); RFFIVariables.setTempDir(tempDir); @@ -168,7 +168,7 @@ public class JNI_CallRFFI implements CallRFFI { @Override public void setInteractive(boolean interactive) { - traceCall("setInteractive", interactive); + traceDownCall("setInteractive", interactive); try { inCritical.acquire(); nativeSetInteractive(interactive); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java index 0b0c7bdd7e..a6f96c9b38 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java @@ -170,11 +170,6 @@ public interface RRuntimeASTAccess { */ void traceAllFunctions(); - /** - * Project circularity workaround. - */ - void enableDebug(RFunction func); - /** * Project circularity workaround. Equivalent to * RASTUtils.unwrap(promise.getRep()).asRSyntaxNode(). @@ -190,4 +185,10 @@ public interface RRuntimeASTAccess { RBaseNode createConstantNode(Object o); + boolean enableDebug(RFunction func, boolean once); + + boolean disableDebug(RFunction func); + + boolean isDebugged(RFunction func); + } -- GitLab