diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_UpCallsRFFIImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_UpCallsRFFIImpl.java
index d5f87c515079f54d6310322924b28f21b450b839..bf5eeed417c045b2d985d2659a550f544863abca 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_UpCallsRFFIImpl.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_UpCallsRFFIImpl.java
@@ -45,12 +45,13 @@ import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.data.RUnboundValue;
 import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper;
 import com.oracle.truffle.r.runtime.ffi.RFFIVariables;
+import com.oracle.truffle.r.runtime.ffi.jni.JNIUpCallsRFFIImpl;
 
 /**
  * (Incomplete) Variant of {@link JavaUpCallsRFFIImpl} for Truffle LLVM.
  *
  */
-public class TruffleLLVM_UpCallsRFFIImpl extends JavaUpCallsRFFIImpl implements VariableUpCallsRFFI {
+public class TruffleLLVM_UpCallsRFFIImpl extends JNIUpCallsRFFIImpl implements VariableUpCallsRFFI {
     private static TruffleLLVM_UpCallsRFFIImpl singleton;
     private static TruffleObject singletonTruffleObject;
 
diff --git a/com.oracle.truffle.r.native/Makefile b/com.oracle.truffle.r.native/Makefile
index 2b59c073ff66292a1acdc7318c2385a98a9da7c5..37ea9afada6df6eab8e1cd5c66f064969d37200a 100644
--- a/com.oracle.truffle.r.native/Makefile
+++ b/com.oracle.truffle.r.native/Makefile
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+# 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
@@ -30,12 +30,17 @@ export FASTR_NATIVE_DIR = $(TOPDIR)
 export R_VERSION = $(subst R-,,$(notdir $(basename $(basename $(wildcard $(FASTR_R_HOME)/libdownloads/R-*.gz)))))
 export GNUR_HOME = $(TOPDIR)/gnur/R-$(R_VERSION)
 
-all: 
+# Completely accurate dependency analysis is very difficult for this project, so use a version number
+# to force a clean build, and elsewhere use sentinels to avoid rebuilding when we can't compute the 
+# dependencies accurately.
+
+all: checkversion
 	$(MAKE) -C gnur
 	$(MAKE) -C include
 	$(MAKE) -C fficall
 	$(MAKE) -C library
 	$(MAKE) -C run
+	cp version.source version.built
 
 clean: 
 	$(MAKE) -C include clean
@@ -44,3 +49,23 @@ clean:
 	$(MAKE) -C run clean
 	$(MAKE) -C gnur clean
 
+version.source := $(shell cat version.source)
+
+#$(info version: $(version.source))
+ifeq ($(wildcard version.built),)
+	doclean = 1
+else
+version.built := $(shell cat version.built)
+#$(info version.built: $(version.built))
+ifneq ($(version.source),$(version.built))
+	doclean = 1
+else
+	doclean = 0
+endif
+endif
+
+#$(info doclean: $(doclean))
+checkversion:
+ifeq ($(doclean),1)
+	$(MAKE) clean
+endif
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 225e41a48e016d01a5699e8aa925e32bffbb558c..7091886c83b2484cf70ea5cdeb3b899383dce97d 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 2ab54e4fda0141f22c8e2d6d34313e63cd8798d8..03118d01c25eaf42c879226e0dfadf0a4476489a 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -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 99732f93766987fdceb40035a84eacce6111d882..c86fc4bc15d69e15f9cb22bc70ced2a0d96676ad 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h
+++ b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -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.native/version.source b/com.oracle.truffle.r.native/version.source
new file mode 100644
index 0000000000000000000000000000000000000000..78c24caea0d6432c6894a971ae42532768cc80d4
--- /dev/null
+++ b/com.oracle.truffle.r.native/version.source
@@ -0,0 +1 @@
+2/10/17
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 4aa1e8d9dc89dc6398662e02dac477b57b5a7b03..03d4150564f5ef3ae2dc0cba1789216d2f4a935a 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/RFFIUpCallMethod.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
index fc354a931de72d93a2b997e4c3d9bf0011a529b5..dd28c59af3fe2185653105acfd503bfaf164d9c2 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
@@ -44,7 +44,10 @@ public enum RFFIUpCallMethod {
     LOGICAL("(object) : object"),
     NAMED("(object) : sint32"),
     OBJECT("(object) : sint32"),
+    PRCODE("(object) : object"),
+    PRENV("(object) : object"),
     PRINTNAME("(object) : object"),
+    PRSEEN("(object) : sint32"),
     PRVALUE("(object) : object"),
     PutRNGstate("() : void"),
     RAW("(object) : object"),
@@ -54,6 +57,7 @@ public enum RFFIUpCallMethod {
     R_BaseEnv("() : object"),
     R_BaseNamespace("() : object"),
     R_BindingIsLocked("(object, object) : sint32"),
+    R_CHAR("(object) : object"),
     R_CleanUp("(sint32, sint32, sint32) : void"),
     R_ExternalPtrAddr("(object) : object"),
     R_ExternalPtrProt("(object) : object"),
@@ -67,6 +71,7 @@ public enum RFFIUpCallMethod {
     R_NamespaceRegistry("() : object"),
     R_NewHashedEnv("(object, sint32) : object"),
     R_ParseVector("(object, sint32, object) : object"),
+    R_PromiseExpr("(object) : object"),
     R_SetExternalPtrAddr("(object, object) : void"),
     R_SetExternalPtrProt("(object, object) : void"),
     R_SetExternalPtrTag("(object, object) : void"),
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 6cda0147f1d4cb3b3a96c11ac7e8b66924e5072c..9b7df136add07eda78a75719536b4af2007874fd 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() {
@@ -141,7 +149,6 @@ public class RFFIUtils {
     }
 
     private static void traceCall(CallMode mode, String name, int depthValue, Object... args) {
-        assert initialized;
         if (traceEnabled) {
             StringBuffer sb = new StringBuffer();
             sb.append("CallRFFI[");
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 f0efb662604f09ce4ba0ff9836f5503e7b6681b5..31a6a88c7c7cfa52f87e69596fe31cb14e6ed07c 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,711 @@
  */
 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());
+    @Override
+    public Object R_CHAR(Object x) {
+        RFFIUtils.traceUpCall("R_CHAR", x);
+        return delegate.R_CHAR(x);
     }
 
 }
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 0000000000000000000000000000000000000000..233e055e8ed4414f744bc12200c1b25df822a6ae
--- /dev/null
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNIUpCallsRFFIImpl.java
@@ -0,0 +1,72 @@
+/*
+ * 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.RInternalError;
+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 class JNIUpCallsRFFIImpl extends JavaUpCallsRFFIImpl {
+    // Checkstyle: stop method name check
+
+    /**
+     * 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());
+    }
+
+    @Override
+    public Object R_CHAR(Object x) {
+        throw RInternalError.shouldNotReachHere();
+    }
+
+}
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 b766682261eb2c0da7e604ac025fdb10927dff39..f729327ebae99dc51f3e1a81c316acc35eb1d7ff 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);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/StdUpCallsRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/StdUpCallsRFFI.java
index 60a8de076bafa2a716962eb7a4ac8566957877da..e8b7a6294030c9e16d23c90328684fbe490c7686 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/StdUpCallsRFFI.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/StdUpCallsRFFI.java
@@ -248,4 +248,6 @@ public interface StdUpCallsRFFI {
 
     Object PRCODE(Object x);
 
+    Object R_CHAR(Object x);
+
 }