From b7f0dac6006b3315a33c11880bf5c23df03af5fc Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Fri, 10 Feb 2017 11:43:16 -0800
Subject: [PATCH] rffi: refactor UpCallsImpl to transparently use wrapper for
 tracing

---
 .../fficall/src/jni/Rinternals.c              |  13 +-
 .../fficall/src/jni/rffiutils.c               |   2 +-
 .../fficall/src/jni/rffiutils.h               |   1 +
 .../r/nodes/ffi/JavaUpCallsRFFIImpl.java      |   2 +-
 .../oracle/truffle/r/nodes/ffi/RFFIUtils.java |  26 +-
 ...IImpl.java => TracingUpCallsRFFIImpl.java} | 501 ++++--------------
 .../r/runtime/ffi/jni/JNIUpCallsRFFIImpl.java |  65 +++
 .../truffle/r/runtime/ffi/jni/JNI_Call.java   |   6 +-
 8 files changed, 211 insertions(+), 405 deletions(-)
 rename com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/{UpCallsRFFIImpl.java => TracingUpCallsRFFIImpl.java} (54%)
 create mode 100644 com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNIUpCallsRFFIImpl.java

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 225e41a48e..7091886c83 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
@@ -136,6 +136,7 @@ static jmethodID Rf_ncolsMethodID;
 
 static jclass CharSXPWrapperClass;
 static jfieldID CharSXPWrapperContentsFieldID;
+jclass JNIUpCallsRFFIImplClass;
 
 jmethodID setCompleteMethodID;
 
@@ -210,7 +211,6 @@ void init_internals(JNIEnv *env) {
 	OBJECT_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "OBJECT", "(Ljava/lang/Object;)I", 0);
 	DUPLICATE_ATTRIB_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "DUPLICATE_ATTRIB", "(Ljava/lang/Object;Ljava/lang/Object;)V", 0);
 	IS_S4_OBJECTMethodID = checkGetMethodID(env, UpCallsRFFIClass, "IS_S4_OBJECT", "(Ljava/lang/Object;)I", 0);
-	logNotCharSXPWrapperMethodID = checkGetMethodID(env, UpCallsRFFIClass, "logNotCharSXPWrapper", "(Ljava/lang/Object;)V", 0);
 	R_tryEvalMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_tryEval", "(Ljava/lang/Object;Ljava/lang/Object;Z)Ljava/lang/Object;", 0);
 	RDEBUGMethodID = checkGetMethodID(env, UpCallsRFFIClass, "RDEBUG", "(Ljava/lang/Object;)I", 0);
 	SET_RDEBUGMethodID = checkGetMethodID(env, UpCallsRFFIClass, "SET_RDEBUG", "(Ljava/lang/Object;I)V", 0);
@@ -225,7 +225,6 @@ void init_internals(JNIEnv *env) {
 	PRCODEMethodID = checkGetMethodID(env, UpCallsRFFIClass, "PRCODE", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
 
 	R_ToplevelExecMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_ToplevelExec", "()Ljava/lang/Object;", 0);
-	restoreHandlerStacksMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_ToplevelExecRestoreErrorHandlerStacks", "(Ljava/lang/Object;)V", 0);
 
 	R_MakeExternalPtrMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_MakeExternalPtr", "(JLjava/lang/Object;Ljava/lang/Object;)Lcom/oracle/truffle/r/runtime/data/RExternalPtr;", 0);
 	R_ExternalPtrAddrMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_ExternalPtrAddr", "(Ljava/lang/Object;)J", 0);
@@ -244,7 +243,11 @@ void init_internals(JNIEnv *env) {
     Rf_nrowsMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_nrows", "(Ljava/lang/Object;)I", 0);
     Rf_ncolsMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_ncols", "(Ljava/lang/Object;)I", 0);
 
-    setCompleteMethodID = checkGetMethodID(env, UpCallsRFFIClass, "setComplete", "(Ljava/lang/Object;Z)V", 0);
+    // static JNI-specific methods
+	JNIUpCallsRFFIImplClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/jni/JNIUpCallsRFFIImpl");
+	logNotCharSXPWrapperMethodID = checkGetMethodID(env, UpCallsRFFIClass, "logNotCharSXPWrapper", "(Ljava/lang/Object;)V", 1);
+	restoreHandlerStacksMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_ToplevelExecRestoreErrorHandlerStacks", "(Ljava/lang/Object;)V", 1);
+    setCompleteMethodID = checkGetMethodID(env, UpCallsRFFIClass, "setComplete", "(Ljava/lang/Object;Z)V", 1);
 }
 
 static jstring stringFromCharSXP(JNIEnv *thisenv, SEXP charsxp) {
@@ -252,7 +255,7 @@ static jstring stringFromCharSXP(JNIEnv *thisenv, SEXP charsxp) {
 	validateRef(thisenv, charsxp, "stringFromCharSXP");
 	if (!(*thisenv)->IsInstanceOf(thisenv, charsxp, CharSXPWrapperClass)) {
 
-	    (*thisenv)->CallVoidMethod(thisenv, UpCallsRFFIObject, logNotCharSXPWrapperMethodID, charsxp);
+	    (*thisenv)->CallStaticVoidMethod(thisenv, JNIUpCallsRFFIImplClass, logNotCharSXPWrapperMethodID, charsxp);
 	    fatalError("only CharSXPWrapper expected in stringFromCharSXP");
 	}
 #endif
@@ -1391,7 +1394,7 @@ Rboolean R_ToplevelExec(void (*fun)(void *), void *data) {
 	JNIEnv *env = getEnv();
 	jobject handlerStacks = (*env)->CallObjectMethod(env, UpCallsRFFIObject, R_ToplevelExecMethodID);
 	fun(data);
-	(*env)->CallVoidMethod(env, UpCallsRFFIObject, restoreHandlerStacksMethodID, handlerStacks);
+	(*env)->CallStaticVoidMethod(env, JNIUpCallsRFFIImplClass, restoreHandlerStacksMethodID, handlerStacks);
 	// TODO how do we detect error
 	return TRUE;
 }
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 2ab54e4fda..bf170af25d 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c
@@ -332,7 +332,7 @@ static void releaseNativeArray(JNIEnv *env, int i, int freedata) {
 			fatalError("releaseNativeArray type");
 		}
 		// update complete status
-		(*env)->CallVoidMethod(env, UpCallsRFFIObject, setCompleteMethodID, cv.obj, complete);
+		(*env)->CallStaticVoidMethod(env, JNIUpCallsRFFIImplClass, setCompleteMethodID, cv.obj, complete);
 
         if (freedata) {
             // free up the slot
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 99732f9376..6ed346d211 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h
+++ b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h
@@ -91,6 +91,7 @@ void setEmbedded(void);
 void setTempDir(JNIEnv *, jstring tempDir);
 
 extern jclass UpCallsRFFIClass;
+extern jclass JNIUpCallsRFFIImplClass;
 extern jobject UpCallsRFFIObject;
 extern FILE *traceFile;
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/JavaUpCallsRFFIImpl.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/JavaUpCallsRFFIImpl.java
index 4aa1e8d9dc..03d4150564 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/JavaUpCallsRFFIImpl.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/JavaUpCallsRFFIImpl.java
@@ -105,7 +105,7 @@ import com.oracle.truffle.r.runtime.rng.RRNG;
  * is desirable. In some cases it may be possible to "implement" the functions in R (which is a
  * simple way to achieve the above).
  */
-public class JavaUpCallsRFFIImpl implements UpCallsRFFI {
+public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
 
     // Checkstyle: stop method name check
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUtils.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUtils.java
index 6cda0147f1..f98624c494 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUtils.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUtils.java
@@ -34,6 +34,7 @@ import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
+import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI;
 
 /**
  * Mostly support for tracing R FFI up/down calls. Currently tracing of the arguments to calls is
@@ -46,7 +47,6 @@ import com.oracle.truffle.r.runtime.data.RTypedValue;
  *
  */
 public class RFFIUtils {
-    private static boolean initialized;
     /**
      * Set this to {@code true} when it is not possible to set {@link FastROptions}.
      */
@@ -66,16 +66,24 @@ public class RFFIUtils {
      */
     private static int depth;
 
-    public static void initialize() {
-        if (!initialized) {
-            traceEnabled = alwaysTrace || FastROptions.TraceNativeCalls.getBooleanValue();
-            if (traceEnabled) {
-                if (traceStream == null) {
-                    initTraceStream();
-                }
+    /**
+     * Handles the initialization of the RFFI downcalls/upcall implementation.
+     *
+     * @param upCallsRFFIImpl the concrete, implementation-specific variant of {@link UpCallsRFFI}.
+     * @return if tracing is enabled an instance of {@link TracingUpCallsRFFIImpl} that wraps
+     *         {@code upCallsRFFIImpl} else {@code upCallsRFFIImpl}.
+     */
+    public static UpCallsRFFI initialize(UpCallsRFFI upCallsRFFIImpl) {
+        UpCallsRFFI returnUpCallsRFFIImpl = upCallsRFFIImpl;
+        traceEnabled = alwaysTrace || FastROptions.TraceNativeCalls.getBooleanValue();
+        if (traceEnabled) {
+            if (traceStream == null) {
+                initTraceStream();
             }
-            initialized = true;
+            returnUpCallsRFFIImpl = new TracingUpCallsRFFIImpl(upCallsRFFIImpl);
         }
+        FFIUpCallRootNode.register();
+        return returnUpCallsRFFIImpl;
     }
 
     private static void initTraceStream() {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/UpCallsRFFIImpl.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/TracingUpCallsRFFIImpl.java
similarity index 54%
rename from com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/UpCallsRFFIImpl.java
rename to com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/TracingUpCallsRFFIImpl.java
index f0efb66260..1d5385bf2d 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/UpCallsRFFIImpl.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/TracingUpCallsRFFIImpl.java
@@ -22,974 +22,705 @@
  */
 package com.oracle.truffle.r.nodes.ffi;
 
-import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.guaranteeInstanceOf;
-
-import com.oracle.truffle.r.runtime.RErrorHandling;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.data.RStringVector;
-import com.oracle.truffle.r.runtime.data.RVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
-import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper;
 import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI;
 
-public final class UpCallsRFFIImpl implements UpCallsRFFI {
+final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
     // Checkstyle: stop method name check
 
     private final UpCallsRFFI delegate;
-    private final boolean tracing;
 
-    public UpCallsRFFIImpl(UpCallsRFFI delegate) {
+    public TracingUpCallsRFFIImpl(UpCallsRFFI delegate) {
         this.delegate = delegate;
-        FFIUpCallRootNode.register();
-        tracing = RFFIUtils.traceEnabled();
     }
 
     @Override
     public RIntVector Rf_ScalarInteger(int value) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_ScalarInteger", value);
-        }
+        RFFIUtils.traceUpCall("Rf_ScalarInteger", value);
         return delegate.Rf_ScalarInteger(value);
     }
 
     @Override
     public RLogicalVector Rf_ScalarLogical(int value) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_ScalarLogical", value);
-        }
+        RFFIUtils.traceUpCall("Rf_ScalarLogical", value);
         return delegate.Rf_ScalarLogical(value);
     }
 
     @Override
     public RDoubleVector Rf_ScalarDouble(double value) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_ScalarDouble", value);
-        }
+        RFFIUtils.traceUpCall("Rf_ScalarDouble", value);
         return delegate.Rf_ScalarDouble(value);
     }
 
     @Override
     public RStringVector Rf_ScalarString(Object value) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_ScalarString", value);
-        }
+        RFFIUtils.traceUpCall("Rf_ScalarString", value);
         return delegate.Rf_ScalarString(value);
     }
 
     @Override
     public int Rf_asInteger(Object x) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_asInteger", x);
-        }
+        RFFIUtils.traceUpCall("Rf_asInteger", x);
         return delegate.Rf_asInteger(x);
     }
 
     @Override
     public double Rf_asReal(Object x) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_asReal", x);
-        }
+        RFFIUtils.traceUpCall("Rf_asReal", x);
         return delegate.Rf_asReal(x);
     }
 
     @Override
     public int Rf_asLogical(Object x) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_asLogical", x);
-        }
+        RFFIUtils.traceUpCall("Rf_asLogical", x);
         return delegate.Rf_asLogical(x);
     }
 
     @Override
     public Object Rf_asChar(Object x) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_asChar", x);
-        }
+        RFFIUtils.traceUpCall("Rf_asChar", x);
         return delegate.Rf_asChar(x);
     }
 
     @Override
     public Object Rf_mkCharLenCE(Object bytes, int len, int encoding) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_mkCharLenCE", bytes);
-        }
+        RFFIUtils.traceUpCall("Rf_mkCharLenCE", bytes);
         return delegate.Rf_mkCharLenCE(bytes, len, encoding);
     }
 
     @Override
     public Object Rf_cons(Object car, Object cdr) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_cons", car, cdr);
-        }
+        RFFIUtils.traceUpCall("Rf_cons", car, cdr);
         return delegate.Rf_cons(car, cdr);
     }
 
     @Override
     public void Rf_defineVar(Object symbolArg, Object value, Object envArg) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_defineVar", symbolArg, value, envArg);
-        }
+        RFFIUtils.traceUpCall("Rf_defineVar", symbolArg, value, envArg);
         delegate.Rf_defineVar(symbolArg, value, envArg);
     }
 
     @Override
     public Object R_do_MAKE_CLASS(Object clazz) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_do_MAKE_CLASS", clazz);
-        }
+        RFFIUtils.traceUpCall("R_do_MAKE_CLASS", clazz);
         return delegate.R_do_MAKE_CLASS(clazz);
     }
 
     @Override
     public Object Rf_findVar(Object symbolArg, Object envArg) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_findVar", symbolArg, envArg);
-        }
+        RFFIUtils.traceUpCall("Rf_findVar", symbolArg, envArg);
         return delegate.Rf_findVar(symbolArg, envArg);
     }
 
     @Override
     public Object Rf_findVarInFrame(Object envArg, Object symbolArg) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_findVarInFrame", envArg, symbolArg);
-        }
+        RFFIUtils.traceUpCall("Rf_findVarInFrame", envArg, symbolArg);
         return delegate.Rf_findVarInFrame(envArg, symbolArg);
     }
 
     @Override
     public Object Rf_findVarInFrame3(Object envArg, Object symbolArg, int doGet) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_findVarInFrame3", envArg, symbolArg);
-        }
+        RFFIUtils.traceUpCall("Rf_findVarInFrame3", envArg, symbolArg);
         return delegate.Rf_findVarInFrame3(envArg, symbolArg, doGet);
     }
 
     @Override
     public Object Rf_getAttrib(Object obj, Object name) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_getAttrib", obj, name);
-        }
+        RFFIUtils.traceUpCall("Rf_getAttrib", obj, name);
         return delegate.Rf_getAttrib(obj, name);
     }
 
     @Override
     public void Rf_setAttrib(Object obj, Object name, Object val) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_setAttrib", obj, name, val);
-        }
+        RFFIUtils.traceUpCall("Rf_setAttrib", obj, name, val);
         delegate.Rf_setAttrib(obj, name, val);
     }
 
     @Override
     public int Rf_inherits(Object x, Object clazz) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_inherits", x, clazz);
-        }
+        RFFIUtils.traceUpCall("Rf_inherits", x, clazz);
         return delegate.Rf_inherits(x, clazz);
     }
 
     @Override
     public Object Rf_install(Object name) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_install", name);
-        }
+        RFFIUtils.traceUpCall("Rf_install", name);
         return delegate.Rf_install(name);
     }
 
     @Override
     public Object Rf_lengthgets(Object x, int newSize) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_lengthgets", x, newSize);
-        }
+        RFFIUtils.traceUpCall("Rf_lengthgets", x, newSize);
         return delegate.Rf_lengthgets(x, newSize);
     }
 
     @Override
     public int Rf_isString(Object x) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_isString", x);
-        }
+        RFFIUtils.traceUpCall("Rf_isString", x);
         return delegate.Rf_isString(x);
     }
 
     @Override
     public int Rf_isNull(Object x) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_isNull", x);
-        }
+        RFFIUtils.traceUpCall("Rf_isNull", x);
         return delegate.Rf_isNull(x);
     }
 
     @Override
     public Object Rf_PairToVectorList(Object x) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_PairToVectorList", x);
-        }
+        RFFIUtils.traceUpCall("Rf_PairToVectorList", x);
         return delegate.Rf_PairToVectorList(x);
     }
 
     @Override
     public void Rf_error(Object msg) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_error", msg);
-        }
+        RFFIUtils.traceUpCall("Rf_error", msg);
         delegate.Rf_error(msg);
     }
 
     @Override
     public void Rf_warning(Object msg) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_warning", msg);
-        }
+        RFFIUtils.traceUpCall("Rf_warning", msg);
         delegate.Rf_warning(msg);
     }
 
     @Override
     public void Rf_warningcall(Object call, Object msg) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_warningcall", call, msg);
-        }
+        RFFIUtils.traceUpCall("Rf_warningcall", call, msg);
         delegate.Rf_warningcall(call, msg);
     }
 
     @Override
     public Object Rf_allocateVector(int mode, int n) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_allocateVector", mode, n);
-        }
+        RFFIUtils.traceUpCall("Rf_allocateVector", mode, n);
         return delegate.Rf_allocateVector(mode, n);
     }
 
     @Override
     public Object Rf_allocateArray(int mode, Object dimsObj) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_allocateArray", mode, dimsObj);
-        }
+        RFFIUtils.traceUpCall("Rf_allocateArray", mode, dimsObj);
         return null;
     }
 
     @Override
     public Object Rf_allocateMatrix(int mode, int nrow, int ncol) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_allocateMatrix", mode, ncol, nrow);
-        }
+        RFFIUtils.traceUpCall("Rf_allocateMatrix", mode, ncol, nrow);
         return delegate.Rf_allocateMatrix(mode, nrow, ncol);
     }
 
     @Override
     public int Rf_nrows(Object x) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_nrows", x);
-        }
+        RFFIUtils.traceUpCall("Rf_nrows", x);
         return delegate.Rf_nrows(x);
     }
 
     @Override
     public int Rf_ncols(Object x) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_ncols", x);
-        }
+        RFFIUtils.traceUpCall("Rf_ncols", x);
         return delegate.Rf_ncols(x);
     }
 
     @Override
     public int LENGTH(Object x) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("LENGTH", x);
-        }
+        RFFIUtils.traceUpCall("LENGTH", x);
         return delegate.LENGTH(x);
     }
 
     @Override
     public void SET_STRING_ELT(Object x, int i, Object v) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("SET_STRING_ELT", x, i, v);
-        }
+        RFFIUtils.traceUpCall("SET_STRING_ELT", x, i, v);
         delegate.SET_STRING_ELT(x, i, v);
     }
 
     @Override
     public void SET_VECTOR_ELT(Object x, int i, Object v) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("SET_VECTOR_ELT", i, v);
-        }
+        RFFIUtils.traceUpCall("SET_VECTOR_ELT", i, v);
         delegate.SET_VECTOR_ELT(x, i, v);
     }
 
     @Override
     public Object RAW(Object x) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("RAW", x);
-        }
+        RFFIUtils.traceUpCall("RAW", x);
         return delegate.RAW(x);
     }
 
     @Override
     public Object LOGICAL(Object x) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("LOGICAL", x);
-        }
+        RFFIUtils.traceUpCall("LOGICAL", x);
         return delegate.LOGICAL(x);
     }
 
     @Override
     public Object INTEGER(Object x) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("INTEGER", x);
-        }
+        RFFIUtils.traceUpCall("INTEGER", x);
         return delegate.INTEGER(x);
     }
 
     @Override
     public Object REAL(Object x) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("REAL", x);
-        }
+        RFFIUtils.traceUpCall("REAL", x);
         return delegate.REAL(x);
     }
 
     @Override
     public Object STRING_ELT(Object x, int i) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("STRING_ELT", x, i);
-        }
+        RFFIUtils.traceUpCall("STRING_ELT", x, i);
         return delegate.STRING_ELT(x, i);
     }
 
     @Override
     public Object VECTOR_ELT(Object x, int i) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("VECTOR_ELT", x, i);
-        }
+        RFFIUtils.traceUpCall("VECTOR_ELT", x, i);
         return delegate.VECTOR_ELT(x, i);
     }
 
     @Override
     public int NAMED(Object x) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("NAMED", x);
-        }
+        RFFIUtils.traceUpCall("NAMED", x);
         return delegate.NAMED(x);
     }
 
     @Override
     public Object SET_TYPEOF_FASTR(Object x, int v) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("SET_TYPEOF_FASTR", x, v);
-        }
+        RFFIUtils.traceUpCall("SET_TYPEOF_FASTR", x, v);
         return delegate.SET_TYPEOF_FASTR(x, v);
     }
 
     @Override
     public int TYPEOF(Object x) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("TYPEOF", x);
-        }
+        RFFIUtils.traceUpCall("TYPEOF", x);
         return delegate.TYPEOF(x);
     }
 
     @Override
     public int OBJECT(Object x) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("OBJECT", x);
-        }
+        RFFIUtils.traceUpCall("OBJECT", x);
         return delegate.OBJECT(x);
     }
 
     @Override
     public Object Rf_duplicate(Object x, int deep) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_duplicate", x, deep);
-        }
+        RFFIUtils.traceUpCall("Rf_duplicate", x, deep);
         return delegate.Rf_duplicate(x, deep);
     }
 
     @Override
     public int Rf_anyDuplicated(Object x, int fromLast) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_anyDuplicated", x, fromLast);
-        }
+        RFFIUtils.traceUpCall("Rf_anyDuplicated", x, fromLast);
         return delegate.Rf_anyDuplicated(x, fromLast);
     }
 
     @Override
     public Object PRINTNAME(Object x) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("PRINTNAME", x);
-        }
+        RFFIUtils.traceUpCall("PRINTNAME", x);
         return delegate.PRINTNAME(x);
     }
 
     @Override
     public Object TAG(Object e) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("TAG", e);
-        }
+        RFFIUtils.traceUpCall("TAG", e);
         return delegate.TAG(e);
     }
 
     @Override
     public Object CAR(Object e) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("CAR", e);
-        }
+        RFFIUtils.traceUpCall("CAR", e);
         return delegate.CAR(e);
     }
 
     @Override
     public Object CDR(Object e) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("CDR", e);
-        }
+        RFFIUtils.traceUpCall("CDR", e);
         return delegate.CDR(e);
     }
 
     @Override
     public Object CADR(Object e) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("CADR", e);
-        }
+        RFFIUtils.traceUpCall("CADR", e);
         return delegate.CADR(e);
     }
 
     @Override
     public Object CADDR(Object e) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("CADDR", e);
-        }
+        RFFIUtils.traceUpCall("CADDR", e);
         return delegate.CADDR(e);
     }
 
     @Override
     public Object CDDR(Object e) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("CDDR", e);
-        }
+        RFFIUtils.traceUpCall("CDDR", e);
         return delegate.CDDR(e);
     }
 
     @Override
     public Object SET_TAG(Object x, Object y) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("SET_TAG", x, y);
-        }
+        RFFIUtils.traceUpCall("SET_TAG", x, y);
         return delegate.SET_TAG(x, y);
     }
 
     @Override
     public Object SETCAR(Object x, Object y) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("SETCAR", x, y);
-        }
+        RFFIUtils.traceUpCall("SETCAR", x, y);
         return delegate.SETCAR(x, y);
     }
 
     @Override
     public Object SETCDR(Object x, Object y) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("SETCDR", x, y);
-        }
+        RFFIUtils.traceUpCall("SETCDR", x, y);
         return delegate.SETCDR(x, y);
     }
 
     @Override
     public Object SETCADR(Object x, Object y) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("SETCADR", x);
-        }
+        RFFIUtils.traceUpCall("SETCADR", x);
         return delegate.SETCADR(x, y);
     }
 
     @Override
     public Object SYMVALUE(Object x) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("SYMVALUE", x);
-        }
+        RFFIUtils.traceUpCall("SYMVALUE", x);
         return delegate.SYMVALUE(x);
     }
 
     @Override
     public void SET_SYMVALUE(Object x, Object v) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("SET_SYMVALUE", x, v);
-        }
+        RFFIUtils.traceUpCall("SET_SYMVALUE", x, v);
         delegate.SET_SYMVALUE(x, v);
     }
 
     @Override
     public int R_BindingIsLocked(Object sym, Object env) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_BindingIsLocked", sym, env);
-        }
+        RFFIUtils.traceUpCall("R_BindingIsLocked", sym, env);
         return delegate.R_BindingIsLocked(sym, env);
     }
 
     @Override
     public Object R_FindNamespace(Object name) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_FindNamespace", name);
-        }
+        RFFIUtils.traceUpCall("R_FindNamespace", name);
         return delegate.R_FindNamespace(name);
     }
 
     @Override
     public Object Rf_eval(Object expr, Object env) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_eval", expr, env);
-        }
+        RFFIUtils.traceUpCall("Rf_eval", expr, env);
         return delegate.Rf_eval(expr, env);
     }
 
     @Override
     public Object Rf_findfun(Object symbolObj, Object envObj) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_findfun", symbolObj, envObj);
-        }
+        RFFIUtils.traceUpCall("Rf_findfun", symbolObj, envObj);
         return delegate.Rf_findfun(symbolObj, envObj);
     }
 
     @Override
     public Object Rf_GetOption1(Object tag) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_GetOption1", tag);
-        }
+        RFFIUtils.traceUpCall("Rf_GetOption1", tag);
         return delegate.Rf_GetOption1(tag);
     }
 
     @Override
     public void Rf_gsetVar(Object symbol, Object value, Object rho) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_gsetVar", symbol, value, rho);
-        }
+        RFFIUtils.traceUpCall("Rf_gsetVar", symbol, value, rho);
         delegate.Rf_gsetVar(symbol, value, rho);
     }
 
     @Override
     public void DUPLICATE_ATTRIB(Object to, Object from) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("DUPLICATE_ATTRIB", to, from);
-        }
+        RFFIUtils.traceUpCall("DUPLICATE_ATTRIB", to, from);
         delegate.DUPLICATE_ATTRIB(to, from);
     }
 
     @Override
     public int R_computeIdentical(Object x, Object y, int flags) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_computeIdentical", x, y, flags);
-        }
+        RFFIUtils.traceUpCall("R_computeIdentical", x, y, flags);
         return delegate.R_computeIdentical(x, y, flags);
     }
 
     @Override
     public void Rf_copyListMatrix(Object s, Object t, int byrow) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_copyListMatrix", t, byrow);
-        }
+        RFFIUtils.traceUpCall("Rf_copyListMatrix", t, byrow);
         delegate.Rf_copyListMatrix(s, t, byrow);
     }
 
     @Override
     public void Rf_copyMatrix(Object s, Object t, int byrow) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_copyMatrix", t, byrow);
-        }
+        RFFIUtils.traceUpCall("Rf_copyMatrix", t, byrow);
         delegate.Rf_copyMatrix(s, t, byrow);
     }
 
     @Override
     public Object R_tryEval(Object expr, Object env, boolean silent) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_tryEval", expr, env, silent);
-        }
+        RFFIUtils.traceUpCall("R_tryEval", expr, env, silent);
         return delegate.R_tryEval(expr, env, silent);
     }
 
     @Override
     public Object R_ToplevelExec() {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_TopLevelExec");
-        }
+        RFFIUtils.traceUpCall("R_TopLevelExec");
         return delegate.R_ToplevelExec();
     }
 
     @Override
     public int RDEBUG(Object x) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("RDEBUG", x);
-        }
+        RFFIUtils.traceUpCall("RDEBUG", x);
         return delegate.RDEBUG(x);
     }
 
     @Override
     public void SET_RDEBUG(Object x, int v) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("SET_RDEBUG", x, v);
-        }
+        RFFIUtils.traceUpCall("SET_RDEBUG", x, v);
         delegate.SET_RDEBUG(x, v);
     }
 
     @Override
     public int RSTEP(Object x) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("RSTEP", x);
-        }
+        RFFIUtils.traceUpCall("RSTEP", x);
         return delegate.RSTEP(x);
     }
 
     @Override
     public void SET_RSTEP(Object x, int v) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("SET_RSTEP", x, v);
-        }
+        RFFIUtils.traceUpCall("SET_RSTEP", x, v);
         delegate.SET_RSTEP(x, v);
     }
 
     @Override
     public Object ENCLOS(Object x) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("ENCLOS", x);
-        }
+        RFFIUtils.traceUpCall("ENCLOS", x);
         return delegate.ENCLOS(x);
     }
 
     @Override
     public Object PRVALUE(Object x) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("PRVALUE", x);
-        }
+        RFFIUtils.traceUpCall("PRVALUE", x);
         return delegate.PRVALUE(x);
     }
 
     @Override
     public Object R_ParseVector(Object text, int n, Object srcFile) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_ParseVector", text, n, srcFile);
-        }
+        RFFIUtils.traceUpCall("R_ParseVector", text, n, srcFile);
         return delegate.R_ParseVector(text, n, srcFile);
     }
 
     @Override
     public Object R_lsInternal3(Object envArg, int allArg, int sortedArg) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_lsInternal3", envArg, allArg, sortedArg);
-        }
+        RFFIUtils.traceUpCall("R_lsInternal3", envArg, allArg, sortedArg);
         return delegate.R_lsInternal3(envArg, allArg, sortedArg);
     }
 
     @Override
     public String R_HomeDir() {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_HomeDir");
-        }
+        RFFIUtils.traceUpCall("R_HomeDir");
         return delegate.R_HomeDir();
     }
 
     @Override
     public void R_CleanUp(int sa, int status, int runlast) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_Cleanup", sa, status, runlast);
-        }
+        RFFIUtils.traceUpCall("R_Cleanup", sa, status, runlast);
         delegate.R_CleanUp(sa, status, runlast);
     }
 
     @Override
     public Object R_GlobalContext() {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_GlobalContext");
-        }
+        RFFIUtils.traceUpCall("R_GlobalContext");
         return delegate.R_GlobalContext();
     }
 
     @Override
     public Object R_GlobalEnv() {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_GlobalEnv");
-        }
+        RFFIUtils.traceUpCall("R_GlobalEnv");
         return delegate.R_GlobalEnv();
     }
 
     @Override
     public Object R_BaseEnv() {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_BaseEnv");
-        }
+        RFFIUtils.traceUpCall("R_BaseEnv");
         return delegate.R_BaseEnv();
     }
 
     @Override
     public Object R_BaseNamespace() {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_BaseNamespace");
-        }
+        RFFIUtils.traceUpCall("R_BaseNamespace");
         return delegate.R_BaseNamespace();
     }
 
     @Override
     public Object R_NamespaceRegistry() {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_NamespaceRegistry");
-        }
+        RFFIUtils.traceUpCall("R_NamespaceRegistry");
         return delegate.R_NamespaceRegistry();
     }
 
     @Override
     public int R_Interactive() {
-        if (tracing) {
-            RFFIUtils.traceUpCall("isInteractive");
-        }
+        RFFIUtils.traceUpCall("isInteractive");
         return delegate.R_Interactive();
     }
 
     @Override
     public int IS_S4_OBJECT(Object x) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("isS4Object");
-        }
+        RFFIUtils.traceUpCall("isS4Object");
         return delegate.IS_S4_OBJECT(x);
     }
 
     @Override
     public void Rprintf(Object message) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rprintf", message);
-        }
+        RFFIUtils.traceUpCall("Rprintf", message);
         delegate.Rprintf(message);
     }
 
     @Override
     public void GetRNGstate() {
-        if (tracing) {
-            RFFIUtils.traceUpCall("GetRNGstate");
-        }
+        RFFIUtils.traceUpCall("GetRNGstate");
         delegate.GetRNGstate();
     }
 
     @Override
     public void PutRNGstate() {
-        if (tracing) {
-            RFFIUtils.traceUpCall("PutRNGstate");
-        }
+        RFFIUtils.traceUpCall("PutRNGstate");
         delegate.PutRNGstate();
     }
 
     @Override
     public double unif_rand() {
-        if (tracing) {
-            RFFIUtils.traceUpCall("unif_rand");
-        }
+        RFFIUtils.traceUpCall("unif_rand");
         return delegate.unif_rand();
     }
 
     @Override
     public Object R_getGlobalFunctionContext() {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_getGlobalFunctionContext");
-        }
+        RFFIUtils.traceUpCall("R_getGlobalFunctionContext");
         return delegate.R_getGlobalFunctionContext();
     }
 
     @Override
     public Object R_getParentFunctionContext(Object c) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_getParentFunctionContext");
-        }
+        RFFIUtils.traceUpCall("R_getParentFunctionContext");
         return delegate.R_getParentFunctionContext(c);
     }
 
     @Override
     public Object R_getContextEnv(Object c) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_getContextEnv", c);
-        }
+        RFFIUtils.traceUpCall("R_getContextEnv", c);
         return delegate.R_getContextEnv(c);
     }
 
     @Override
     public Object R_getContextFun(Object c) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_getContextFun", c);
-        }
+        RFFIUtils.traceUpCall("R_getContextFun", c);
         return delegate.R_getContextFun(c);
     }
 
     @Override
     public Object R_getContextCall(Object c) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_getContextCall", c);
-        }
+        RFFIUtils.traceUpCall("R_getContextCall", c);
         return delegate.R_getContextCall(c);
     }
 
     @Override
     public Object R_getContextSrcRef(Object c) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_getContextSrcRef", c);
-        }
+        RFFIUtils.traceUpCall("R_getContextSrcRef", c);
         return delegate.R_getContextSrcRef(c);
     }
 
     @Override
     public int R_insideBrowser() {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_insideBrowser");
-        }
+        RFFIUtils.traceUpCall("R_insideBrowser");
         return delegate.R_insideBrowser();
     }
 
     @Override
     public int R_isGlobal(Object c) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_isGlobal", c);
-        }
+        RFFIUtils.traceUpCall("R_isGlobal", c);
         return delegate.R_isGlobal(c);
     }
 
     @Override
     public int R_isEqual(Object x, Object y) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("isEqual", x, y);
-        }
+        RFFIUtils.traceUpCall("isEqual", x, y);
         return delegate.R_isEqual(x, y);
     }
 
     @Override
     public Object Rf_classgets(Object x, Object y) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("Rf_classgets", x, y);
-        }
+        RFFIUtils.traceUpCall("Rf_classgets", x, y);
         return delegate.Rf_classgets(x, y);
     }
 
     @Override
     public RExternalPtr R_MakeExternalPtr(long addr, Object tag, Object prot) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_MakeExternalPtr", addr, tag, prot);
-        }
+        RFFIUtils.traceUpCall("R_MakeExternalPtr", addr, tag, prot);
         return delegate.R_MakeExternalPtr(addr, tag, prot);
     }
 
     @Override
     public long R_ExternalPtrAddr(Object x) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_ExternalPtrAddr", x);
-        }
+        RFFIUtils.traceUpCall("R_ExternalPtrAddr", x);
         return delegate.R_ExternalPtrAddr(x);
     }
 
     @Override
     public Object R_ExternalPtrTag(Object x) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_ExternalPtrTag", x);
-        }
+        RFFIUtils.traceUpCall("R_ExternalPtrTag", x);
         return delegate.R_ExternalPtrTag(x);
     }
 
     @Override
     public Object R_ExternalPtrProt(Object x) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_ExternalPtrProt", x);
-        }
+        RFFIUtils.traceUpCall("R_ExternalPtrProt", x);
         return delegate.R_ExternalPtrProt(x);
     }
 
     @Override
     public void R_SetExternalPtrAddr(Object x, long addr) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_SetExternalPtrAddr", x);
-        }
+        RFFIUtils.traceUpCall("R_SetExternalPtrAddr", x);
         delegate.R_SetExternalPtrAddr(x, addr);
     }
 
     @Override
     public void R_SetExternalPtrTag(Object x, Object tag) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_SetExternalPtrTag", x);
-        }
+        RFFIUtils.traceUpCall("R_SetExternalPtrTag", x);
         delegate.R_SetExternalPtrTag(x, tag);
     }
 
     @Override
     public void R_SetExternalPtrProt(Object x, Object prot) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_ExternalPtrProt", x);
-        }
+        RFFIUtils.traceUpCall("R_ExternalPtrProt", x);
         delegate.R_SetExternalPtrProt(x, prot);
     }
 
     @Override
     public REnvironment R_NewHashedEnv(REnvironment parent, int initialSize) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_NewHashedEnv", parent, initialSize);
-        }
+        RFFIUtils.traceUpCall("R_NewHashedEnv", parent, initialSize);
         return delegate.R_NewHashedEnv(parent, initialSize);
     }
 
     @Override
     public int PRSEEN(Object x) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("PRSEEN", x);
-        }
+        RFFIUtils.traceUpCall("PRSEEN", x);
         return delegate.PRSEEN(x);
     }
 
     @Override
     public Object PRENV(Object x) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("PRENV", x);
-        }
+        RFFIUtils.traceUpCall("PRENV", x);
         return delegate.PRENV(x);
     }
 
     @Override
     public Object R_PromiseExpr(Object x) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("R_PromiseExpr", x);
-        }
+        RFFIUtils.traceUpCall("R_PromiseExpr", x);
         return delegate.R_PromiseExpr(x);
     }
 
     @Override
     public Object PRCODE(Object x) {
-        if (tracing) {
-            RFFIUtils.traceUpCall("PRCODE", x);
-        }
+        RFFIUtils.traceUpCall("PRCODE", x);
         return delegate.PRCODE(x);
     }
 
-    // Implementation specific support
-
-    /**
-     * Helper function for {@code R_TopLevelExec}, see {@link #R_ToplevelExec()}, called after C
-     * function returns.
-     */
-    @SuppressWarnings("static-method")
-    public void R_ToplevelExecRestoreErrorHandlerStacks(Object stacks) {
-        RErrorHandling.HandlerStacks handlerStacks = guaranteeInstanceOf(stacks, RErrorHandling.HandlerStacks.class);
-        RErrorHandling.restoreHandlerStacks(handlerStacks);
-    }
-
-    /**
-     * Called to possibly update the "complete" status on {@code x}. N.B. {@code x} may not be an
-     * object with a concrete {@code setComplete} method, e.g. see {@link #INTEGER(Object)}.
-     */
-    @SuppressWarnings("static-method")
-    public void setComplete(Object x, boolean complete) {
-        // only care about concrete vectors
-        if (x instanceof RVector) {
-            ((RVector<?>) x).setComplete(complete);
-        }
-    }
-
-    /**
-     * Called when a {@link CharSXPWrapper} is expected and not found.
-     */
-    @SuppressWarnings("static-method")
-    public void logNotCharSXPWrapper(Object x) {
-        System.out.println("object " + x);
-        System.out.println("class " + x.getClass());
-    }
-
 }
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNIUpCallsRFFIImpl.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNIUpCallsRFFIImpl.java
new file mode 100644
index 0000000000..17087d2880
--- /dev/null
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNIUpCallsRFFIImpl.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.runtime.ffi.jni;
+
+import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.guaranteeInstanceOf;
+
+import com.oracle.truffle.r.nodes.ffi.JavaUpCallsRFFIImpl;
+import com.oracle.truffle.r.runtime.RErrorHandling;
+import com.oracle.truffle.r.runtime.data.RVector;
+import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper;
+
+/**
+ * Some additional methods to support the native JNI side.
+ */
+public final class JNIUpCallsRFFIImpl extends JavaUpCallsRFFIImpl {
+
+    /**
+     * Helper function for {@code R_TopLevelExec}, see {@link #R_ToplevelExec()}, called after C
+     * function returns.
+     */
+    public static void R_ToplevelExecRestoreErrorHandlerStacks(Object stacks) {
+        RErrorHandling.HandlerStacks handlerStacks = guaranteeInstanceOf(stacks, RErrorHandling.HandlerStacks.class);
+        RErrorHandling.restoreHandlerStacks(handlerStacks);
+    }
+
+    /**
+     * Called to possibly update the "complete" status on {@code x}. N.B. {@code x} may not be an
+     * object with a concrete {@code setComplete} method, e.g. see {@link #INTEGER(Object)}.
+     */
+    public static void setComplete(Object x, boolean complete) {
+        // only care about concrete vectors
+        if (x instanceof RVector) {
+            ((RVector<?>) x).setComplete(complete);
+        }
+    }
+
+    /**
+     * Called when a {@link CharSXPWrapper} is expected and not found.
+     */
+    public static void logNotCharSXPWrapper(Object x) {
+        System.out.println("object " + x);
+        System.out.println("class " + x.getClass());
+    }
+
+}
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java
index b766682261..f729327eba 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java
@@ -27,9 +27,7 @@ import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceDownCallReturn;
 import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceEnabled;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.r.nodes.ffi.JavaUpCallsRFFIImpl;
 import com.oracle.truffle.r.nodes.ffi.RFFIUtils;
-import com.oracle.truffle.r.nodes.ffi.UpCallsRFFIImpl;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.ffi.CallRFFI;
 import com.oracle.truffle.r.runtime.ffi.NativeCallInfo;
@@ -123,13 +121,13 @@ public class JNI_Call implements CallRFFI {
 
     @TruffleBoundary
     private static void initialize() {
-        RFFIUtils.initialize();
+        UpCallsRFFI upCallsRFFIImpl = RFFIUtils.initialize(new JNIUpCallsRFFIImpl());
 
         if (traceEnabled()) {
             traceDownCall("initialize");
         }
         try {
-            initialize(new UpCallsRFFIImpl(new JavaUpCallsRFFIImpl()), RFFIVariables.initialize());
+            initialize(upCallsRFFIImpl, RFFIVariables.initialize());
         } finally {
             if (traceEnabled()) {
                 traceDownCallReturn("initialize", null);
-- 
GitLab