From 9f2d638b579033c45af8a308e9c6b878b2fc0eae Mon Sep 17 00:00:00 2001 From: Mick Jordan <mick.jordan@oracle.com> Date: Mon, 8 Aug 2016 12:18:46 -0700 Subject: [PATCH] ffi: maintain stack of jmpbuf ptrs; run callEnter/callExit on Rembedded dowfalls --- .../fficall/src/jni/Rembedded.c | 50 +++++++++++++------ .../fficall/src/jni/rfficall.c | 15 +++++- .../fficall/src/jni/rffiutils.c | 19 ++++--- .../fficall/src/jni/rffiutils.h | 1 + .../packages/testrffi/testrffi/R/testrffi.R | 10 +++- .../packages/testrffi/testrffi/src/testrffi.c | 14 +++++- 6 files changed, 81 insertions(+), 28 deletions(-) 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 61431ad1d6..191cd77780 100644 --- a/com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c +++ b/com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c @@ -406,14 +406,19 @@ void setupOverrides(void) { } static void REmbed_nativeWriteConsole(JNIEnv *jniEnv, jclass c, jstring string, int otype) { - int len = (*jniEnv)->GetStringUTFLength(jniEnv, string); - const char *cbuf = (*jniEnv)->GetStringUTFChars(jniEnv, string, NULL); - if (ptr_R_WriteConsole == NULL) { - (*ptr_R_WriteConsoleEx)(cbuf, len, otype); - } else { - (*ptr_R_WriteConsole)(cbuf, len); + jmp_buf error_jmpbuf; + callEnter(jniEnv, &error_jmpbuf); + if (!setjmp(error_jmpbuf)) { + int len = (*jniEnv)->GetStringUTFLength(jniEnv, string); + const char *cbuf = (*jniEnv)->GetStringUTFChars(jniEnv, string, NULL); + if (ptr_R_WriteConsole == NULL) { + (*ptr_R_WriteConsoleEx)(cbuf, len, otype); + } else { + (*ptr_R_WriteConsole)(cbuf, len); + } + (*jniEnv)->ReleaseStringUTFChars(jniEnv, string, cbuf); } - (*jniEnv)->ReleaseStringUTFChars(jniEnv, string, cbuf); + callExit(jniEnv); } JNIEXPORT void JNICALL Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1REmbed_nativeWriteConsole(JNIEnv *jniEnv, jclass c, jstring string) { @@ -425,22 +430,37 @@ JNIEXPORT void JNICALL Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1REmbed_nat } JNIEXPORT jstring JNICALL Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1REmbed_nativeReadConsole(JNIEnv *jniEnv, jclass c, jstring prompt) { - const char *cprompt = (*jniEnv)->GetStringUTFChars(jniEnv, prompt, NULL); - unsigned char cbuf[1024]; - int n = (*ptr_R_ReadConsole)(cprompt, cbuf, 1024, 0); - jstring result; - result = (*jniEnv)->NewStringUTF(jniEnv, (const char *)cbuf); - (*jniEnv)->ReleaseStringUTFChars(jniEnv, prompt, cprompt); + jmp_buf error_jmpbuf; + jstring result = NULL; + callEnter(jniEnv, &error_jmpbuf); + if (!setjmp(error_jmpbuf)) { + const char *cprompt = (*jniEnv)->GetStringUTFChars(jniEnv, prompt, NULL); + unsigned char cbuf[1024]; + int n = (*ptr_R_ReadConsole)(cprompt, cbuf, 1024, 0); + result = (*jniEnv)->NewStringUTF(jniEnv, (const char *)cbuf); + (*jniEnv)->ReleaseStringUTFChars(jniEnv, prompt, cprompt); + } + callExit(jniEnv); return result; } JNIEXPORT void JNICALL Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1REmbed_nativeCleanUp(JNIEnv *jniEnv, jclass c, jint x, jint y, jint z) { + jmp_buf error_jmpbuf; + callEnter(jniEnv, &error_jmpbuf); + if (!setjmp(error_jmpbuf)) { (*ptr_R_CleanUp)(x, y, z); + } + callExit(jniEnv); } JNIEXPORT void JNICALL Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1REmbed_nativeSuicide(JNIEnv *jniEnv, jclass c, jstring string) { - const char *cbuf = (*jniEnv)->GetStringUTFChars(jniEnv, string, NULL); - (*ptr_R_Suicide)(cbuf); + jmp_buf error_jmpbuf; + callEnter(jniEnv, &error_jmpbuf); + if (!setjmp(error_jmpbuf)) { + const char *cbuf = (*jniEnv)->GetStringUTFChars(jniEnv, string, NULL); + (*ptr_R_Suicide)(cbuf); + } + callExit(jniEnv); } void uR_PolledEvents(void) { diff --git a/com.oracle.truffle.r.native/fficall/src/jni/rfficall.c b/com.oracle.truffle.r.native/fficall/src/jni/rfficall.c index a8d153d4a0..9b2a545370 100644 --- a/com.oracle.truffle.r.native/fficall/src/jni/rfficall.c +++ b/com.oracle.truffle.r.native/fficall/src/jni/rfficall.c @@ -42,8 +42,6 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_nativeSetTempDir(JNIEnv setTempDir(env, tempDir); } -static jmp_buf error_jmpbuf; - // Boilerplate methods for the actual calls typedef SEXP (*call0func)(); @@ -343,6 +341,7 @@ typedef SEXP (*call64func)(SEXP arg1, SEXP arg2, SEXP arg3, SEXP arg4, SEXP arg5 JNIEXPORT jobject JNICALL Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call0(JNIEnv *env, jclass c, jlong address) { + jmp_buf error_jmpbuf; jobject result = NULL; callEnter(env, &error_jmpbuf); if (!setjmp(error_jmpbuf)) { @@ -355,6 +354,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call0(JNIEnv *env, jclas JNIEXPORT jobject JNICALL Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call1(JNIEnv *env, jclass c, jlong address, jobject arg1) { + jmp_buf error_jmpbuf; jobject result = NULL; callEnter(env, &error_jmpbuf); if (!setjmp(error_jmpbuf)) { @@ -367,6 +367,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call1(JNIEnv *env, jclas JNIEXPORT jobject JNICALL Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call2(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2) { + jmp_buf error_jmpbuf; jobject result = NULL; callEnter(env, &error_jmpbuf); if (!setjmp(error_jmpbuf)) { @@ -380,6 +381,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call2(JNIEnv *env, jclas JNIEXPORT jobject JNICALL Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call3(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2, jobject arg3) { + jmp_buf error_jmpbuf; jobject result = NULL; callEnter(env, &error_jmpbuf); if (!setjmp(error_jmpbuf)) { @@ -393,6 +395,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call3(JNIEnv *env, jclas JNIEXPORT jobject JNICALL Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call4(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2, jobject arg3, jobject arg4) { + jmp_buf error_jmpbuf; jobject result = NULL; callEnter(env, &error_jmpbuf); if (!setjmp(error_jmpbuf)) { @@ -406,6 +409,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call4(JNIEnv *env, jclas JNIEXPORT jobject JNICALL Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call5(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2, jobject arg3, jobject arg4, jobject arg5) { + jmp_buf error_jmpbuf; jobject result = NULL; callEnter(env, &error_jmpbuf); if (!setjmp(error_jmpbuf)) { @@ -419,6 +423,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call5(JNIEnv *env, jclas JNIEXPORT jobject JNICALL Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call6(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2, jobject arg3, jobject arg4, jobject arg5, jobject arg6) { + jmp_buf error_jmpbuf; jobject result = NULL; callEnter(env, &error_jmpbuf); if (!setjmp(error_jmpbuf)) { @@ -432,6 +437,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call6(JNIEnv *env, jclas JNIEXPORT jobject JNICALL Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call7(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2, jobject arg3, jobject arg4, jobject arg5, jobject arg6, jobject arg7) { + jmp_buf error_jmpbuf; jobject result = NULL; callEnter(env, &error_jmpbuf); if (!setjmp(error_jmpbuf)) { @@ -445,6 +451,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call7(JNIEnv *env, jclas JNIEXPORT jobject JNICALL Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call8(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2, jobject arg3, jobject arg4, jobject arg5, jobject arg6, jobject arg7, jobject arg8) { + jmp_buf error_jmpbuf; jobject result = NULL; callEnter(env, &error_jmpbuf); if (!setjmp(error_jmpbuf)) { @@ -458,6 +465,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call8(JNIEnv *env, jclas JNIEXPORT jobject JNICALL Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call9(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2, jobject arg3, jobject arg4, jobject arg5, jobject arg6, jobject arg7, jobject arg8, jobject arg9) { + jmp_buf error_jmpbuf; jobject result = NULL; callEnter(env, &error_jmpbuf); if (!setjmp(error_jmpbuf)) { @@ -470,6 +478,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call9(JNIEnv *env, jclas JNIEXPORT jobject JNICALL Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call(JNIEnv *env, jclass c, jlong address, jobjectArray args) { + jmp_buf error_jmpbuf; jobject result = NULL; callEnter(env, &error_jmpbuf); jsize len = (*env)->GetArrayLength(env, args); @@ -1214,6 +1223,7 @@ typedef void (*callVoid1func)(SEXP arg1); JNIEXPORT void JNICALL Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_callVoid1(JNIEnv *env, jclass c, jlong address, jobject arg1) { + jmp_buf error_jmpbuf; callEnter(env, &error_jmpbuf); if (!setjmp(error_jmpbuf)) { callVoid1func call1 = (callVoid1func) address; @@ -1226,6 +1236,7 @@ typedef void (*callVoid0func)(); JNIEXPORT void JNICALL Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_callVoid0(JNIEnv *env, jclass c, jlong address) { + jmp_buf error_jmpbuf; callEnter(env, &error_jmpbuf); if (!setjmp(error_jmpbuf)) { callVoid0func call1 = (callVoid0func) address; diff --git a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c index 2ec1c0522e..30257753b7 100644 --- a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c +++ b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c @@ -43,7 +43,6 @@ jmethodID createSymbolMethodID; static jmethodID validateMethodID; static JNIEnv *curenv = NULL; -jmp_buf *callErrorJmpBuf; // default for trace output when enabled FILE *traceFile = NULL; @@ -84,10 +83,14 @@ void setEmbedded() { } // native down call depth, indexes nativeArrayTableHwmStack -int callDepth; +int callDepth = 0; + +#define CALLDEPTH_STACK_SIZE 16 +static int nativeArrayTableHwmStack[CALLDEPTH_STACK_SIZE]; + +// stack of jmp_buf ptrs for non-local control transfer on error +static jmp_buf* callErrorJmpBufTable[CALLDEPTH_STACK_SIZE]; -#define NATIVE_ARRAY_TABLE_HWM_STACK_SIZE 16 -int nativeArrayTableHwmStack[NATIVE_ARRAY_TABLE_HWM_STACK_SIZE] ; void init_utils(JNIEnv *env) { curenv = env; @@ -140,8 +143,9 @@ const char *stringToChars(JNIEnv *jniEnv, jstring string) { void callEnter(JNIEnv *env, jmp_buf *jmpbuf) { setEnv(env); - callErrorJmpBuf = jmpbuf; - if (callDepth >= NATIVE_ARRAY_TABLE_HWM_STACK_SIZE) { + //printf("callEnter: callDepth %d, jmpbufptr %p\n", callDepth, jmpbuf); + callErrorJmpBufTable[callDepth] = jmpbuf; + if (callDepth >= CALLDEPTH_STACK_SIZE) { fatalError("call stack overflow\n"); } nativeArrayTableHwmStack[callDepth] = nativeArrayTableHwm; @@ -149,7 +153,8 @@ void callEnter(JNIEnv *env, jmp_buf *jmpbuf) { } jmp_buf *getErrorJmpBuf() { - return callErrorJmpBuf; + // printf("getErrorJmpBuf: callDepth %d, jmpbufptr %p\n", callDepth, callErrorJmpBufTable[callDepth - 1]); + return callErrorJmpBufTable[callDepth - 1]; } void callExit(JNIEnv *env) { diff --git a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h index 4311b0464a..8dad284ce3 100644 --- a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h +++ b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h @@ -64,6 +64,7 @@ void callExit(JNIEnv *env); // called by callExit to deallocate transient memory void allocExit(); +// returns the jmp_buf at the current call depth jmp_buf *getErrorJmpBuf(); // Given the x denotes an R vector type, return a pointer to diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R index 5f3f4ff8c3..6f53923b53 100644 --- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R +++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R @@ -30,8 +30,8 @@ rffi.TYPEOF <- function(x) { .Call("invoke_TYPEOF", x, PACKAGE = "testrffi") } -rffi.error <- function() { - .Call("invoke_error", PACKAGE = "testrffi") +rffi.error <- function(msg = "invoke_error in testrffi") { + .Call("invoke_error", msg, PACKAGE = "testrffi") } rffi.dotExternalAccessArgs <- function(...) { @@ -103,4 +103,10 @@ rffi.release_object <- function(x) { invisible(.Call("release_object", x, PACKAGE = "testrffi")) } +rffi.findvar <- function(x, env) { + if (is.character(x)) { + x = as.symbol(x) + } + .Call("findvar", x, env, PACKAGE = "testrffi") +} diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c index 21be9bc239..61f4862f88 100644 --- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c +++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c @@ -89,8 +89,8 @@ SEXP invoke_TYPEOF(SEXP x) { return ScalarInteger(TYPEOF(x)); } -SEXP invoke_error() { - error("invoke_error in testrffi"); +SEXP invoke_error(SEXP msg) { + error(R_CHAR(STRING_ELT(msg, 0))); } // returns a @@ -270,3 +270,13 @@ SEXP release_object(SEXP x) { R_ReleaseObject(x); return R_NilValue; } + +SEXP findvar(SEXP x, SEXP env) { + SEXP v = Rf_findVar(x, env); + if (v == R_UnboundValue) { + Rf_error("'%s' not found", R_CHAR(PRINTNAME(x))); + } else { + return v; + } +} + -- GitLab