diff --git a/com.oracle.truffle.r.native/Makefile b/com.oracle.truffle.r.native/Makefile
index 0f209bf9e57b066c1072ed577eac1288d979e842..b56d8c118269f478873d72697f8fe47345bc71d6 100644
--- a/com.oracle.truffle.r.native/Makefile
+++ b/com.oracle.truffle.r.native/Makefile
@@ -33,14 +33,12 @@ export GNUR_HOME = $(TOPDIR)/gnur/R-$(R_VERSION)
 all: 
 	$(MAKE) -C gnur
 	$(MAKE) -C include
-	$(MAKE) -C osextras
 	$(MAKE) -C fficall
 	$(MAKE) -C library
 	$(MAKE) -C run
 
 clean: 
 	$(MAKE) -C include clean
-	$(MAKE) -C osextras clean
 	$(MAKE) -C fficall clean
 	$(MAKE) -C library clean
 	$(MAKE) -C run clean
diff --git a/com.oracle.truffle.r.native/fficall/Makefile b/com.oracle.truffle.r.native/fficall/Makefile
index d703990b4fcac05314bb58a934cc567f10c57e2e..6e549b23ededbd6393386514cad43dc803bd6648 100644
--- a/com.oracle.truffle.r.native/fficall/Makefile
+++ b/com.oracle.truffle.r.native/fficall/Makefile
@@ -33,8 +33,10 @@ endif
 
 .PHONY: all clean objs
 
-C_LIBNAME := libR$(DYLIB_EXT)
-C_LIB := $(FASTR_LIB_DIR)/$(C_LIBNAME)
+R_LIBNAME := libR$(DYLIB_EXT)
+R_LIB := $(FASTR_LIB_DIR)/$(R_LIBNAME)
+BOOTJNI_LIBNAME := libjniboot$(DYLIB_EXT)
+BOOTJNI_LIB := $(FASTR_LIB_DIR)/$(BOOTJNI_LIBNAME)
 
 ifeq ($(OS_NAME), Darwin)
 VERSION_FLAGS := -current_version $(R_VERSION) -compatibility_version $(R_VERSION)
@@ -42,20 +44,26 @@ endif
 
 BLAS_TARGET := $(FASTR_LIB_DIR)/libRblas$(DYLIB_EXT)
 
-all: $(C_LIB)
+all: $(R_LIB) $(BOOTJNI_LIB)
 
-$(C_LIB): objs 
-	$(DYLIB_LD) $(DYLIB_LDFLAGS) -o $(C_LIB) $(wildcard lib/*.o) -L $(GNUR_HOME)/lib -lRblas $(VERSION_FLAGS)
+$(R_LIB): objs 
+	$(DYLIB_LD) $(DYLIB_LDFLAGS) -o $(R_LIB) $(wildcard lib/*.o) -L $(GNUR_HOME)/lib -lRblas $(VERSION_FLAGS)
 ifeq ($(OS_NAME),Darwin)
-	install_name_tool -change libRblas.dylib $(BLAS_TARGET) $(C_LIB)
+	install_name_tool -change libRblas.dylib $(BLAS_TARGET) $(R_LIB)
 endif
 
 objs:
 	$(MAKE) -C src/common all
 	$(MAKE) -C src/jni all
 
+$(BOOTJNI_LIB): bootobjs
+	$(DYLIB_LD) $(DYLIB_LDFLAGS) -o $(BOOTJNI_LIB) src/jniboot/jniboot.o $(VERSION_FLAGS)
+
+bootobjs:
+	$(MAKE) -C src/jniboot all
+
 clean:
 	$(MAKE) -C src/common clean
 	$(MAKE) -C src/jni clean
-	rm -rf $(C_LIB)
+	rm -rf $(R_LIB)
 	
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Parse.c b/com.oracle.truffle.r.native/fficall/src/jni/Parse.c
index 4727c2cba093be8d04f683e06f42b17eec0eed15..cc55518f197af736df1fedfb4780aea80643c0c4 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Parse.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Parse.c
@@ -31,7 +31,7 @@ static jfieldID parseExprFieldID;
 
 void init_parse(JNIEnv *env) {
 	parseMethodID = checkGetMethodID(env, CallRFFIHelperClass, "R_ParseVector", "(Ljava/lang/Object;ILjava/lang/Object;)Ljava/lang/Object;", 1);
-	parseResultClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper$ParseResult");
+	parseResultClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/jni/CallRFFIHelper$ParseResult");
 	parseStatusFieldID = checkGetFieldID(env, parseResultClass, "parseStatus", "I", 0);
 	parseExprFieldID = checkGetFieldID(env, parseResultClass, "expr", "Ljava/lang/Object;", 0);
 }
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Rdynload_fastr.c b/com.oracle.truffle.r.native/fficall/src/jni/Rdynload_fastr.c
index f0b05fc5733fe75249d9b14e5aaf0f1a35465176..b86229a115ec850ed2d81b4533c2efdd51a16cb7 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Rdynload_fastr.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Rdynload_fastr.c
@@ -29,7 +29,7 @@ static jmethodID findSymbolID;
 
 void init_dynload(JNIEnv *env) {
     DLLClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/DLL");
-    JNI_PkgInitClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/jnr/JNI_PkgInit");
+    JNI_PkgInitClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/jni/JNI_PkgInit");
     DotSymbolClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/DLL$DotSymbol");
     RegisteredNativeSymbolClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/DLL$RegisteredNativeSymbol");
 
@@ -85,7 +85,7 @@ void R_RegisterCCallable(const char *package, const char *name, DL_FUNC fptr) {
 }
 
 JNIEXPORT jobject JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1PkgInit_setSymbol(JNIEnv *env, jclass c, jint nstOrd, jlong routinesAddr, jint index) {
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1PkgInit_setSymbol(JNIEnv *env, jclass c, jint nstOrd, jlong routinesAddr, jint index) {
 	const char *name;
 	long fun;
 	int numArgs;
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c b/com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c
index 9cc1084873df36694d21b388221de6315f029f61..f7cb4401f5891fd9cfbcf9802c9b52f91c3dc10c 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c
@@ -421,15 +421,15 @@ static void REmbed_nativeWriteConsole(JNIEnv *jniEnv, jclass c, jstring string,
 	callExit(jniEnv);
 }
 
-JNIEXPORT void JNICALL Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1REmbed_nativeWriteConsole(JNIEnv *jniEnv, jclass c, jstring string) {
+JNIEXPORT void JNICALL Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1REmbed_nativeWriteConsole(JNIEnv *jniEnv, jclass c, jstring string) {
 	REmbed_nativeWriteConsole(jniEnv, c, string, 0);
 }
 
-JNIEXPORT void JNICALL Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1REmbed_nativeWriteErrConsole(JNIEnv *jniEnv, jclass c, jstring string) {
+JNIEXPORT void JNICALL Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1REmbed_nativeWriteErrConsole(JNIEnv *jniEnv, jclass c, jstring string) {
 	REmbed_nativeWriteConsole(jniEnv, c, string, 1);
 }
 
-JNIEXPORT jstring JNICALL Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1REmbed_nativeReadConsole(JNIEnv *jniEnv, jclass c, jstring prompt) {
+JNIEXPORT jstring JNICALL Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1REmbed_nativeReadConsole(JNIEnv *jniEnv, jclass c, jstring prompt) {
 	jmp_buf error_jmpbuf;
 	jstring result = NULL;
 	callEnter(jniEnv, &error_jmpbuf);
@@ -444,7 +444,7 @@ JNIEXPORT jstring JNICALL Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1REmbed_
 	return result;
 }
 
-JNIEXPORT void JNICALL Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1REmbed_nativeCleanUp(JNIEnv *jniEnv, jclass c, jint x, jint y, jint z) {
+JNIEXPORT void JNICALL Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1REmbed_nativeCleanUp(JNIEnv *jniEnv, jclass c, jint x, jint y, jint z) {
 	jmp_buf error_jmpbuf;
 	callEnter(jniEnv, &error_jmpbuf);
 	if (!setjmp(error_jmpbuf)) {
@@ -453,7 +453,7 @@ JNIEXPORT void JNICALL Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1REmbed_nat
 	callExit(jniEnv);
 }
 
-JNIEXPORT void JNICALL Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1REmbed_nativeSuicide(JNIEnv *jniEnv, jclass c, jstring string) {
+JNIEXPORT void JNICALL Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1REmbed_nativeSuicide(JNIEnv *jniEnv, jclass c, jstring string) {
 	jmp_buf error_jmpbuf;
 	callEnter(jniEnv, &error_jmpbuf);
 	if (!setjmp(error_jmpbuf)) {
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 66b5983b0b7ede1dd757f41f42787582d4146622..a5c4ac637f69b5193a979f241931a08f918a5da4 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
@@ -219,7 +219,7 @@ void init_internals(JNIEnv *env) {
 	externalPtrSetTagMethodID = checkGetMethodID(env, RExternalPtrClass, "setTag", "(Ljava/lang/Object;)V", 0);
 	externalPtrSetProtMethodID = checkGetMethodID(env, RExternalPtrClass, "setProt", "(Ljava/lang/Object;)V", 0);
 
-	CharSXPWrapperClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper$CharSXPWrapper");
+	CharSXPWrapperClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/jni/CallRFFIHelper$CharSXPWrapper");
 	CharSXPWrapperContentsFieldID = checkGetFieldID(env, CharSXPWrapperClass, "contents", "Ljava/lang/String;", 0);
 
     R_computeIdenticalMethodID = checkGetMethodID(env, CallRFFIHelperClass, "R_computeIdentical", "(Ljava/lang/Object;Ljava/lang/Object;I)I", 1);
@@ -252,24 +252,6 @@ SEXP Rf_ScalarReal(double value) {
     return checkRef(thisenv, result);
 }
 
-// JNR calls to PCRE do not work properly (via JNR) without these wrappers
-
-char *pcre_maketables();
-void *pcre_compile(char * pattern, int options, char ** errorMessage, int *errOffset, char * tables);
-int  pcre_exec(void * code, void *extra, char* subject, int subjectLength, int startOffset, int options, int *ovector, int ovecSize);
-
-char *fastr_pcre_maketables() {
-	return pcre_maketables();
-}
-
-void *fastr_pcre_compile(char * pattern, int options, char ** errorMessage, int *errOffset, char * tables) {
-	return pcre_compile(pattern, options, errorMessage, errOffset, tables);
-}
-
-int fastr_pcre_exec(void * code, void *extra,  char* subject, int subjectLength, int startOffset, int options, int *ovector, int ovecSize) {
-	return pcre_exec(code, extra, subject, subjectLength, startOffset, options, ovector, ovecSize);
-}
-
 SEXP Rf_ScalarString(SEXP value) {
 	TRACE(TARGp, value);
 	JNIEnv *thisenv = getEnv();
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/appl_rffi.c b/com.oracle.truffle.r.native/fficall/src/jni/appl_rffi.c
new file mode 100644
index 0000000000000000000000000000000000000000..bd570ec5022b2a8a4703188087a92f611583e87a
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/jni/appl_rffi.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2016, 2016, 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.
+ */
+
+#include <rffiutils.h>
+
+extern void dqrdc2_(double *x, int *ldx, int *n, int *p, double *tol, int *rank, double *qraux, int* pivot, double *work);
+extern void dqrcf_(double *x, int *n, int *k, double *qraux, double *y, int *ny, double *b, int* info);
+extern void dqrls_(double *x, int *n, int *p, double *y, int *ny, double *tol, double *b, double *rsd, double *qty, int *k, int *jpvt, double *qraux, double *work);
+
+JNIEXPORT void JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1RAppl_native_1dqrdc2(JNIEnv *env, jclass c,
+		jdoubleArray jx, jint ldx, jint n, jint p, jdouble tol, jintArray jrank, jdoubleArray jqraux,
+		jintArray jpivot, jdoubleArray jwork) {
+	double *x = (*env)->GetPrimitiveArrayCritical(env, jx, NULL);
+	int *rank = (*env)->GetPrimitiveArrayCritical(env, jrank, NULL);
+	double *qraux = (*env)->GetPrimitiveArrayCritical(env, jqraux, NULL);
+	int *pivot = (*env)->GetPrimitiveArrayCritical(env, jpivot, NULL);
+	double *work = (*env)->GetPrimitiveArrayCritical(env, jwork, NULL);
+	dqrdc2_(x, &ldx, &n, &p, &tol, rank, qraux, pivot, work);
+	(*env)->ReleasePrimitiveArrayCritical(env, jx, x, 0);
+	(*env)->ReleasePrimitiveArrayCritical(env, jrank, rank, 0);
+	(*env)->ReleasePrimitiveArrayCritical(env, jqraux, qraux, 0);
+	(*env)->ReleasePrimitiveArrayCritical(env, jpivot, pivot, 0);
+	(*env)->ReleasePrimitiveArrayCritical(env, jwork, work, 0);
+}
+
+JNIEXPORT void JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1RAppl_native_1dqrcf(JNIEnv *env, jclass c,
+		jdoubleArray jx, jint n, jint k, jdoubleArray jqraux, jdoubleArray jy, jint ny, jdoubleArray jb, jintArray jinfo) {
+	double *x = (*env)->GetPrimitiveArrayCritical(env, jx, NULL);
+	double *qraux = (*env)->GetPrimitiveArrayCritical(env, jqraux, NULL);
+	double *y = (*env)->GetPrimitiveArrayCritical(env, jy, NULL);
+	double *b = (*env)->GetPrimitiveArrayCritical(env, jb, NULL);
+	int *info = (*env)->GetPrimitiveArrayCritical(env, jinfo, NULL);
+	dqrcf_(x, &n, &k, qraux, y, &ny, b, info);
+	(*env)->ReleasePrimitiveArrayCritical(env, jx, x, 0);
+	(*env)->ReleasePrimitiveArrayCritical(env, jqraux, qraux, 0);
+	(*env)->ReleasePrimitiveArrayCritical(env, jy, y, 0);
+	(*env)->ReleasePrimitiveArrayCritical(env, jb, b, 0);
+	(*env)->ReleasePrimitiveArrayCritical(env, jinfo, info, 0);
+}
+
+JNIEXPORT void JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1RAppl_native_1dqrls(JNIEnv *env, jclass c,
+		jdoubleArray jx, int n, int p, jdoubleArray jy, int ny, double tol, jdoubleArray jb,
+		jdoubleArray jrsd, jdoubleArray jqty, jintArray jk, jintArray jjpvt, jdoubleArray jqraux, jdoubleArray jwork) {
+	double *x = (*env)->GetPrimitiveArrayCritical(env, jx, NULL);
+	double *y = (*env)->GetPrimitiveArrayCritical(env, jy, NULL);
+	double *b = (*env)->GetPrimitiveArrayCritical(env, jb, NULL);
+	double *rsd = (*env)->GetPrimitiveArrayCritical(env, jrsd, NULL);
+	double *qty = (*env)->GetPrimitiveArrayCritical(env, jqty, NULL);
+	int *k = (*env)->GetPrimitiveArrayCritical(env, jk, NULL);
+	int *jpvt = (*env)->GetPrimitiveArrayCritical(env, jjpvt, NULL);
+	double *qraux = (*env)->GetPrimitiveArrayCritical(env, jqraux, NULL);
+	double *work = (*env)->GetPrimitiveArrayCritical(env, jwork, NULL);
+	dqrls_(x, &n, &p, y, &ny, &tol, b, rsd, qty, k, jpvt, qraux, work);
+	(*env)->ReleasePrimitiveArrayCritical(env, jx, x, 0);
+	(*env)->ReleasePrimitiveArrayCritical(env, jy, y, 0);
+	(*env)->ReleasePrimitiveArrayCritical(env, jb, b, 0);
+	(*env)->ReleasePrimitiveArrayCritical(env, jrsd, rsd, 0);
+	(*env)->ReleasePrimitiveArrayCritical(env, jqty, qty, 0);
+	(*env)->ReleasePrimitiveArrayCritical(env, jk, k, 0);
+	(*env)->ReleasePrimitiveArrayCritical(env, jjpvt, jpvt, 0);
+	(*env)->ReleasePrimitiveArrayCritical(env, jqraux, qraux, 0);
+	(*env)->ReleasePrimitiveArrayCritical(env, jwork, work, 0);
+}
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/base_rffi.c b/com.oracle.truffle.r.native/fficall/src/jni/base_rffi.c
new file mode 100644
index 0000000000000000000000000000000000000000..0af58786b908555c60b933b7d7e42fb392c51a4d
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/jni/base_rffi.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2016, 2016, 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.
+ */
+
+// JNI implementation of BaseRFFI
+
+#include <rffiutils.h>
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <glob.h>
+#include <sys/utsname.h>
+
+#include <errno.h>
+
+JNIEXPORT jint JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1getpid(JNIEnv *env, jclass c) {
+	pid_t pid = getpid();
+	return (jint) pid;
+}
+
+JNIEXPORT jint JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1getwd(JNIEnv *env, jclass c, jbyteArray jdest, int len) {
+    char *dest = (*env)->GetPrimitiveArrayCritical(env, jdest, NULL);
+    char *r = getcwd(dest, len);
+    if (r == NULL) return 0;
+    (*env)->ReleasePrimitiveArrayCritical(env, jdest, dest, 0);
+    return 1;
+}
+
+JNIEXPORT jint JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1setwd(JNIEnv *env, jclass c, jstring jdir) {
+    const char *dir = (*env)->GetStringUTFChars(env, jdir, NULL);
+    int rc = chdir(dir);
+    (*env)->ReleaseStringUTFChars(env, jdir, dir);
+    return rc;
+}
+
+JNIEXPORT jint JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1mkdtemp(JNIEnv *env, jclass c, jbyteArray jtemplate) {
+    char *template = (*env)->GetPrimitiveArrayCritical(env, jtemplate, NULL);
+    char *r = mkdtemp(template);
+    if (r == NULL) return 0;
+    (*env)->ReleasePrimitiveArrayCritical(env, jtemplate, template, 0);
+    return 1;
+}
+
+JNIEXPORT jint JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1mkdir(JNIEnv *env, jclass c, jstring jdir, jint mode) {
+    const char *dir = (*env)->GetStringUTFChars(env, jdir, NULL);
+    int rc = mkdir(dir, mode);
+    (*env)->ReleaseStringUTFChars(env, jdir, dir);
+    return rc;
+}
+
+JNIEXPORT jint JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1chmod(JNIEnv *env, jclass c, jstring jdir, jint mode) {
+    const char *dir = (*env)->GetStringUTFChars(env, jdir, NULL);
+    int rc = chmod(dir, mode);
+    (*env)->ReleaseStringUTFChars(env, jdir, dir);
+    return rc;
+}
+
+JNIEXPORT jlong JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1strtol(JNIEnv *env, jclass c, jstring js, jint base, jintArray jerrno) {
+    const char *s = (*env)->GetStringUTFChars(env, js, NULL);
+    jlong rc = strtol(s, NULL, base);
+    if (errno) {
+    	int *cerrno = (*env)->GetPrimitiveArrayCritical(env, jerrno, NULL);
+    	*cerrno = errno;
+    	(*env)->ReleasePrimitiveArrayCritical(env, jerrno, cerrno, 0);
+    }
+    (*env)->ReleaseStringUTFChars(env, js, s);
+    return rc;
+}
+
+JNIEXPORT jstring JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1readlink(JNIEnv *env, jclass c, jstring jpath, jintArray jerrno) {
+    const char *path = (*env)->GetStringUTFChars(env, jpath, NULL);
+    char buf[4096];
+    int len = readlink(path, buf, 4096);
+    jstring result = NULL;
+    if (len == -1) {
+    	int *cerrno = (*env)->GetPrimitiveArrayCritical(env, jerrno, NULL);
+    	*cerrno = errno;
+    	(*env)->ReleasePrimitiveArrayCritical(env, jerrno, cerrno, 0);
+    } else {
+    	buf[len] = 0;
+    	result = (*env)->NewStringUTF(env, buf);
+    }
+    (*env)->ReleaseStringUTFChars(env, jpath, path);
+    return result;
+}
+
+
+static jmethodID addPathID = 0;
+
+JNIEXPORT void JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Glob_doglob(JNIEnv *env, jobject obj, jstring pattern) {
+	glob_t globstruct;
+
+	if (addPathID == 0) {
+		addPathID = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, obj), "addPath", "(Ljava/lang/String;)V");
+	}
+
+	const char *patternChars = (*env)->GetStringUTFChars(env, pattern, NULL);
+	int rc = glob(patternChars, 0, NULL, &globstruct);
+	if (rc == 0) {
+		int i;
+		for (i = 0; i < globstruct.gl_pathc; i++) {
+			char *path = globstruct.gl_pathv[i];
+			jstring pathString = (*env)->NewStringUTF(env, path);
+			(*env)->CallVoidMethod(env, obj, addPathID, pathString);
+		}
+	}
+}
+
+JNIEXPORT void JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1UtsName_getutsname(JNIEnv *env, jobject obj) {
+	struct utsname name;
+
+	uname(&name);
+	jstring sysname = (*env)->NewStringUTF(env, name.sysname);
+	jstring release = (*env)->NewStringUTF(env, name.release);
+	jstring version = (*env)->NewStringUTF(env, name.version);
+	jstring machine = (*env)->NewStringUTF(env, name.machine);
+	jstring nodename = (*env)->NewStringUTF(env, name.nodename);
+
+	jclass klass = (*env)->GetObjectClass(env, obj);
+
+	jfieldID sysnameId = checkGetFieldID(env, klass, "sysname", "Ljava/lang/String;", 0);
+	jfieldID releaseId = checkGetFieldID(env, klass, "release", "Ljava/lang/String;", 0);
+	jfieldID versionId = checkGetFieldID(env, klass, "version", "Ljava/lang/String;", 0);
+	jfieldID machineId = checkGetFieldID(env, klass, "machine", "Ljava/lang/String;", 0);
+	jfieldID nodenameId = checkGetFieldID(env, klass, "nodename", "Ljava/lang/String;", 0);
+
+	(*env)->SetObjectField(env, obj, sysnameId, sysname);
+	(*env)->SetObjectField(env, obj, releaseId, release);
+	(*env)->SetObjectField(env, obj, versionId, version);
+	(*env)->SetObjectField(env, obj, machineId, machine);
+	(*env)->SetObjectField(env, obj, nodenameId, nodename);
+
+}
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/c_rffi.c b/com.oracle.truffle.r.native/fficall/src/jni/c_rffi.c
new file mode 100644
index 0000000000000000000000000000000000000000..9f1015280a6f3e5edb4e47ff5e135564e6330422
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/jni/c_rffi.c
@@ -0,0 +1,977 @@
+/*
+ * Copyright (c) 2016, 2016, 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.
+ */
+
+#include <rffiutils.h>
+
+static jclass intArrayClass;
+static jclass doubleArrayClass;
+
+void init_c(JNIEnv *env) {
+	intArrayClass = checkFindClass(env, "[I");
+	doubleArrayClass = checkFindClass(env, "[D");
+}
+
+typedef void (*c0func)();
+typedef void (*c1func)(void *arg1);
+typedef void (*c2func)(void *arg1, void *arg2);
+typedef void (*c3func)(void *arg1, void *arg2, void *arg3);
+typedef void (*c4func)(void *arg1, void *arg2, void *arg3, void *arg4);
+typedef void (*c5func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5);
+typedef void (*c6func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6);
+typedef void (*c7func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7);
+typedef void (*c8func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8);
+typedef void (*c9func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9);
+typedef void (*c10func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10);
+typedef void (*c11func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11);
+typedef void (*c12func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12);
+typedef void (*c13func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13);
+typedef void (*c14func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14);
+typedef void (*c15func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15);
+typedef void (*c16func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16);
+typedef void (*c17func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17);
+typedef void (*c18func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18);
+typedef void (*c19func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19);
+typedef void (*c20func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20);
+typedef void (*c21func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21);
+typedef void (*c22func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22);
+typedef void (*c23func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23);
+typedef void (*c24func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24);
+typedef void (*c25func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25);
+typedef void (*c26func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26);
+typedef void (*c27func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27);
+typedef void (*c28func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28);
+typedef void (*c29func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29);
+typedef void (*c30func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30);
+typedef void (*c31func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31);
+typedef void (*c32func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32);
+typedef void (*c33func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33);
+typedef void (*c34func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34);
+typedef void (*c35func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34, void *arg35);
+typedef void (*c36func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34, void *arg35, void *arg36);
+typedef void (*c37func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34, void *arg35, void *arg36, void *arg37);
+typedef void (*c38func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38);
+typedef void (*c39func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39);
+typedef void (*c40func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40);
+typedef void (*c41func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40,
+        void *arg41);
+typedef void (*c42func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40,
+        void *arg41, void *arg42);
+typedef void (*c43func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40,
+        void *arg41, void *arg42, void *arg43);
+typedef void (*c44func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40,
+        void *arg41, void *arg42, void *arg43, void *arg44);
+typedef void (*c45func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40,
+        void *arg41, void *arg42, void *arg43, void *arg44, void *arg45);
+typedef void (*c46func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40,
+        void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46);
+typedef void (*c47func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40,
+        void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47);
+typedef void (*c48func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40,
+        void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48);
+typedef void (*c49func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40,
+        void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48,
+        void *arg49);
+typedef void (*c50func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40,
+        void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48,
+        void *arg49, void *arg50);
+typedef void (*c51func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40,
+        void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48,
+        void *arg49, void *arg50, void *arg51);
+typedef void (*c52func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40,
+        void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48,
+        void *arg49, void *arg50, void *arg51, void *arg52);
+typedef void (*c53func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40,
+        void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48,
+        void *arg49, void *arg50, void *arg51, void *arg52, void *arg53);
+typedef void (*c54func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40,
+        void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48,
+        void *arg49, void *arg50, void *arg51, void *arg52, void *arg53, void *arg54);
+typedef void (*c55func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40,
+        void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48,
+        void *arg49, void *arg50, void *arg51, void *arg52, void *arg53, void *arg54, void *arg55);
+typedef void (*c56func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40,
+        void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48,
+        void *arg49, void *arg50, void *arg51, void *arg52, void *arg53, void *arg54, void *arg55, void *arg56);
+typedef void (*c57func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40,
+        void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48,
+        void *arg49, void *arg50, void *arg51, void *arg52, void *arg53, void *arg54, void *arg55, void *arg56,
+        void *arg57);
+typedef void (*c58func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40,
+        void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48,
+        void *arg49, void *arg50, void *arg51, void *arg52, void *arg53, void *arg54, void *arg55, void *arg56,
+        void *arg57, void *arg58);
+typedef void (*c59func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40,
+        void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48,
+        void *arg49, void *arg50, void *arg51, void *arg52, void *arg53, void *arg54, void *arg55, void *arg56,
+        void *arg57, void *arg58, void *arg59);
+typedef void (*c60func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40,
+        void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48,
+        void *arg49, void *arg50, void *arg51, void *arg52, void *arg53, void *arg54, void *arg55, void *arg56,
+        void *arg57, void *arg58, void *arg59, void *arg60);
+typedef void (*c61func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40,
+        void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48,
+        void *arg49, void *arg50, void *arg51, void *arg52, void *arg53, void *arg54, void *arg55, void *arg56,
+        void *arg57, void *arg58, void *arg59, void *arg60, void *arg61);
+typedef void (*c62func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40,
+        void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48,
+        void *arg49, void *arg50, void *arg51, void *arg52, void *arg53, void *arg54, void *arg55, void *arg56,
+        void *arg57, void *arg58, void *arg59, void *arg60, void *arg61, void *arg62);
+typedef void (*c63func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40,
+        void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48,
+        void *arg49, void *arg50, void *arg51, void *arg52, void *arg53, void *arg54, void *arg55, void *arg56,
+        void *arg57, void *arg58, void *arg59, void *arg60, void *arg61, void *arg62, void *arg63);
+typedef void (*c64func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40,
+        void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48,
+        void *arg49, void *arg50, void *arg51, void *arg52, void *arg53, void *arg54, void *arg55, void *arg56,
+        void *arg57, void *arg58, void *arg59, void *arg60, void *arg61, void *arg62, void *arg63, void *arg64);
+typedef void (*c65func)(void *arg1, void *arg2, void *arg3, void *arg4, void *arg5, void *arg6, void *arg7, void *arg8,
+        void *arg9, void *arg10, void *arg11, void *arg12, void *arg13, void *arg14, void *arg15, void *arg16,
+        void *arg17, void *arg18, void *arg19, void *arg20, void *arg21, void *arg22, void *arg23, void *arg24,
+        void *arg25, void *arg26, void *arg27, void *arg28, void *arg29, void *arg30, void *arg31, void *arg32,
+        void *arg33, void *arg34, void *arg35, void *arg36, void *arg37, void *arg38, void *arg39, void *arg40,
+        void *arg41, void *arg42, void *arg43, void *arg44, void *arg45, void *arg46, void *arg47, void *arg48,
+        void *arg49, void *arg50, void *arg51, void *arg52, void *arg53, void *arg54, void *arg55, void *arg56,
+        void *arg57, void *arg58, void *arg59, void *arg60, void *arg61, void *arg62, void *arg63, void *arg64,
+        void *arg65);
+
+
+JNIEXPORT void JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1C_c(JNIEnv *env, jclass c, jlong address, jobjectArray args) {
+	int len = (*env)->GetArrayLength(env, args);
+	void *cargs[len];
+	jobject jarrays[len];
+	for (int i = 0; i < len; i++) {
+		jarrays[i] = (*env)->GetObjectArrayElement(env, args, i);
+		cargs[i] = (*env)->GetPrimitiveArrayCritical(env, jarrays[i], NULL);
+	}
+	switch (len) {
+    case 0: {
+        c0func c0 = (c0func) address;
+        (*c0)();
+        break;
+    }
+
+    case 1: {
+        c1func c1 = (c1func) address;
+        (*c1)(cargs[0]);
+        break;
+    }
+
+    case 2: {
+        c2func c2 = (c2func) address;
+        (*c2)(cargs[0], cargs[1]);
+        break;
+    }
+
+    case 3: {
+        c3func c3 = (c3func) address;
+        (*c3)(cargs[0], cargs[1], cargs[2]);
+        break;
+    }
+
+    case 4: {
+        c4func c4 = (c4func) address;
+        (*c4)(cargs[0], cargs[1], cargs[2], cargs[3]);
+        break;
+    }
+
+    case 5: {
+        c5func c5 = (c5func) address;
+        (*c5)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4]);
+        break;
+    }
+
+    case 6: {
+        c6func c6 = (c6func) address;
+        (*c6)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5]);
+        break;
+    }
+
+    case 7: {
+        c7func c7 = (c7func) address;
+        (*c7)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6]);
+        break;
+    }
+
+    case 8: {
+        c8func c8 = (c8func) address;
+        (*c8)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7]);
+        break;
+    }
+
+    case 9: {
+        c9func c9 = (c9func) address;
+        (*c9)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8]);
+        break;
+    }
+
+    case 10: {
+        c10func c10 = (c10func) address;
+        (*c10)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9]);
+        break;
+    }
+
+    case 11: {
+        c11func c11 = (c11func) address;
+        (*c11)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10]);
+        break;
+    }
+
+    case 12: {
+        c12func c12 = (c12func) address;
+        (*c12)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11]);
+        break;
+    }
+
+    case 13: {
+        c13func c13 = (c13func) address;
+        (*c13)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12]);
+        break;
+    }
+
+    case 14: {
+        c14func c14 = (c14func) address;
+        (*c14)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13]);
+        break;
+    }
+
+    case 15: {
+        c15func c15 = (c15func) address;
+        (*c15)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14]);
+        break;
+    }
+
+    case 16: {
+        c16func c16 = (c16func) address;
+        (*c16)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15]);
+        break;
+    }
+
+    case 17: {
+        c17func c17 = (c17func) address;
+        (*c17)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16]);
+        break;
+    }
+
+    case 18: {
+        c18func c18 = (c18func) address;
+        (*c18)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17]);
+        break;
+    }
+
+    case 19: {
+        c19func c19 = (c19func) address;
+        (*c19)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18]);
+        break;
+    }
+
+    case 20: {
+        c20func c20 = (c20func) address;
+        (*c20)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19]);
+        break;
+    }
+
+    case 21: {
+        c21func c21 = (c21func) address;
+        (*c21)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20]);
+        break;
+    }
+
+    case 22: {
+        c22func c22 = (c22func) address;
+        (*c22)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21]);
+        break;
+    }
+
+    case 23: {
+        c23func c23 = (c23func) address;
+        (*c23)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22]);
+        break;
+    }
+
+    case 24: {
+        c24func c24 = (c24func) address;
+        (*c24)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23]);
+        break;
+    }
+
+    case 25: {
+        c25func c25 = (c25func) address;
+        (*c25)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24]);
+        break;
+    }
+
+    case 26: {
+        c26func c26 = (c26func) address;
+        (*c26)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25]);
+        break;
+    }
+
+    case 27: {
+        c27func c27 = (c27func) address;
+        (*c27)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26]);
+        break;
+    }
+
+    case 28: {
+        c28func c28 = (c28func) address;
+        (*c28)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27]);
+        break;
+    }
+
+    case 29: {
+        c29func c29 = (c29func) address;
+        (*c29)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28]);
+        break;
+    }
+
+    case 30: {
+        c30func c30 = (c30func) address;
+        (*c30)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29]);
+        break;
+    }
+
+    case 31: {
+        c31func c31 = (c31func) address;
+        (*c31)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30]);
+        break;
+    }
+
+    case 32: {
+        c32func c32 = (c32func) address;
+        (*c32)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31]);
+        break;
+    }
+
+    case 33: {
+        c33func c33 = (c33func) address;
+        (*c33)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32]);
+        break;
+    }
+
+    case 34: {
+        c34func c34 = (c34func) address;
+        (*c34)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33]);
+        break;
+    }
+
+    case 35: {
+        c35func c35 = (c35func) address;
+        (*c35)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33], cargs[34]);
+        break;
+    }
+
+    case 36: {
+        c36func c36 = (c36func) address;
+        (*c36)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33], cargs[34], cargs[35]);
+        break;
+    }
+
+    case 37: {
+        c37func c37 = (c37func) address;
+        (*c37)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33], cargs[34], cargs[35], cargs[36]);
+        break;
+    }
+
+    case 38: {
+        c38func c38 = (c38func) address;
+        (*c38)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37]);
+        break;
+    }
+
+    case 39: {
+        c39func c39 = (c39func) address;
+        (*c39)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38]);
+        break;
+    }
+
+    case 40: {
+        c40func c40 = (c40func) address;
+        (*c40)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39]);
+        break;
+    }
+
+    case 41: {
+        c41func c41 = (c41func) address;
+        (*c41)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39],
+        cargs[40]);
+        break;
+    }
+
+    case 42: {
+        c42func c42 = (c42func) address;
+        (*c42)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39],
+        cargs[40], cargs[41]);
+        break;
+    }
+
+    case 43: {
+        c43func c43 = (c43func) address;
+        (*c43)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39],
+        cargs[40], cargs[41], cargs[42]);
+        break;
+    }
+
+    case 44: {
+        c44func c44 = (c44func) address;
+        (*c44)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39],
+        cargs[40], cargs[41], cargs[42], cargs[43]);
+        break;
+    }
+
+    case 45: {
+        c45func c45 = (c45func) address;
+        (*c45)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39],
+        cargs[40], cargs[41], cargs[42], cargs[43], cargs[44]);
+        break;
+    }
+
+    case 46: {
+        c46func c46 = (c46func) address;
+        (*c46)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39],
+        cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45]);
+        break;
+    }
+
+    case 47: {
+        c47func c47 = (c47func) address;
+        (*c47)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39],
+        cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46]);
+        break;
+    }
+
+    case 48: {
+        c48func c48 = (c48func) address;
+        (*c48)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39],
+        cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47]);
+        break;
+    }
+
+    case 49: {
+        c49func c49 = (c49func) address;
+        (*c49)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39],
+        cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47],
+        cargs[48]);
+        break;
+    }
+
+    case 50: {
+        c50func c50 = (c50func) address;
+        (*c50)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39],
+        cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47],
+        cargs[48], cargs[49]);
+        break;
+    }
+
+    case 51: {
+        c51func c51 = (c51func) address;
+        (*c51)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39],
+        cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47],
+        cargs[48], cargs[49], cargs[50]);
+        break;
+    }
+
+    case 52: {
+        c52func c52 = (c52func) address;
+        (*c52)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39],
+        cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47],
+        cargs[48], cargs[49], cargs[50], cargs[51]);
+        break;
+    }
+
+    case 53: {
+        c53func c53 = (c53func) address;
+        (*c53)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39],
+        cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47],
+        cargs[48], cargs[49], cargs[50], cargs[51], cargs[52]);
+        break;
+    }
+
+    case 54: {
+        c54func c54 = (c54func) address;
+        (*c54)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39],
+        cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47],
+        cargs[48], cargs[49], cargs[50], cargs[51], cargs[52], cargs[53]);
+        break;
+    }
+
+    case 55: {
+        c55func c55 = (c55func) address;
+        (*c55)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39],
+        cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47],
+        cargs[48], cargs[49], cargs[50], cargs[51], cargs[52], cargs[53], cargs[54]);
+        break;
+    }
+
+    case 56: {
+        c56func c56 = (c56func) address;
+        (*c56)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39],
+        cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47],
+        cargs[48], cargs[49], cargs[50], cargs[51], cargs[52], cargs[53], cargs[54], cargs[55]);
+        break;
+    }
+
+    case 57: {
+        c57func c57 = (c57func) address;
+        (*c57)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39],
+        cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47],
+        cargs[48], cargs[49], cargs[50], cargs[51], cargs[52], cargs[53], cargs[54], cargs[55],
+        cargs[56]);
+        break;
+    }
+
+    case 58: {
+        c58func c58 = (c58func) address;
+        (*c58)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39],
+        cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47],
+        cargs[48], cargs[49], cargs[50], cargs[51], cargs[52], cargs[53], cargs[54], cargs[55],
+        cargs[56], cargs[57]);
+        break;
+    }
+
+    case 59: {
+        c59func c59 = (c59func) address;
+        (*c59)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39],
+        cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47],
+        cargs[48], cargs[49], cargs[50], cargs[51], cargs[52], cargs[53], cargs[54], cargs[55],
+        cargs[56], cargs[57], cargs[58]);
+        break;
+    }
+
+    case 60: {
+        c60func c60 = (c60func) address;
+        (*c60)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39],
+        cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47],
+        cargs[48], cargs[49], cargs[50], cargs[51], cargs[52], cargs[53], cargs[54], cargs[55],
+        cargs[56], cargs[57], cargs[58], cargs[59]);
+        break;
+    }
+
+    case 61: {
+        c61func c61 = (c61func) address;
+        (*c61)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39],
+        cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47],
+        cargs[48], cargs[49], cargs[50], cargs[51], cargs[52], cargs[53], cargs[54], cargs[55],
+        cargs[56], cargs[57], cargs[58], cargs[59], cargs[60]);
+        break;
+    }
+
+    case 62: {
+        c62func c62 = (c62func) address;
+        (*c62)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39],
+        cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47],
+        cargs[48], cargs[49], cargs[50], cargs[51], cargs[52], cargs[53], cargs[54], cargs[55],
+        cargs[56], cargs[57], cargs[58], cargs[59], cargs[60], cargs[61]);
+        break;
+    }
+
+    case 63: {
+        c63func c63 = (c63func) address;
+        (*c63)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39],
+        cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47],
+        cargs[48], cargs[49], cargs[50], cargs[51], cargs[52], cargs[53], cargs[54], cargs[55],
+        cargs[56], cargs[57], cargs[58], cargs[59], cargs[60], cargs[61], cargs[62]);
+        break;
+    }
+
+    case 64: {
+        c64func c64 = (c64func) address;
+        (*c64)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39],
+        cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47],
+        cargs[48], cargs[49], cargs[50], cargs[51], cargs[52], cargs[53], cargs[54], cargs[55],
+        cargs[56], cargs[57], cargs[58], cargs[59], cargs[60], cargs[61], cargs[62], cargs[63]);
+        break;
+    }
+
+    case 65: {
+        c65func c65 = (c65func) address;
+        (*c65)(cargs[0], cargs[1], cargs[2], cargs[3], cargs[4], cargs[5], cargs[6], cargs[7],
+        cargs[8], cargs[9], cargs[10], cargs[11], cargs[12], cargs[13], cargs[14], cargs[15],
+        cargs[16], cargs[17], cargs[18], cargs[19], cargs[20], cargs[21], cargs[22], cargs[23],
+        cargs[24], cargs[25], cargs[26], cargs[27], cargs[28], cargs[29], cargs[30], cargs[31],
+        cargs[32], cargs[33], cargs[34], cargs[35], cargs[36], cargs[37], cargs[38], cargs[39],
+        cargs[40], cargs[41], cargs[42], cargs[43], cargs[44], cargs[45], cargs[46], cargs[47],
+        cargs[48], cargs[49], cargs[50], cargs[51], cargs[52], cargs[53], cargs[54], cargs[55],
+        cargs[56], cargs[57], cargs[58], cargs[59], cargs[60], cargs[61], cargs[62], cargs[63],
+        cargs[64]);
+        break;
+    }
+	}
+
+	for (int i = 0; i < len; i++) {
+		(*env)->ReleasePrimitiveArrayCritical(env, jarrays[i], cargs[i], 0);
+	}
+}
+
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/rfficall.c b/com.oracle.truffle.r.native/fficall/src/jni/call_rffi.c
similarity index 96%
rename from com.oracle.truffle.r.native/fficall/src/jni/rfficall.c
rename to com.oracle.truffle.r.native/fficall/src/jni/call_rffi.c
index 78d3d632e39a1eaadb630696fb32713075387609..e0628f0683fc7fd3da55ea830bd83ff26506a537 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/rfficall.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/call_rffi.c
@@ -26,7 +26,7 @@
 #include <setjmp.h>
 
 JNIEXPORT void JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_initialize(JNIEnv *env, jclass c,
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_initialize(JNIEnv *env, jclass c,
 		jobjectArray initialValues) {
 	init_utils(env); // must be first
 	init_variables(env, initialValues);
@@ -35,43 +35,15 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_initialize(JNIEnv *env,
 	init_rmath(env);
 	init_random(env);
 	init_parse(env);
+	init_pcre(env);
+	init_c(env);
 }
 
 JNIEXPORT void JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_nativeSetTempDir(JNIEnv *env, jclass c, jstring tempDir) {
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_nativeSetTempDir(JNIEnv *env, jclass c, jstring tempDir) {
 	setTempDir(env, tempDir);
 }
 
-JNIEXPORT jdouble JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_exactSumFunc(JNIEnv *env, jclass c, jdoubleArray values, jboolean hasNa, jboolean naRm) {
-	jint length = (*env)->GetArrayLength(env, values);
-	jdouble* contents = (jdouble*) (*env)->GetPrimitiveArrayCritical(env, values, NULL);
-
-	long double sum = 0;
-	int i = 0;
-	if (!hasNa) {
-		for (; i < length - 3; i+= 4) {
-			sum += contents[i];
-			sum += contents[i + 1];
-			sum += contents[i + 2];
-			sum += contents[i + 3];
-		}
-	}
-	for (; i < length; i++) {
-		jdouble value = contents[i];
-		if (R_IsNA(value)) {
-			if (!naRm) {
-				(*env)->ReleasePrimitiveArrayCritical(env, values, contents, JNI_ABORT);
-				return R_NaReal;
-			}
-		} else {
-			sum += value;
-		}
-	}
-
-	(*env)->ReleasePrimitiveArrayCritical(env, values, contents, JNI_ABORT);
-	return sum;
-}
 
 // Boilerplate methods for the actual calls
 
@@ -371,7 +343,7 @@ typedef SEXP (*call64func)(SEXP arg1, SEXP arg2, SEXP arg3, SEXP arg4, SEXP arg5
         );
 
 JNIEXPORT jobject JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call0(JNIEnv *env, jclass c, jlong address) {
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call0(JNIEnv *env, jclass c, jlong address) {
 	jmp_buf error_jmpbuf;
 	jobject result = NULL;
 	callEnter(env, &error_jmpbuf);
@@ -384,7 +356,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call0(JNIEnv *env, jclas
 }
 
 JNIEXPORT jobject JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call1(JNIEnv *env, jclass c, jlong address, jobject arg1) {
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call1(JNIEnv *env, jclass c, jlong address, jobject arg1) {
 	jmp_buf error_jmpbuf;
 	jobject result = NULL;
 	callEnter(env, &error_jmpbuf);
@@ -397,7 +369,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call1(JNIEnv *env, jclas
 }
 
 JNIEXPORT jobject JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call2(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2) {
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call2(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2) {
 	jmp_buf error_jmpbuf;
 	jobject result = NULL;
 	callEnter(env, &error_jmpbuf);
@@ -410,7 +382,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call2(JNIEnv *env, jclas
 }
 
 JNIEXPORT jobject JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call3(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2,
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call3(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2,
 		jobject arg3) {
 	jmp_buf error_jmpbuf;
 	jobject result = NULL;
@@ -424,21 +396,25 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call3(JNIEnv *env, jclas
 }
 
 JNIEXPORT jobject JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call4(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2,
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call4(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2,
 		jobject arg3, jobject arg4) {
 	jmp_buf error_jmpbuf;
 	jobject result = NULL;
+	printf("in call4\n");
 	callEnter(env, &error_jmpbuf);
 	if (!setjmp(error_jmpbuf)) {
 		call4func call4 = (call4func) address;
+		printf("calling\n");
 		result = (*call4)(checkRef(env, arg1), checkRef(env, arg2), checkRef(env, arg3), checkRef(env, arg4));
 	}
+	printf("callexit\n");
 	callExit(env);
+	printf("done\n");
 	return result;
 }
 
 JNIEXPORT jobject JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call5(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2,
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call5(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2,
 		jobject arg3, jobject arg4, jobject arg5) {
 	jmp_buf error_jmpbuf;
 	jobject result = NULL;
@@ -452,7 +428,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call5(JNIEnv *env, jclas
 }
 
 JNIEXPORT jobject JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call6(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2,
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call6(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2,
 		jobject arg3, jobject arg4, jobject arg5, jobject arg6) {
 	jmp_buf error_jmpbuf;
 	jobject result = NULL;
@@ -466,7 +442,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call6(JNIEnv *env, jclas
 }
 
 JNIEXPORT jobject JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call7(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2,
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call7(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2,
 		jobject arg3, jobject arg4, jobject arg5, jobject arg6, jobject arg7) {
 	jmp_buf error_jmpbuf;
 	jobject result = NULL;
@@ -480,7 +456,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call7(JNIEnv *env, jclas
 }
 
 JNIEXPORT jobject JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call8(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2,
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call8(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2,
 		jobject arg3, jobject arg4, jobject arg5, jobject arg6, jobject arg7, jobject arg8) {
 	jmp_buf error_jmpbuf;
 	jobject result = NULL;
@@ -494,7 +470,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call8(JNIEnv *env, jclas
 }
 
 JNIEXPORT jobject JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call9(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2,
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call9(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2,
 		jobject arg3, jobject arg4, jobject arg5, jobject arg6, jobject arg7, jobject arg8, jobject arg9) {
 	jmp_buf error_jmpbuf;
 	jobject result = NULL;
@@ -508,7 +484,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call9(JNIEnv *env, jclas
 }
 
 JNIEXPORT jobject JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call(JNIEnv *env, jclass c, jlong address, jobjectArray args) {
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call(JNIEnv *env, jclass c, jlong address, jobjectArray args) {
 	jmp_buf error_jmpbuf;
 	jobject result = NULL;
 	callEnter(env, &error_jmpbuf);
@@ -1253,7 +1229,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_call(JNIEnv *env, jclass
 typedef void (*callVoid1func)(SEXP arg1);
 
 JNIEXPORT void JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_callVoid1(JNIEnv *env, jclass c, jlong address, jobject arg1) {
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_callVoid1(JNIEnv *env, jclass c, jlong address, jobject arg1) {
 	jmp_buf error_jmpbuf;
 	callEnter(env, &error_jmpbuf);
 	if (!setjmp(error_jmpbuf)) {
@@ -1266,7 +1242,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_callVoid1(JNIEnv *env, j
 typedef void (*callVoid0func)();
 
 JNIEXPORT void JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_callVoid0(JNIEnv *env, jclass c, jlong address) {
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_callVoid0(JNIEnv *env, jclass c, jlong address) {
 	jmp_buf error_jmpbuf;
 	callEnter(env, &error_jmpbuf);
 	if (!setjmp(error_jmpbuf)) {
@@ -1279,7 +1255,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_callVoid0(JNIEnv *env, j
 #include <Rinterface.h>
 
 JNIEXPORT void JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1CallRFFI_nativeSetInteractive(JNIEnv *env, jclass c, jboolean interactive) {
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_nativeSetInteractive(JNIEnv *env, jclass c, jboolean interactive) {
 	R_Interactive = interactive;
 }
 
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/lapack_rffi.c b/com.oracle.truffle.r.native/fficall/src/jni/lapack_rffi.c
new file mode 100644
index 0000000000000000000000000000000000000000..f7e52ad62480baf634b92dfdd3b09e82195e15ab
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/jni/lapack_rffi.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2016, 2016, 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.
+ */
+
+#include <rffiutils.h>
+
+extern void ilaver_(int *major, int *minor, int *patch);
+
+JNIEXPORT void JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1ilaver(JNIEnv *env, jclass klass, jintArray jversion) {
+	int major;
+	int minor;
+	int patch;
+	ilaver_(&major, &minor, &patch);
+	int *version = (*env)->GetPrimitiveArrayCritical(env, jversion, NULL);
+	version[0] = major;
+	version[1] = minor;
+	version[2] = patch;
+	(*env)->ReleasePrimitiveArrayCritical(env, jversion, version, 0);
+}
+
+
+extern int dgeev_(char *jobVL, char *jobVR, int *n, double *a, int *lda, double *wr, double *wi, double *vl, int *ldvl, double *vr, int *ldvr, double *work, int *lwork, int *info);
+
+JNIEXPORT jint JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dgeev(JNIEnv *env, jclass klass,
+        char jobVL, char jobVR, int n, jdoubleArray ja, int lda, jdoubleArray jwr, jdoubleArray jwi, jdoubleArray jvl, int ldvl, jdoubleArray jvr, int ldvr, jdoubleArray jwork, int lwork) {
+    double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL);
+    double *wr = (*env)->GetPrimitiveArrayCritical(env, jwr, NULL);
+    double *wi = (*env)->GetPrimitiveArrayCritical(env, jwi, NULL);
+    double *vl = jvl == NULL ? NULL : (*env)->GetPrimitiveArrayCritical(env, jvl, NULL);
+    double *vr = jvr == NULL ? NULL : (*env)->GetPrimitiveArrayCritical(env, jvr, NULL);
+    double *work = (*env)->GetPrimitiveArrayCritical(env, jwork, NULL);
+    int info;
+    dgeev_(&jobVL, &jobVR, &n, a, &lda, wr, wi, vl, &ldvl, vr, &ldvr, work, &lwork, &info);
+    (*env)->ReleasePrimitiveArrayCritical(env, ja, a, 0);
+    (*env)->ReleasePrimitiveArrayCritical(env, jwr, wr, 0);
+    (*env)->ReleasePrimitiveArrayCritical(env, jwi, wi, 0);
+    if (jvl != NULL) (*env)->ReleasePrimitiveArrayCritical(env, jvl, vl, 0);
+    if (jvr != NULL) (*env)->ReleasePrimitiveArrayCritical(env, jvr, vr, 0);
+    (*env)->ReleasePrimitiveArrayCritical(env, jwork, work, 0);
+    return info;
+}
+
+extern int dgeqp3_(int *m, int *n, double *a, int *lda, int *jpvt, double *tau, double *work, int *lwork, int *info);
+
+JNIEXPORT jint JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dgeqp3(JNIEnv *env, jclass klass,
+        int m, int n, jdoubleArray ja, int lda, jintArray jjpvt, jdoubleArray jtau, jdoubleArray jwork, int lwork) {
+    double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL);
+    int *jpvt = (*env)->GetPrimitiveArrayCritical(env, jjpvt, NULL);
+    double *tau = (*env)->GetPrimitiveArrayCritical(env, jtau, NULL);
+    double *work = (*env)->GetPrimitiveArrayCritical(env, jwork, NULL);
+    int info;
+    dgeqp3_(&m, &n, a, &lda, jpvt, tau, work, &lwork, &info);
+    (*env)->ReleasePrimitiveArrayCritical(env, ja, a, 0);
+    (*env)->ReleasePrimitiveArrayCritical(env, jjpvt, jpvt, 0);
+    (*env)->ReleasePrimitiveArrayCritical(env, jtau, tau, 0);
+    (*env)->ReleasePrimitiveArrayCritical(env, jwork, work, 0);
+    return info;
+}
+
+extern int dormqr_(char *side, char *trans, int *m, int *n, int *k, double *a, int *lda, double *tau, double *c, int *ldc, double *work, int *lwork, int *info);
+
+JNIEXPORT jint JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dormqr(JNIEnv *env, jclass klass,
+        char side, char trans, int m, int n, int k, jdoubleArray ja, int lda, jdoubleArray jtau, jdoubleArray jc, int ldc, jdoubleArray jwork, int lwork) {
+    double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL);
+    double *tau = (*env)->GetPrimitiveArrayCritical(env, jtau, NULL);
+    double *c = (*env)->GetPrimitiveArrayCritical(env, jc, NULL);
+    double *work = (*env)->GetPrimitiveArrayCritical(env, jwork, NULL);
+    int info;
+    dormqr_(&side, &trans, &m, &n, &k, a, &lda, tau, c, &ldc, work, &lwork, &info);
+    (*env)->ReleasePrimitiveArrayCritical(env, ja, a, JNI_ABORT);
+    (*env)->ReleasePrimitiveArrayCritical(env, jtau, tau, JNI_ABORT);
+    (*env)->ReleasePrimitiveArrayCritical(env, jc, c, 0);
+    (*env)->ReleasePrimitiveArrayCritical(env, jwork, work, 0);
+    return info;
+}
+
+extern int dtrtrs_(char *uplo, char *trans, char *diag, int *n, int *nrhs, double *a, int *lda, double *b, int *ldb, int *info);
+
+JNIEXPORT jint JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dtrtrs(JNIEnv *env, jclass klass,
+        char uplo, char trans, char diag, int n, int nrhs, jdoubleArray ja, int lda, jdoubleArray jb, int ldb) {
+    double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL);
+    double *b = (*env)->GetPrimitiveArrayCritical(env, jb, NULL);
+    int info;
+    dtrtrs_(&uplo, &trans, &diag, &n, &nrhs, a, &lda, b, &ldb, &info);
+    (*env)->ReleasePrimitiveArrayCritical(env, ja, a, JNI_ABORT);
+    (*env)->ReleasePrimitiveArrayCritical(env, jb, b, 0);
+    return info;
+}
+
+extern int dgetrf_(int *m, int *n, double *a, int *lda, int *ipiv, int *info);
+
+JNIEXPORT jint JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dgetrf(JNIEnv *env, jclass klass,
+        int m, int n, jdoubleArray ja, int lda, jintArray jipiv) {
+    double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL);
+    int *ipiv = (*env)->GetPrimitiveArrayCritical(env, jipiv, NULL);
+    int info;
+    dgetrf_(&m, &n, a, &lda, ipiv, &info);
+    (*env)->ReleasePrimitiveArrayCritical(env, ja, a, 0);
+    (*env)->ReleasePrimitiveArrayCritical(env, jipiv, ipiv, 0);
+    return info;
+}
+
+extern int dpotrf_(char *uplo, int *n, double *a, int *lda, int *info);
+
+JNIEXPORT jint JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dpotrf(JNIEnv *env, jclass klass,
+        char uplo, int n, jdoubleArray ja, int lda) {
+    double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL);
+    int info;
+    dpotrf_(&uplo, &n, a, &lda, &info);
+    (*env)->ReleasePrimitiveArrayCritical(env, ja, a, 0);
+    return info;
+}
+
+extern int dpstrf_(char *uplo, int *n, double *a, int *lda, int *piv, int *rank, double *tol, double *work, int *info);
+
+JNIEXPORT jint JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dpstrf(JNIEnv *env, jclass klass,
+        char uplo, int n, jdoubleArray ja, int lda, jintArray jpiv, jintArray jrank, double tol, jdoubleArray jwork) {
+    double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL);
+    int *piv = (*env)->GetPrimitiveArrayCritical(env, jpiv, NULL);
+    int *rank = (*env)->GetPrimitiveArrayCritical(env, jrank, NULL);
+    double *work = (*env)->GetPrimitiveArrayCritical(env, jwork, NULL);
+    int info;
+    dpstrf_(&uplo, &n, a, &lda, piv, rank, &tol, work, &info);
+    (*env)->ReleasePrimitiveArrayCritical(env, ja, a, 0);
+    (*env)->ReleasePrimitiveArrayCritical(env, jpiv, piv, 0);
+    (*env)->ReleasePrimitiveArrayCritical(env, jrank, rank, 0);
+    (*env)->ReleasePrimitiveArrayCritical(env, jwork, work, 0);
+    return info;
+}
+
+extern int dgesv_(int *n, int *nrhs, double *a, int *lda, int *ipiv, double *b, int *ldb, int *info);
+
+JNIEXPORT jint JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dgesv(JNIEnv *env, jclass klass,
+        int n, int nrhs, jdoubleArray ja, int lda, jintArray jipiv, jdoubleArray jb, int ldb) {
+    double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL);
+    int *ipiv = (*env)->GetPrimitiveArrayCritical(env, jipiv, NULL);
+    double *b = (*env)->GetPrimitiveArrayCritical(env, jb, NULL);
+    int info;
+    dgesv_(&n, &nrhs, a, &lda, ipiv, b, &ldb, &info);
+    (*env)->ReleasePrimitiveArrayCritical(env, ja, a, 0);
+    (*env)->ReleasePrimitiveArrayCritical(env, jipiv, ipiv, 0);
+    (*env)->ReleasePrimitiveArrayCritical(env, jb, b, 0);
+    return info;
+}
+
+extern double dlange_(char *norm, int *m, int *n, double *a, int *lda, double *work);
+
+JNIEXPORT jdouble JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dlange(JNIEnv *env, jclass klass,
+        char norm, int m, int n, jdoubleArray ja, int lda, jdoubleArray jwork) {
+    double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL);
+    double *work = jwork == NULL ? NULL : (*env)->GetPrimitiveArrayCritical(env, jwork, NULL);
+    double info = dlange_(&norm, &m, &n, a, &lda, work);
+    (*env)->ReleasePrimitiveArrayCritical(env, ja, a, JNI_ABORT);
+    if (jwork != NULL) (*env)->ReleasePrimitiveArrayCritical(env, jwork, work, JNI_ABORT);
+    return info;
+}
+
+extern int dgecon_(char *norm, int *n, double *a, int *lda, double *anorm, double *rcond, double *work, int *iwork, int *info);
+
+JNIEXPORT jint JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dgecon(JNIEnv *env, jclass klass,
+        char norm, int n, jdoubleArray ja, int lda, double anorm, jdoubleArray jrcond, jdoubleArray jwork, jintArray jiwork) {
+    double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL);
+    double *rcond = (*env)->GetPrimitiveArrayCritical(env, jrcond, NULL);
+    double *work = (*env)->GetPrimitiveArrayCritical(env, jwork, NULL);
+    int *iwork = (*env)->GetPrimitiveArrayCritical(env, jiwork, NULL);
+    int info;
+    dgecon_(&norm, &n, a, &lda, &anorm, rcond, work, iwork, &info);
+    (*env)->ReleasePrimitiveArrayCritical(env, ja, a, JNI_ABORT);
+    (*env)->ReleasePrimitiveArrayCritical(env, jrcond, rcond, 0);
+    (*env)->ReleasePrimitiveArrayCritical(env, jwork, work, 0);
+    (*env)->ReleasePrimitiveArrayCritical(env, jiwork, iwork, 0);
+    return info;
+}
+
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/misc_rffi.c b/com.oracle.truffle.r.native/fficall/src/jni/misc_rffi.c
new file mode 100644
index 0000000000000000000000000000000000000000..b4ee639d1e7c9df1c303574cc9de1a4a060afed2
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/jni/misc_rffi.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2015, 2016, 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.
+ */
+
+#include <rffiutils.h>
+
+JNIEXPORT jdouble JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Misc_exactSumFunc(JNIEnv *env, jclass c, jdoubleArray values, jboolean hasNa, jboolean naRm) {
+	jint length = (*env)->GetArrayLength(env, values);
+	jdouble* contents = (jdouble*) (*env)->GetPrimitiveArrayCritical(env, values, NULL);
+
+	long double sum = 0;
+	int i = 0;
+	if (!hasNa) {
+		for (; i < length - 3; i+= 4) {
+			sum += contents[i];
+			sum += contents[i + 1];
+			sum += contents[i + 2];
+			sum += contents[i + 3];
+		}
+	}
+	for (; i < length; i++) {
+		jdouble value = contents[i];
+		if (R_IsNA(value)) {
+			if (!naRm) {
+				(*env)->ReleasePrimitiveArrayCritical(env, values, contents, JNI_ABORT);
+				return R_NaReal;
+			}
+		} else {
+			sum += value;
+		}
+	}
+
+	(*env)->ReleasePrimitiveArrayCritical(env, values, contents, JNI_ABORT);
+	return sum;
+}
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/pcre_rffi.c b/com.oracle.truffle.r.native/fficall/src/jni/pcre_rffi.c
new file mode 100644
index 0000000000000000000000000000000000000000..40819418b6236b84066ddb157c302cae90fdcfe6
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/jni/pcre_rffi.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2016, 2016, 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.
+ */
+
+#include <rffiutils.h>
+
+char *pcre_maketables();
+void *pcre_compile(char * pattern, int options, char ** errorMessage, int *errOffset, char * tables);
+int  pcre_exec(void * code, void *extra, char* subject, int subjectLength, int startOffset, int options, int *ovector, int ovecSize);
+
+jclass JNI_PCRE_ResultClass;
+jmethodID ResultClassConstructorID;
+
+void init_pcre(JNIEnv *env) {
+	JNI_PCRE_ResultClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/PCRERFFI$Result");
+	ResultClassConstructorID = checkGetMethodID(env, JNI_PCRE_ResultClass, "<init>", "(JLjava/lang/String;I)V", 0);
+}
+
+JNIEXPORT jlong JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1PCRE_nativeMaketables(JNIEnv *env, jclass c) {
+	return (jlong) pcre_maketables();
+}
+
+JNIEXPORT jobject JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1PCRE_nativeCompile(JNIEnv *env, jclass c, jstring pattern, jint options, jlong tables) {
+	const char *patternChars = (*env)->GetStringUTFChars(env, pattern, NULL);
+	char *errorMessage;
+	int errOffset;
+	void *pcre_result = pcre_compile(patternChars, options, &errorMessage, &errOffset, (char*) tables);
+	jstring stringErrorMessage = NULL;
+	if (pcre_result == NULL) {
+	    stringErrorMessage = (*env)->NewStringUTF(env, errorMessage);
+	}
+	jobject result = (*env)->NewObject(env, JNI_PCRE_ResultClass, ResultClassConstructorID, pcre_result, stringErrorMessage, errOffset);
+	return result;
+}
+
+JNIEXPORT jint JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1PCRE_nativeExec(JNIEnv *env, jclass c,jlong code, jlong extra, jstring subject,
+		jint startOffset, jint options, jintArray ovector, jint ovectorLen) {
+	const char *subjectChars = (*env)->GetStringUTFChars(env, subject, NULL);
+	int subjectLength = (*env)->GetStringUTFLength(env, subject);
+	int* ovectorElems = (*env)->GetIntArrayElements(env, ovector, NULL);
+
+	int rc = pcre_exec(code, extra, subjectChars, subjectLength, startOffset, options,
+			ovectorElems, ovectorLen);
+	(*env)->ReleaseIntArrayElements(env, ovector, ovectorElems, 0);
+	(*env)->ReleaseStringUTFChars(env, subject, subjectChars);
+	return rc;
+}
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 5f9425d8a7ffd68d8607ad2c3cc9864671065fb9..c083d5a7811e31bc3d106fb65b55defeb8c4a6c8 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c
@@ -115,7 +115,7 @@ void init_utils(JNIEnv *env) {
 		}
 	}
 	RDataFactoryClass = checkFindClass(env, "com/oracle/truffle/r/runtime/data/RDataFactory");
-	CallRFFIHelperClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper");
+	CallRFFIHelperClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/jni/CallRFFIHelper");
 	RRuntimeClass = checkFindClass(env, "com/oracle/truffle/r/runtime/RRuntime");
 	RInternalErrorClass = checkFindClass(env, "com/oracle/truffle/r/runtime/RInternalError");
 	unimplementedMethodID = checkGetMethodID(env, RInternalErrorClass, "unimplemented", "(Ljava/lang/String;)Ljava/lang/RuntimeException;", 1);
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 78bbe21b9fe3c27f7113b2f213ac5500e5721929..1a217b586c83a8ea42af363fa6adc2cb791dfc3d 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h
+++ b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h
@@ -84,6 +84,8 @@ void init_internals(JNIEnv *env);
 void init_random(JNIEnv *env);
 void init_utils(JNIEnv *env);
 void init_parse(JNIEnv *env);
+void init_pcre(JNIEnv *env);
+void init_c(JNIEnv *env);
 
 void setEmbedded(void);
 
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/stats_fft.c b/com.oracle.truffle.r.native/fficall/src/jni/stats_fft.c
new file mode 100644
index 0000000000000000000000000000000000000000..4ed4a0dcf2474cf871d25907b58d5a460c3a9063
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/jni/stats_fft.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2016, 2016, 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.
+ */
+
+#include <rffiutils.h>
+
+typedef void (*fft_factor)(int n, int *pmaxf, int *pmaxp);
+typedef Rboolean (*fft_work)(double *a, int nseg, int n, int nspn, int isn,
+		  double *work, int *iwork);
+
+JNIEXPORT void JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Stats_native_1fft_1factor(JNIEnv *env, jclass c, jlong address,
+		jint n, jintArray jpmaxf, jintArray jpmaxp) {
+	fft_factor f = (fft_factor) address;
+	int *pmaxf = (*env)->GetPrimitiveArrayCritical(env, jpmaxf, NULL);
+	int *pmaxp = (*env)->GetPrimitiveArrayCritical(env, jpmaxp, NULL);
+	f(n, pmaxp, pmaxf);
+	(*env)->ReleasePrimitiveArrayCritical(env, jpmaxf, pmaxf, 0);
+	(*env)->ReleasePrimitiveArrayCritical(env, jpmaxp, pmaxp, 0);
+}
+
+JNIEXPORT int JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Stats_native_1fft_1work(JNIEnv *env, jclass c, jlong address,
+		jdoubleArray ja, int nseg, int n, int nsps, int isn, jdoubleArray jwork, jintArray jiwork) {
+	fft_work f = (fft_work) address;
+	double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL);
+	double *work = (*env)->GetPrimitiveArrayCritical(env, jwork, NULL);
+	int *iwork = (*env)->GetPrimitiveArrayCritical(env, jiwork, NULL);
+	int res = f(a, nseg, n, nsps, isn, work, iwork);
+	(*env)->ReleasePrimitiveArrayCritical(env, ja, a, 0);
+	(*env)->ReleasePrimitiveArrayCritical(env, jwork, work, JNI_ABORT);
+	(*env)->ReleasePrimitiveArrayCritical(env, jiwork, iwork, JNI_ABORT);
+	return res;
+}
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/userrng.c b/com.oracle.truffle.r.native/fficall/src/jni/userrng_rffi.c
similarity index 88%
rename from com.oracle.truffle.r.native/fficall/src/jni/userrng.c
rename to com.oracle.truffle.r.native/fficall/src/jni/userrng_rffi.c
index 35d4e2bd9128da1be5cba8a53251026f43945d8d..a946f23f8b1f9fbcc72322e199a1103afe3649a8 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/userrng.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/userrng_rffi.c
@@ -29,27 +29,27 @@ typedef int* (*call_nSeed)(void);
 typedef int* (*call_seeds)(void);
 
 JNIEXPORT void JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1UserRng_init(JNIEnv *env, jclass c, jlong address, jint seed) {
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1UserRng_init(JNIEnv *env, jclass c, jlong address, jint seed) {
 	call_init f = (call_init) address;
 	f(seed);
 }
 
 JNIEXPORT double JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1UserRng_rand(JNIEnv *env, jclass c, jlong address) {
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1UserRng_rand(JNIEnv *env, jclass c, jlong address) {
 	call_rand f = (call_rand) address;
 	double* dp = f();
 	return *dp;
 }
 
 JNIEXPORT jint JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1UserRng_nSeed(JNIEnv *env, jclass c, jlong address) {
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1UserRng_nSeed(JNIEnv *env, jclass c, jlong address) {
 	call_nSeed f = (call_nSeed) address;
 	int *pn = f();
 	return *pn;
 }
 
 JNIEXPORT void JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1UserRng_seeds(JNIEnv *env, jclass c, jlong address, jintArray seedsArray) {
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1UserRng_seeds(JNIEnv *env, jclass c, jlong address, jintArray seedsArray) {
 	call_seeds f = (call_seeds) address;
 	int *pseeds = f();
 	int seedslen = (*env)->GetArrayLength(env, seedsArray);
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/zip_rffi.c b/com.oracle.truffle.r.native/fficall/src/jni/zip_rffi.c
new file mode 100644
index 0000000000000000000000000000000000000000..e6bbec4c6cd08089bc7f3eea81a57198a064c21f
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/jni/zip_rffi.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2016, 2016, 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.
+ */
+
+#include <rffiutils.h>
+
+extern int compress(char *dest, long *destlen, char *source, long *sourcelen);
+extern int uncompress(char *dest, long *destlen, char *source, long *sourcelen);
+
+JNIEXPORT jint JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Zip_native_1compress(JNIEnv *env, jclass c,
+		jbyteArray jdest, jlong destlen, jbyteArray jsource, jlong sourcelen) {
+    char *dest = (*env)->GetPrimitiveArrayCritical(env, jdest, NULL);
+    char *source = (*env)->GetPrimitiveArrayCritical(env, jsource, NULL);
+    int rc = compress(dest, &destlen, source, sourcelen);
+    (*env)->ReleasePrimitiveArrayCritical(env, jdest, dest, 0);
+    (*env)->ReleasePrimitiveArrayCritical(env, jsource, source, JNI_ABORT);
+    return rc;
+}
+
+JNIEXPORT jint JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Zip_native_1uncompress(JNIEnv *env, jclass c,
+		jbyteArray jdest, jlong destlen, jbyteArray jsource, jlong sourcelen) {
+    char *dest = (*env)->GetPrimitiveArrayCritical(env, jdest, NULL);
+    char *source = (*env)->GetPrimitiveArrayCritical(env, jsource, NULL);
+    int rc = uncompress(dest, &destlen, source, sourcelen);
+    (*env)->ReleasePrimitiveArrayCritical(env, jdest, dest, 0);
+    (*env)->ReleasePrimitiveArrayCritical(env, jsource, source, JNI_ABORT);
+	return rc;
+}
diff --git a/com.oracle.truffle.r.native/osextras/Makefile b/com.oracle.truffle.r.native/fficall/src/jniboot/Makefile
similarity index 64%
rename from com.oracle.truffle.r.native/osextras/Makefile
rename to com.oracle.truffle.r.native/fficall/src/jniboot/Makefile
index 3e88e01f22dc0f38867cc582bb6154dc180458c0..951610837a51d0497f2692f460b1cab72c99bbfb 100644
--- a/com.oracle.truffle.r.native/osextras/Makefile
+++ b/com.oracle.truffle.r.native/fficall/src/jniboot/Makefile
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2016, 2016, 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
@@ -21,38 +21,16 @@
 # questions.
 #
 
-ifeq ($(TOPDIR),)
-    TOPDIR = $(abspath ../..)
-endif
-
 ifneq ($(MAKECMDGOALS),clean)
 include $(TOPDIR)/platform.mk
 endif
 
-.PHONY: all clean
 
-OBJ = lib
-SRC = src
-C_SOURCES := $(wildcard $(SRC)/*.c)
-C_LIBNAME := libosextras$(DYLIB_EXT)
-C_OBJECTS := $(subst $(SRC),$(OBJ),$(C_SOURCES:.c=.o))
-C_LIB := $(TOPDIR)/../lib/$(C_LIBNAME)
-#CFLAGS := $(CFLAGS) -DFASTR
+.PHONY: all
 
 JNI_INCLUDES = -I $(JAVA_HOME)/include -I $(JAVA_HOME)/include/$(JDK_OS_DIR)
 
-INCLUDES := $(JNI_INCLUDES)
-
-all: $(C_LIB)
-
-$(C_LIB): $(OBJ) $(C_OBJECTS)
-	$(DYLIB_LD) $(DYLIB_LDFLAGS) -o $(C_LIB) $(C_OBJECTS)
-
-$(OBJ):
-	mkdir -p $(OBJ)
-
-$(OBJ)/%.o: $(SRC)/%.c 
-	$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
+all: jniboot.o
 
-clean:
-	rm -rf $(OBJ) $(C_LIB)
+jniboot.o: jniboot.c
+	$(CC) $(CFLAGS) $(JNI_INCLUDES) -c jniboot.c -o $@
diff --git a/com.oracle.truffle.r.native/fficall/src/jniboot/jniboot.c b/com.oracle.truffle.r.native/fficall/src/jniboot/jniboot.c
new file mode 100644
index 0000000000000000000000000000000000000000..47efbbee2735138f6bd386ea7b754f2776455b7c
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/jniboot/jniboot.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2016, 2016, 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.
+ */
+
+// These functions, while defined in JNI_Base are stored in a seperate library, jniboot
+// in order to be able to bootstrap the system as libR has to be loaded using these functions.
+
+#include <dlfcn.h>
+#include <jni.h>
+
+JNIEXPORT jlong JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1dlopen(JNIEnv *env, jclass c, jstring jpath, jboolean local, jboolean now) {
+    const char *path = (*env)->GetStringUTFChars(env, jpath, NULL);
+    int flags = (local ? RTLD_LOCAL : RTLD_GLOBAL) | (now ? RTLD_NOW : RTLD_LAZY);
+    void *handle = dlopen(path, flags);
+    (*env)->ReleaseStringUTFChars(env, jpath, path);
+    return (jlong) handle;
+}
+
+// It seems that an internal (JVM) dlsym call can occur between a call to this dlsym and dlerror
+// (probably resolving the JNI dlerror symbol, so we capture it here (N.B. depends on single
+// threaded limitation).
+
+static char *last_dlerror;
+
+JNIEXPORT jlong JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1dlsym(JNIEnv *env, jclass c, jlong handle, jstring jsymbol) {
+    const char *symbol = (*env)->GetStringUTFChars(env, jsymbol, NULL);
+    void *address = dlsym((void *)handle, symbol);
+	last_dlerror = dlerror();
+    (*env)->ReleaseStringUTFChars(env, jsymbol, symbol);
+    return (jlong) address;
+}
+
+JNIEXPORT jint JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1dlclose(JNIEnv *env, jclass c, jlong handle) {
+    int rc = dlclose((void *)handle);
+    return rc;
+}
+
+JNIEXPORT jobject JNICALL
+Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1dlerror(JNIEnv *env, jclass c) {
+    char *err = last_dlerror;
+    if (err == NULL) {
+    	return NULL;
+    } else {
+    	return (*env)->NewStringUTF(env, err);
+    }
+}
+
diff --git a/com.oracle.truffle.r.native/gnur/Makefile.libs b/com.oracle.truffle.r.native/gnur/Makefile.libs
index 13841dcc2b47ed3aeb80dc589d1f0422f010b9de..89f5cb31d9552a8f753ce363da6fff28038b0697 100644
--- a/com.oracle.truffle.r.native/gnur/Makefile.libs
+++ b/com.oracle.truffle.r.native/gnur/Makefile.libs
@@ -33,8 +33,12 @@ endif
 
 BLAS_TARGET := $(FASTR_LIB_DIR)/libRblas$(DYLIB_EXT)
 LAPACK_TARGET := $(FASTR_LIB_DIR)/libRlapack$(DYLIB_EXT)
+# at a minimum we need to know where libpcre/libz are located,
+# to keep the Java side simpler, we copy them to $(FASTR_LIB_DIR)
+PCRE_TARGET := $(FASTR_LIB_DIR)/libpcre$(DYLIB_EXT)
+Z_TARGET := $(FASTR_LIB_DIR)/libz$(DYLIB_EXT)
 
-all: $(FASTR_LIB_DIR) $(BLAS_TARGET) $(LAPACK_TARGET)
+all: $(FASTR_LIB_DIR) $(BLAS_TARGET) $(LAPACK_TARGET) $(PCRE_TARGET) $(Z_TARGET)
 
 $(FASTR_LIB_DIR):
 	mkdir -p $(FASTR_LIB_DIR)
@@ -51,7 +55,13 @@ ifeq ($(OS_NAME),Darwin)
 	install_name_tool -id $(LAPACK_TARGET) $(LAPACK_TARGET)
 endif
 
+$(PCRE_TARGET): 
+	cp $(shell mx rfindlib pcre) $(PCRE_TARGET)
+	
+$(Z_TARGET): 
+	cp $(shell mx rfindlib z) $(Z_TARGET)
+	
 clean:
-	rm -f $(BLAS_TARGET) $(LAPACK_TARGET)
+	rm -f $(BLAS_TARGET) $(LAPACK_TARGET) $(PCRE_TARGET) $(Z_TARGET)
 
 		
diff --git a/com.oracle.truffle.r.native/osextras/src/getutsname.c b/com.oracle.truffle.r.native/osextras/src/getutsname.c
deleted file mode 100644
index a676f8545b0850ebecb0e92412c64c4231214ba8..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.native/osextras/src/getutsname.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (c) 2014, 2015, 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.
- */
-#include <string.h>
-#include <sys/utsname.h>
-#include <jni.h>
-
-struct utsname name;
-
-static jfieldID checkGetFieldID(JNIEnv *env, jclass klass, const char *name, const char *sig) {
-	jfieldID fieldID = (*env)->GetFieldID(env, klass, name, sig);
-	if (fieldID == NULL) {
-		char buf[1024];
-		strcpy(buf, "failed to find field ");
-		strcat(buf, name);
-		(*env)->FatalError(env, buf);
-	}
-	return fieldID;
-}
-
-JNIEXPORT void JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1UtsName_getutsname(JNIEnv *env, jobject obj) {
-	uname(&name);
-	jstring sysname = (*env)->NewStringUTF(env, name.sysname);
-	jstring release = (*env)->NewStringUTF(env, name.release);
-	jstring version = (*env)->NewStringUTF(env, name.version);
-	jstring machine = (*env)->NewStringUTF(env, name.machine);
-	jstring nodename = (*env)->NewStringUTF(env, name.nodename);
-
-	jclass klass = (*env)->GetObjectClass(env, obj);
-
-	jfieldID sysnameId = checkGetFieldID(env, klass, "sysname", "Ljava/lang/String;");
-	jfieldID releaseId = checkGetFieldID(env, klass, "release", "Ljava/lang/String;");
-	jfieldID versionId = checkGetFieldID(env, klass, "version", "Ljava/lang/String;");
-	jfieldID machineId = checkGetFieldID(env, klass, "machine", "Ljava/lang/String;");
-	jfieldID nodenameId = checkGetFieldID(env, klass, "nodename", "Ljava/lang/String;");
-
-	(*env)->SetObjectField(env, obj, sysnameId, sysname);
-	(*env)->SetObjectField(env, obj, releaseId, release);
-	(*env)->SetObjectField(env, obj, versionId, version);
-	(*env)->SetObjectField(env, obj, machineId, machine);
-	(*env)->SetObjectField(env, obj, nodenameId, nodename);
-
-}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java
index 17c735f5162aa5988c9bbfa271e74e32df72037a..9a180cf9038503e02a506b84eb7971af40a48120 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java
@@ -82,7 +82,7 @@ public abstract class Sum extends RBuiltinNode {
         int length = lengthProfile.profile(vector.getLength());
 
         if (needsExactSumProfile.profile(length >= 3)) {
-            return RFFIFactory.getRFFI().getCallRFFI().exactSum(vector.getDataWithoutCopying(), !vector.isComplete(), cachedNaRm);
+            return RFFIFactory.getRFFI().getMiscRFFI().exactSum(vector.getDataWithoutCopying(), !vector.isComplete(), cachedNaRm);
         } else {
             na.enable(vector);
             loopProfile.profileCounted(length);
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/Load_RFFIFactory.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/Load_RFFIFactory.java
index f178e6264add01001baa99864f8a290312dc9f6d..003cfc0e03d5cd67a3e6fde4468a32f33eed1fb3 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/Load_RFFIFactory.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/Load_RFFIFactory.java
@@ -32,7 +32,7 @@ public class Load_RFFIFactory {
     private static final String FACTORY_CLASS_PROPERTY = "fastr.ffi.factory.class";
     private static final String PACKAGE_PREFIX = "com.oracle.truffle.r.runtime.ffi.";
     private static final String SUFFIX = "_RFFIFactory";
-    private static final String DEFAULT_FACTORY = "jnr";
+    private static final String DEFAULT_FACTORY = "jni";
     private static final String DEFAULT_FACTORY_CLASS = mapSimpleName(DEFAULT_FACTORY);
 
     private static String mapSimpleName(String simpleName) {
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/RFFIVariables.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/RFFIVariables.java
index 7aa097a1e35b9f594b1a7884d40cada004552cf0..0695d46b3a50b64b9664e158c287d9e44c03bafc 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/RFFIVariables.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/RFFIVariables.java
@@ -29,7 +29,7 @@ import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RUnboundValue;
 import com.oracle.truffle.r.runtime.env.REnvironment;
-import com.oracle.truffle.r.runtime.ffi.jnr.CallRFFIHelper;
+import com.oracle.truffle.r.runtime.ffi.jni.CallRFFIHelper;
 
 public enum RFFIVariables {
     R_Home(REnvVars.rHome()),
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/CallRFFIHelper.java
similarity index 99%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java
rename to com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/CallRFFIHelper.java
index 60a68d6a8bdebba0bbe1a7081168c965a3ee9ac4..8bc1d0c7b86f60a84440f9d934194a9f5bedc90a 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CallRFFIHelper.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/CallRFFIHelper.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.jnr;
+package com.oracle.truffle.r.runtime.ffi.jni;
 
 import java.nio.charset.StandardCharsets;
 import java.util.function.Function;
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Base.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Base.java
new file mode 100644
index 0000000000000000000000000000000000000000..ca874253e76c4bbd00c8d568e7d74f6d9f32fd20
--- /dev/null
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Base.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2014, 2016, 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 java.io.IOException;
+import java.util.ArrayList;
+
+import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
+
+public class JNI_Base implements BaseRFFI {
+    @Override
+    public int getpid() {
+        return native_getpid();
+    }
+
+    @Override
+    public int setwd(String dir) {
+        return native_setwd(dir);
+    }
+
+    @Override
+    public String getwd() {
+        byte[] buf = new byte[4096];
+        int rc = native_getwd(buf, buf.length);
+        if (rc == 0) {
+            return null;
+        } else {
+            int i = 0;
+            while (buf[i] != 0 && i < buf.length) {
+                i++;
+            }
+            return new String(buf, 0, i);
+        }
+    }
+
+    private static final int EINVAL = 22;
+
+    @Override
+    public String readlink(String path) throws IOException {
+        int[] errno = new int[]{0};
+        String s = native_readlink(path, errno);
+        if (s == null) {
+            if (errno[0] == EINVAL) {
+                // not a link
+            } else {
+                // some other error
+                throw new IOException("readlink failed: " + errno[0]);
+            }
+        }
+        return s;
+    }
+
+    @Override
+    public String mkdtemp(String template) {
+        byte[] bytes = template.getBytes();
+        long result = native_mkdtemp(bytes);
+        if (result == 0) {
+            return null;
+        } else {
+            return new String(bytes);
+        }
+    }
+
+    @Override
+    public void mkdir(String dir, int mode) throws IOException {
+        int rc = native_mkdir(dir, mode);
+        if (rc != 0) {
+            throw new IOException("mkdir " + dir + " failed");
+        }
+    }
+
+    @Override
+    public int chmod(String path, int mode) {
+        return native_chmod(path, mode);
+    }
+
+    @Override
+    public long strtol(String s, int base) throws IllegalArgumentException {
+        int[] errno = new int[]{0};
+        long result = native_strtol(s, base, errno);
+        if (errno[0] != 0) {
+            throw new IllegalArgumentException("strtol failure");
+        } else {
+            return result;
+        }
+    }
+
+    @Override
+    public Object dlopen(String path, boolean local, boolean now) {
+        long handle = native_dlopen(path, local, now);
+        if (handle == 0) {
+            return null;
+        } else {
+            return new Long(handle);
+        }
+    }
+
+    @Override
+    public long dlsym(Object handle, String symbol) {
+        long nativeHandle = (Long) handle;
+        return native_dlsym(nativeHandle, symbol);
+    }
+
+    @Override
+    public int dlclose(Object handle) {
+        long nativeHandle = (Long) handle;
+        return native_dlclose(nativeHandle);
+    }
+
+    @Override
+    public String dlerror() {
+        return native_dlerror();
+    }
+
+    @Override
+    public UtsName uname() {
+        return JNI_UtsName.get();
+    }
+
+    @Override
+    public ArrayList<String> glob(String pattern) {
+        return JNI_Glob.glob(pattern);
+    }
+
+    // Checkstyle: stop method name
+
+    private static native int native_getpid();
+
+    private static native int native_getwd(byte[] buf, int buflength);
+
+    private static native int native_setwd(String dir);
+
+    private static native int native_mkdtemp(byte[] template);
+
+    private static native int native_mkdir(String dir, int mode);
+
+    private static native int native_chmod(String dir, int mode);
+
+    private static native long native_strtol(String s, int base, int[] errno);
+
+    private static native String native_readlink(String s, int[] errno);
+
+    private static native long native_dlopen(String path, boolean local, boolean now);
+
+    private static native int native_dlclose(long handle);
+
+    private static native String native_dlerror();
+
+    private static native long native_dlsym(long handle, String symbol);
+
+}
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_C.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_C.java
new file mode 100644
index 0000000000000000000000000000000000000000..e3bf27cfa8436afd0fcb198f9b6ecbc3cf43b153
--- /dev/null
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_C.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2014, 2016, 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 com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.r.runtime.ffi.CRFFI;
+import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
+
+public class JNI_C implements CRFFI {
+
+    /**
+     * This is rather similar to {@link JNI_Call}, except the objects are guaranteed to be
+     * native array types, no upcalls are possible, and no result is returned. However, the
+     * receiving function expects actual native arrays (not SEXPs), so these have to be handled on
+     * the JNI side.
+     */
+    @Override
+    @TruffleBoundary
+    public synchronized void invoke(long address, Object[] args) {
+        c(address, args);
+    }
+
+    private static native void c(long address, Object[] args);
+}
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_CallRFFI.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java
similarity index 93%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_CallRFFI.java
rename to com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java
index 3f4525fdc087e9d4c4d2292bde8ff38b32951ddf..3d3fb55004ac59ea96ab88cf9205b194a3000028 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_CallRFFI.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.jnr;
+package com.oracle.truffle.r.runtime.ffi.jni;
 
 import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceDownCall;
 import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceDownCallReturn;
@@ -28,6 +28,7 @@ import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceEnabled;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
 import com.oracle.truffle.r.runtime.ffi.CallRFFI;
 import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.ffi.DLL.DLLException;
@@ -43,9 +44,9 @@ import com.oracle.truffle.r.runtime.ffi.RFFIVariables;
  *
  * The JNI layer is not (currently) MT safe, so all calls are single threaded.
  */
-public class JNI_CallRFFI implements CallRFFI {
+public class JNI_Call implements CallRFFI {
 
-    JNI_CallRFFI() {
+    JNI_Call() {
         loadLibrary();
     }
 
@@ -57,9 +58,15 @@ public class JNI_CallRFFI implements CallRFFI {
      * {@code RTLD_LOCAL} with {@code dlopen}, so we have to load the library manually and set
      * {@code RTLD_GLOBAL}. However, a {@code dlopen} does not hook the JNI functions into the JVM,
      * so we have to do an additional {@code System.load} to achieve that.
+     *
+     * Before we do that we must load {@code libjniboot} because the implementation of
+     * {@link BaseRFFI#dlopen} is called by {@link DLL#load} which uses JNI!
      */
     @TruffleBoundary
     private static void loadLibrary() {
+        String libjnibootPath = LibPaths.getBuiltinLibPath("jniboot");
+        System.load(libjnibootPath);
+
         String librffiPath = LibPaths.getBuiltinLibPath("R");
         try {
             DLL.load(librffiPath, ForceRTLDGlobal, false);
@@ -119,8 +126,6 @@ public class JNI_CallRFFI implements CallRFFI {
 
     private static native void nativeSetInteractive(boolean interactive);
 
-    private static native double exactSumFunc(double[] values, boolean hasNa, boolean naRm);
-
     private static native Object call(long address, Object[] args);
 
     private static native Object call0(long address);
@@ -194,17 +199,4 @@ public class JNI_CallRFFI implements CallRFFI {
         }
     }
 
-    @Override
-    public double exactSum(double[] values, boolean hasNa, boolean naRm) {
-        if (traceEnabled()) {
-            traceDownCall("exactSum");
-        }
-        try {
-            return exactSumFunc(values, hasNa, naRm);
-        } finally {
-            if (traceEnabled()) {
-                traceDownCallReturn("exactSum", null);
-            }
-        }
-    }
 }
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_Glob.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Glob.java
similarity index 96%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_Glob.java
rename to com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Glob.java
index 111b1f6e308be889b7008e670320e2867555fc75..975294266f0d1753ac9b461960a528a681701b97 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_Glob.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Glob.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.jnr;
+package com.oracle.truffle.r.runtime.ffi.jni;
 
 import java.util.ArrayList;
 
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Lapack.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Lapack.java
new file mode 100644
index 0000000000000000000000000000000000000000..83499ad00ca8cfff07359a0af4d40b9c7b405222
--- /dev/null
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Lapack.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2015, 2016, 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 com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.r.runtime.ffi.LapackRFFI;
+
+public class JNI_Lapack implements LapackRFFI {
+    @Override
+    @TruffleBoundary
+    public void ilaver(int[] version) {
+        native_ilaver(version);
+    }
+
+    @Override
+    @TruffleBoundary
+    public int dgeev(char jobVL, char jobVR, int n, double[] a, int lda, double[] wr, double[] wi, double[] vl, int ldvl, double[] vr, int ldvr, double[] work, int lwork) {
+        return native_dgeev(jobVL, jobVR, n, a, lda, wr, wi, vl, ldvl, vr, ldvr, work, lwork);
+    }
+
+    @Override
+    @TruffleBoundary
+    public int dgeqp3(int m, int n, double[] a, int lda, int[] jpvt, double[] tau, double[] work, int lwork) {
+        return native_dgeqp3(m, n, a, lda, jpvt, tau, work, lwork);
+    }
+
+    @Override
+    @TruffleBoundary
+    public int dormqr(char side, char trans, int m, int n, int k, double[] a, int lda, double[] tau, double[] c, int ldc, double[] work, int lwork) {
+        return native_dormqr(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork);
+    }
+
+    @Override
+    @TruffleBoundary
+    public int dtrtrs(char uplo, char trans, char diag, int n, int nrhs, double[] a, int lda, double[] b, int ldb) {
+        return native_dtrtrs(uplo, trans, diag, n, nrhs, a, lda, b, ldb);
+    }
+
+    @Override
+    @TruffleBoundary
+    public int dgetrf(int m, int n, double[] a, int lda, int[] ipiv) {
+        return native_dgetrf(m, n, a, lda, ipiv);
+    }
+
+    @Override
+    @TruffleBoundary
+    public int dpotrf(char uplo, int n, double[] a, int lda) {
+        return native_dpotrf(uplo, n, a, lda);
+    }
+
+    @Override
+    @TruffleBoundary
+    public int dpstrf(char uplo, int n, double[] a, int lda, int[] piv, int[] rank, double tol, double[] work) {
+        return native_dpstrf(uplo, n, a, lda, piv, rank, tol, work);
+    }
+
+    @Override
+    @TruffleBoundary
+    public int dgesv(int n, int nrhs, double[] a, int lda, int[] ipiv, double[] b, int ldb) {
+        return native_dgesv(n, nrhs, a, lda, ipiv, b, ldb);
+    }
+
+    @Override
+    @TruffleBoundary
+    public double dlange(char norm, int m, int n, double[] a, int lda, double[] work) {
+        return native_dlange(norm, m, n, a, lda, work);
+    }
+
+    @Override
+    @TruffleBoundary
+    public int dgecon(char norm, int n, double[] a, int lda, double anorm, double[] rcond, double[] work, int[] iwork) {
+        return native_dgecon(norm, n, a, lda, anorm, rcond, work, iwork);
+    }
+
+    // Checkstyle: stop method name
+
+    private static native void native_ilaver(int[] version);
+
+    private static native int native_dgeev(char jobVL, char jobVR, int n, double[] a, int lda, double[] wr, double[] wi, double[] vl, int ldvl, double[] vr, int ldvr, double[] work, int lwork);
+
+    private static native int native_dgeqp3(int m, int n, double[] a, int lda, int[] jpvt, double[] tau, double[] work, int lwork);
+
+    private static native int native_dormqr(char side, char trans, int m, int n, int k, double[] a, int lda, double[] tau, double[] c, int ldc, double[] work, int lwork);
+
+    private static native int native_dtrtrs(char uplo, char trans, char diag, int n, int nrhs, double[] a, int lda, double[] b, int ldb);
+
+    private static native int native_dgetrf(int m, int n, double[] a, int lda, int[] ipiv);
+
+    private static native int native_dpotrf(char uplo, int n, double[] a, int lda);
+
+    private static native int native_dpstrf(char uplo, int n, double[] a, int lda, int[] piv, int[] rank, double tol, double[] work);
+
+    private static native int native_dgesv(int n, int nrhs, double[] a, int lda, int[] ipiv, double[] b, int ldb);
+
+    private static native double native_dlange(char norm, int m, int n, double[] a, int lda, double[] work);
+
+    private static native int native_dgecon(char norm, int n, double[] a, int lda, double anorm, double[] rcond, double[] work, int[] iwork);
+
+}
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Misc.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Misc.java
new file mode 100644
index 0000000000000000000000000000000000000000..eb9acfc8566c51815bdb537e07d5a842ddb8bad8
--- /dev/null
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Misc.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2016, 2016, 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.runtime.ffi.RFFIUtils.traceDownCall;
+import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceDownCallReturn;
+import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.traceEnabled;
+
+import com.oracle.truffle.r.runtime.ffi.MiscRFFI;
+
+public class JNI_Misc implements MiscRFFI {
+
+    @Override
+    public double exactSum(double[] values, boolean hasNa, boolean naRm) {
+        if (traceEnabled()) {
+            traceDownCall("exactSum");
+        }
+        try {
+            return exactSumFunc(values, hasNa, naRm);
+        } finally {
+            if (traceEnabled()) {
+                traceDownCallReturn("exactSum", null);
+            }
+        }
+    }
+
+    private static native double exactSumFunc(double[] values, boolean hasNa, boolean naRm);
+
+}
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PCRE.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PCRE.java
new file mode 100644
index 0000000000000000000000000000000000000000..b9b97036b2f9c8b626550b6cc94840da16245acb
--- /dev/null
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PCRE.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2015, 2016, 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 com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.ffi.LibPaths;
+import com.oracle.truffle.r.runtime.ffi.PCRERFFI;
+
+public class JNI_PCRE implements PCRERFFI {
+    JNI_PCRE() {
+        System.load(LibPaths.getBuiltinLibPath("pcre"));
+    }
+
+    @Override
+    public long maketables() {
+        return nativeMaketables();
+    }
+
+    @Override
+    public Result compile(String pattern, int options, long tables) {
+        return nativeCompile(pattern, options, tables);
+    }
+
+    @Override
+    public Result study(long code, int options) {
+        throw RInternalError.unimplemented("pcre_study");
+    }
+
+    @Override
+    public int exec(long code, long extra, String subject, int offset, int options, int[] ovector) {
+        return nativeExec(code, extra, subject, offset, options, ovector, ovector.length);
+    }
+
+    private static native long nativeMaketables();
+
+    private static native Result nativeCompile(String pattern, int options, long tables);
+
+    private static native int nativeExec(long code, long extra, String subject, int offset,
+                    int options, int[] ovector, int ovectorLen);
+
+}
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_PkgInit.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PkgInit.java
similarity index 98%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_PkgInit.java
rename to com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PkgInit.java
index 4576a66fdf3cec66e4430969573602e730985521..a93b6008d661a12ba9887a5d948bf7f0f6a06c6c 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_PkgInit.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PkgInit.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.jnr;
+package com.oracle.truffle.r.runtime.ffi.jni;
 
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.ffi.DLL;
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RAppl.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RAppl.java
new file mode 100644
index 0000000000000000000000000000000000000000..b48a2fa9c113c12f68a2632ee147f1b3c55c4287
--- /dev/null
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RAppl.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014, 2016, 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 com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.r.runtime.ffi.RApplRFFI;
+
+public class JNI_RAppl implements RApplRFFI {
+    @Override
+    @TruffleBoundary
+    public void dqrdc2(double[] x, int ldx, int n, int p, double tol, int[] rank, double[] qraux, int[] pivot, double[] work) {
+        native_dqrdc2(x, ldx, n, p, tol, rank, qraux, pivot, work);
+    }
+
+    @Override
+    @TruffleBoundary
+    public void dqrcf(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] b, int[] info) {
+        native_dqrcf(x, n, k, qraux, y, ny, b, info);
+    }
+
+    @Override
+    @TruffleBoundary
+    public void dqrls(double[] x, int n, int p, double[] y, int ny, double tol, double[] b, double[] rsd, double[] qty, int[] k, int[] jpvt, double[] qraux, double[] work) {
+        native_dqrls(x, n, p, y, ny, tol, b, rsd, qty, k, jpvt, qraux, work);
+    }
+
+    // Checkstyle: stop method name
+
+    private static native void native_dqrdc2(double[] x, int ldx, int n, int p, double tol, int[] rank, double[] qraux, int[] pivot, double[] work);
+
+    private static native void native_dqrcf(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] b, int[] info);
+
+    private static native void native_dqrls(double[] x, int n, int p, double[] y, int ny, double tol, double[] b, double[] rsd, double[] qty, int[] k, int[] jpvt, double[] qraux, double[] work);
+
+}
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_REmbed.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_REmbed.java
similarity index 97%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_REmbed.java
rename to com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_REmbed.java
index e6fe980732140e280f2c1bfdd4ded4a93d4335f4..bf44eeafa0cc61566f58ebb97d8bfb6340bcdc68 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_REmbed.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_REmbed.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.jnr;
+package com.oracle.truffle.r.runtime.ffi.jni;
 
 import com.oracle.truffle.r.runtime.ffi.REmbedRFFI;
 
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_RFFIFactory.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RFFIFactory.java
similarity index 78%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_RFFIFactory.java
rename to com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RFFIFactory.java
index 19aba1169678bd8cdfffd5d9d8e2c4c5ed5aec24..af726e7ecdc27bab43ce06d7f818ef22e304cd1b 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_RFFIFactory.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RFFIFactory.java
@@ -20,11 +20,10 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.jnr;
+package com.oracle.truffle.r.runtime.ffi.jni;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.r.runtime.RPlatform;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.context.RContext.ContextState;
 import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
@@ -32,7 +31,7 @@ import com.oracle.truffle.r.runtime.ffi.CRFFI;
 import com.oracle.truffle.r.runtime.ffi.CallRFFI;
 import com.oracle.truffle.r.runtime.ffi.GridRFFI;
 import com.oracle.truffle.r.runtime.ffi.LapackRFFI;
-import com.oracle.truffle.r.runtime.ffi.LibPaths;
+import com.oracle.truffle.r.runtime.ffi.MiscRFFI;
 import com.oracle.truffle.r.runtime.ffi.PCRERFFI;
 import com.oracle.truffle.r.runtime.ffi.RApplRFFI;
 import com.oracle.truffle.r.runtime.ffi.REmbedRFFI;
@@ -46,33 +45,17 @@ import com.oracle.truffle.r.runtime.ffi.generic.Generic_Grid;
 import com.oracle.truffle.r.runtime.ffi.generic.Generic_Tools;
 
 /**
- * JNR/JNI-based factory. The majority of the FFI instances are instantiated on demand.
+ * JNI-based factory. The majority of the FFI instances are instantiated on demand.
  */
-public class JNR_RFFIFactory extends RFFIFactory implements RFFI {
+public class JNI_RFFIFactory extends RFFIFactory implements RFFI {
 
-    public JNR_RFFIFactory() {
+    public JNI_RFFIFactory() {
     }
 
     @Override
     protected void initialize(boolean runtime) {
         // This must load early as package libraries reference symbols in it.
         getCallRFFI();
-        /*
-         * Some package C code calls these functions and, therefore, expects the linpack symbols to
-         * be available, which will not be the case unless one of the functions has already been
-         * called from R code. So we eagerly load the library to define the symbols.
-         *
-         * There is an additional problem when running without a *_LIBRARY_PATH being set which is
-         * mandated by Mac OSX El Capitan, which is we must tell JNR where to find the libraries.
-         */
-        String jnrLibPath = LibPaths.getBuiltinLibPath();
-        if (RPlatform.getOSInfo().osName.equals("Mac OS X")) {
-            // Why this is necessary is a JNR mystery
-            jnrLibPath += ":/usr/lib";
-        }
-        System.setProperty("jnr.ffi.library.path", jnrLibPath);
-        JNR_RAppl.linpack();
-        JNR_Lapack.lapack();
     }
 
     /**
@@ -98,7 +81,7 @@ public class JNR_RFFIFactory extends RFFIFactory implements RFFI {
     public BaseRFFI getBaseRFFI() {
         if (baseRFFI == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            baseRFFI = new JNR_Base();
+            baseRFFI = new JNI_Base();
         }
         return baseRFFI;
     }
@@ -109,7 +92,7 @@ public class JNR_RFFIFactory extends RFFIFactory implements RFFI {
     public LapackRFFI getLapackRFFI() {
         if (lapackRFFI == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            lapackRFFI = new JNR_Lapack();
+            lapackRFFI = new JNI_Lapack();
         }
         return lapackRFFI;
     }
@@ -120,7 +103,7 @@ public class JNR_RFFIFactory extends RFFIFactory implements RFFI {
     public RApplRFFI getRApplRFFI() {
         if (rApplRFFI == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            rApplRFFI = new JNR_RAppl();
+            rApplRFFI = new JNI_RAppl();
         }
         return rApplRFFI;
     }
@@ -131,7 +114,7 @@ public class JNR_RFFIFactory extends RFFIFactory implements RFFI {
     public StatsRFFI getStatsRFFI() {
         if (statsRFFI == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            statsRFFI = new JNR_Stats();
+            statsRFFI = new JNI_Stats();
         }
         return statsRFFI;
     }
@@ -175,7 +158,7 @@ public class JNR_RFFIFactory extends RFFIFactory implements RFFI {
     public CRFFI getCRFFI() {
         if (cRFFI == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            cRFFI = new CRFFI_JNR_Invoke();
+            cRFFI = new JNI_C();
         }
         return cRFFI;
     }
@@ -186,7 +169,7 @@ public class JNR_RFFIFactory extends RFFIFactory implements RFFI {
     public CallRFFI getCallRFFI() {
         if (callRFFI == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            callRFFI = new JNI_CallRFFI();
+            callRFFI = new JNI_Call();
         }
         return callRFFI;
     }
@@ -197,7 +180,7 @@ public class JNR_RFFIFactory extends RFFIFactory implements RFFI {
     public ZipRFFI getZipRFFI() {
         if (zipRFFI == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            zipRFFI = new JNR_Zip();
+            zipRFFI = new JNI_Zip();
         }
         return zipRFFI;
     }
@@ -207,8 +190,7 @@ public class JNR_RFFIFactory extends RFFIFactory implements RFFI {
     @Override
     public PCRERFFI getPCRERFFI() {
         if (pcreRFFI == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            pcreRFFI = new JNR_PCRE();
+            pcreRFFI = new JNI_PCRE();
         }
         return pcreRFFI;
     }
@@ -223,4 +205,14 @@ public class JNR_RFFIFactory extends RFFIFactory implements RFFI {
         return rEmbedRFFI;
     }
 
+    private MiscRFFI miscRFFI;
+
+    @Override
+    public MiscRFFI getMiscRFFI() {
+        if (miscRFFI == null) {
+            miscRFFI = new JNI_Misc();
+        }
+        return miscRFFI;
+    }
+
 }
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_Stats.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Stats.java
similarity index 57%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_Stats.java
rename to com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Stats.java
index 1f62195064f853ec7e893f5211ad49bf5e23d4cb..460515618e7e8fb6d656cbd9b594f77c4e83df51 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_Stats.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Stats.java
@@ -20,57 +20,50 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.jnr;
+package com.oracle.truffle.r.runtime.ffi.jni;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.ffi.DLL;
+import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
 import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo;
 import com.oracle.truffle.r.runtime.ffi.StatsRFFI;
 
-import jnr.ffi.LibraryLoader;
-import jnr.ffi.annotations.In;
-import jnr.ffi.annotations.Out;
-
 // Checkstyle: stop method name
-public class JNR_Stats implements StatsRFFI {
-    public interface Stats {
-        void fft_factor(int n, @Out int[] pmaxf, @Out int[] pmaxp);
+public class JNI_Stats implements StatsRFFI {
+    @Override
+    @TruffleBoundary
+    public void fft_factor(int n, int[] pmaxf, int[] pmaxp) {
+        native_fft_factor(fft_factor_address(), n, pmaxf, pmaxp);
+    }
 
-        int fft_work(double[] a, int nseg, int n, int nspn, int isn, @In double[] work, @In int[] iwork);
+    @Override
+    @TruffleBoundary
+    public int fft_work(double[] a, int nseg, int n, int nspn, int isn, double[] work, int[] iwork) {
+        return native_fft_work(fft_work_address(), a, nseg, n, nspn, isn, work, iwork);
     }
 
-    private static class StatsProvider {
-        private static Stats stats;
+    private long fft_factor_address;
+    private long fft_work_address;
 
-        @TruffleBoundary
-        private static Stats createAndLoadLib() {
-            // fft is in the stats package .so
+    private long fft_factor_address() {
+        if (fft_factor_address == 0) {
             DLLInfo dllInfo = DLL.findLibrary("stats");
-            assert dllInfo != null;
-            return LibraryLoader.create(Stats.class).load(dllInfo.path);
-        }
-
-        static Stats fft() {
-            if (stats == null) {
-                stats = createAndLoadLib();
-            }
-            return stats;
+            fft_factor_address = RFFIFactory.getRFFI().getBaseRFFI().dlsym(dllInfo.handle, "fft_factor");
+            assert fft_factor_address != DLL.SYMBOL_NOT_FOUND;
         }
+        return fft_factor_address;
     }
 
-    private static Stats stats() {
-        return StatsProvider.fft();
+    private long fft_work_address() {
+        if (fft_work_address == 0) {
+            DLLInfo dllInfo = DLL.findLibrary("stats");
+            fft_work_address = RFFIFactory.getRFFI().getBaseRFFI().dlsym(dllInfo.handle, "fft_work");
+            assert fft_work_address != DLL.SYMBOL_NOT_FOUND;
+        }
+        return fft_work_address;
     }
 
-    @Override
-    @TruffleBoundary
-    public void fft_factor(int n, int[] pmaxf, int[] pmaxp) {
-        stats().fft_factor(n, pmaxf, pmaxp);
-    }
+    private static native void native_fft_factor(long address, int n, int[] pmaxf, int[] pmaxp);
 
-    @Override
-    @TruffleBoundary
-    public int fft_work(double[] a, int nseg, int n, int nspn, int isn, double[] work, int[] iwork) {
-        return stats().fft_work(a, nseg, n, nspn, isn, work, iwork);
-    }
+    private static native int native_fft_work(long address, double[] a, int nseg, int n, int nspn, int isn, double[] work, int[] iwork);
 }
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_UserRng.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_UserRng.java
similarity index 97%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_UserRng.java
rename to com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_UserRng.java
index fcb6c4c8d6f3ed744a912944823950b842892264..bc935d7b3223a3002440066511b2252471d85248 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_UserRng.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_UserRng.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.jnr;
+package com.oracle.truffle.r.runtime.ffi.jni;
 
 import static com.oracle.truffle.r.runtime.rng.user.UserRNG.Function;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_UtsName.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_UtsName.java
similarity index 97%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_UtsName.java
rename to com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_UtsName.java
index 5212999dfb9daeecabc1199a122d04f9714a9e20..51151f9636943de72ec687c4303790d86b5cbc48 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_UtsName.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_UtsName.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.jnr;
+package com.oracle.truffle.r.runtime.ffi.jni;
 
 import com.oracle.truffle.r.runtime.ffi.BaseRFFI.UtsName;
 
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_Zip.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Zip.java
similarity index 52%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_Zip.java
rename to com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Zip.java
index e0de35c38ed459eddb9e7031489d250a929c1f8e..883158f77b2b9ae90c46fade784c96d20c5fc15c 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_Zip.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Zip.java
@@ -20,54 +20,38 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.jnr;
+package com.oracle.truffle.r.runtime.ffi.jni;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.r.runtime.ffi.LibPaths;
 import com.oracle.truffle.r.runtime.ffi.ZipRFFI;
 
-import jnr.ffi.LibraryLoader;
-import jnr.ffi.annotations.In;
-import jnr.ffi.annotations.Out;
-
 /**
- * Zip support using JNR.
+ * Zip support using JNI.
  */
-public class JNR_Zip implements ZipRFFI {
-    public interface Zip {
-        int compress(@Out byte[] dest, long[] destlen, @In byte[] source, long sourcelen);
-
-        int uncompress(@Out byte[] dest, long[] destlen, @In byte[] source, long sourcelen);
-    }
-
-    private static class ZipProvider {
-        private static Zip zip;
-
-        @TruffleBoundary
-        private static Zip createAndLoadLib() {
-            return LibraryLoader.create(Zip.class).load("z");
-        }
+public class JNI_Zip implements ZipRFFI {
 
-        static Zip zip() {
-            if (zip == null) {
-                zip = createAndLoadLib();
-            }
-            return zip;
-        }
-    }
-
-    private static Zip zip() {
-        return ZipProvider.zip();
+    JNI_Zip() {
+        System.load(LibPaths.getBuiltinLibPath("z"));
     }
 
     @Override
     @TruffleBoundary
-    public int compress(byte[] dest, long[] destlen, byte[] source) {
-        return zip().compress(dest, destlen, source, source.length);
+    public int compress(byte[] dest, byte[] source) {
+        int rc = native_compress(dest, dest.length, source, source.length);
+        return rc;
     }
 
     @Override
     @TruffleBoundary
-    public int uncompress(byte[] dest, long[] destlen, byte[] source) {
-        return zip().uncompress(dest, destlen, source, source.length);
+    public int uncompress(byte[] dest, byte[] source) {
+        int rc = native_uncompress(dest, dest.length, source, source.length);
+        return rc;
     }
+
+    // Checkstyle: stop method name
+
+    private static native int native_compress(byte[] dest, long destlen, byte[] source, long sourcelen);
+
+    private static native int native_uncompress(byte[] dest, long destlen, byte[] source, long sourcelen);
 }
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CRFFI_JNR_Invoke.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CRFFI_JNR_Invoke.java
deleted file mode 100644
index d5c6fc43c1b1f0edd11fa2fdc6c4c0174cf25953..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/CRFFI_JNR_Invoke.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2014, 2016, 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.jnr;
-
-import java.lang.invoke.MethodHandle;
-
-import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.ffi.CRFFI;
-
-import jnr.invoke.CodeAddress;
-import jnr.invoke.DataDirection;
-import jnr.invoke.Native;
-import jnr.invoke.NativeType;
-import jnr.invoke.ParameterType;
-import jnr.invoke.ResultType;
-import jnr.invoke.Signature;
-
-/**
- * An implementation of {@link CRFFI} that uses {@code jnr-invoke}.
- */
-public class CRFFI_JNR_Invoke implements CRFFI {
-
-    /**
-     * We construct a signature for jnr-invoke based on the types in {@code args}. Everything is an
-     * array (call by reference for scalars). As we already loaded the library and looked up the
-     * symbol address we don't need to use JNR for that.
-     */
-    @Override
-    public void invoke(long address, Object[] args) {
-        ParameterType[] parameterTypes = new ParameterType[args.length];
-        for (int i = 0; i < args.length; i++) {
-            Object arg = args[i];
-            if (arg instanceof double[]) {
-                parameterTypes[i] = ParameterType.array(double[].class, DataDirection.INOUT);
-            } else if (arg instanceof int[]) {
-                parameterTypes[i] = ParameterType.array(int[].class, DataDirection.INOUT);
-            } else {
-                assert (false);
-            }
-        }
-        Signature sig = Signature.getSignature(ResultType.primitive(NativeType.VOID, void.class), parameterTypes);
-
-        // We already have up the symbol address
-        MethodHandle mh = Native.getMethodHandle(sig, new CodeAddress(address));
-        try {
-            mh.invokeWithArguments(args);
-        } catch (Throwable ex) {
-            throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, ex.getMessage());
-        }
-    }
-}
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_OSExtras.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_OSExtras.java
deleted file mode 100644
index c903af4de7e6c0a11994f57fec2f74d7f71309e6..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNI_OSExtras.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2014, 2016, 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.jnr;
-
-import java.util.ArrayList;
-
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
-import com.oracle.truffle.r.runtime.ffi.BaseRFFI.UtsName;
-import com.oracle.truffle.r.runtime.ffi.LibPaths;
-
-/**
- * Additional support for {@link BaseRFFI} that is implemented using JNI not JNR.
- */
-public class JNI_OSExtras {
-    private interface OSExtras {
-        UtsName uname();
-
-        ArrayList<String> glob(String pattern);
-    }
-
-    private static class OSExtraProvider implements OSExtras {
-        private static OSExtras osExtras;
-
-        @TruffleBoundary
-        private static OSExtras createAndLoadLib() {
-            try {
-                System.load(LibPaths.getBuiltinLibPath("osextras"));
-                return new OSExtraProvider();
-            } catch (UnsatisfiedLinkError ex) {
-                throw RInternalError.shouldNotReachHere("osextras");
-            }
-        }
-
-        static OSExtras osExtras() {
-            if (osExtras == null) {
-                osExtras = createAndLoadLib();
-            }
-            return osExtras;
-        }
-
-        @Override
-        public UtsName uname() {
-            return JNI_UtsName.get();
-        }
-
-        @Override
-        public ArrayList<String> glob(String pattern) {
-            return JNI_Glob.glob(pattern);
-        }
-    }
-
-    private static OSExtras osExtras() {
-        return OSExtraProvider.osExtras();
-    }
-
-    static UtsName uname() {
-        return osExtras().uname();
-    }
-
-    static ArrayList<String> glob(String pattern) {
-        return osExtras().glob(pattern);
-    }
-}
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_Base.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_Base.java
deleted file mode 100644
index 04dc45199a5dea49b9510e7a7476869669b150cf..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_Base.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (c) 2014, 2016, 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.jnr;
-
-import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.ioex;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
-
-import jnr.constants.platform.Errno;
-import jnr.ffi.LibraryLoader;
-import jnr.ffi.annotations.In;
-import jnr.ffi.annotations.Out;
-import jnr.posix.POSIX;
-import jnr.posix.POSIXFactory;
-
-public class JNR_Base implements BaseRFFI {
-    /**
-     * Functions missing from JNR POSIX.
-     */
-    public interface LibCX {
-        int getwd(@Out byte[] path);
-
-        long mkdtemp(@In @Out ByteBuffer template);
-
-        long strtol(@In String dir, @In String end, int base);
-
-        int uname(@In long[] utsname);
-    }
-
-    private static class LibCXProvider {
-        private static LibCX libcx;
-
-        @TruffleBoundary
-        private static LibCX createAndLoadLib() {
-            return LibraryLoader.create(LibCX.class).load("c");
-        }
-
-        static LibCX libcx() {
-            if (libcx == null) {
-                libcx = createAndLoadLib();
-            }
-            return libcx;
-        }
-    }
-
-    private static LibCX libcx() {
-        return LibCXProvider.libcx();
-    }
-
-    protected POSIX posix;
-
-    protected POSIX posix() {
-        if (posix == null) {
-            posix = POSIXFactory.getPOSIX();
-        }
-        return posix;
-    }
-
-    @Override
-    public int getpid() {
-        return posix().getpid();
-    }
-
-    @Override
-    public int setwd(String dir) {
-        return posix().chdir(dir);
-    }
-
-    @Override
-    public String getwd() {
-        byte[] buf = new byte[4096];
-        int rc = libcx().getwd(buf);
-        if (rc == 0) {
-            return null;
-        } else {
-            int i = 0;
-            while (buf[i] != 0 && i < buf.length) {
-                i++;
-            }
-            return new String(buf, 0, i);
-        }
-    }
-
-    @Override
-    public String readlink(String path) throws IOException {
-        String s = posix().readlink(path);
-        if (s == null) {
-            int n = posix().errno();
-            if (n == Errno.EINVAL.intValue()) {
-                // not a link
-            } else {
-                // some other error
-                throw ioex(Errno.valueOf(n).description());
-            }
-        }
-        return s;
-    }
-
-    @Override
-    public String mkdtemp(String template) {
-        ByteBuffer bb = ByteBuffer.wrap(template.getBytes());
-        long result = libcx().mkdtemp(bb);
-        if (result == 0) {
-            return null;
-        } else {
-            return new String(bb.array());
-        }
-    }
-
-    @Override
-    public void mkdir(String dir, int mode) throws IOException {
-        try {
-            posix().mkdir(dir, mode);
-        } catch (RuntimeException ex) {
-            throw ioex(Errno.valueOf(posix().errno()).description());
-        }
-    }
-
-    @Override
-    public int chmod(String path, int mode) {
-        return posix().chmod(path, mode);
-    }
-
-    @Override
-    public long strtol(String s, int base) throws IllegalArgumentException {
-        posix().errno(0);
-        long result = libcx().strtol(s, null, base);
-        int e = posix().errno();
-        if (e != 0) {
-            throw new IllegalArgumentException(Errno.valueOf(e).description());
-        } else {
-            return result;
-        }
-    }
-
-    @Override
-    public Object dlopen(String path, boolean local, boolean now) {
-        int flags = (local ? com.kenai.jffi.Library.LOCAL : com.kenai.jffi.Library.GLOBAL) | (now ? com.kenai.jffi.Library.NOW : com.kenai.jffi.Library.LAZY);
-        return com.kenai.jffi.Library.getCachedInstance(path, flags);
-    }
-
-    @Override
-    public long dlsym(Object handle, String symbol) {
-        return ((com.kenai.jffi.Library) handle).getSymbolAddress(symbol);
-    }
-
-    @Override
-    public int dlclose(Object handle) {
-        // TODO JNR provides no (public) way to close a library
-        return 1;
-    }
-
-    @Override
-    public String dlerror() {
-        return com.kenai.jffi.Library.getLastError();
-    }
-
-    @Override
-    public UtsName uname() {
-        return JNI_OSExtras.uname();
-    }
-
-    @Override
-    public ArrayList<String> glob(String pattern) {
-        return JNI_OSExtras.glob(pattern);
-    }
-}
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_Lapack.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_Lapack.java
deleted file mode 100644
index 89ecb117dc52f06dbec05834e7a83754d78bbd1f..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_Lapack.java
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
- * Copyright (c) 2015, 2016, 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.jnr;
-
-import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.wrapChar;
-import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.wrapDouble;
-import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.wrapInt;
-
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.r.runtime.ffi.LapackRFFI;
-
-import jnr.ffi.LibraryLoader;
-import jnr.ffi.annotations.In;
-import jnr.ffi.annotations.Out;
-
-public class JNR_Lapack implements LapackRFFI {
-    /**
-     * Fortran does call by reference for everything, which we handle with arrays. Evidently, this
-     * is not as efficient as it could be. This implementation assumes a single-threaded
-     * environment.
-     */
-    public interface Lapack {
-        // Checkstyle: stop method name
-        void ilaver_(@Out int[] major, @Out int[] minor, @Out int[] patch);
-
-        void dgeev_(@In byte[] jobVL, @In byte[] jobVR, @In int[] n, @In double[] a, @In int[] lda, @Out double[] wr, @Out double[] wi, @Out double[] vl, @In int[] ldvl, @Out double[] vr,
-                        @In int[] ldvr, @Out double[] work, @In int[] lwork, @Out int[] info);
-
-        void dgeqp3_(@In int[] m, @In int[] n, double[] a, @In int[] lda, int[] jpvt, @Out double[] tau, @Out double[] work, @In int[] lwork, @Out int[] info);
-
-        void dormqr_(@In byte[] side, @In byte[] trans, @In int[] m, @In int[] n, @In int[] k, @In double[] a, @In int[] lda, @In double[] tau, double[] c, @In int[] ldc, @Out double[] work,
-                        @In int[] lwork, @Out int[] info);
-
-        void dtrtrs_(@In byte[] uplo, @In byte[] trans, @In byte[] diag, @In int[] n, @In int[] nrhs, @In double[] a, @In int[] lda, double[] b, @In int[] ldb, @Out int[] info);
-
-        void dgetrf_(@In int[] m, @In int[] n, double[] a, @In int[] lda, @Out int[] ipiv, @Out int[] info);
-
-        void dpotrf_(@In byte[] uplo, @In int[] n, double[] a, @In int[] lda, @Out int[] info);
-
-        void dpstrf_(@In byte[] uplo, @In int[] n, double[] a, @In int[] lda, @Out int[] piv, @Out int[] rank, @In double[] tol, @Out double[] work, @Out int[] info);
-
-        void dgesv_(@In int[] n, @In int[] nrhs, double[] a, @In int[] lda, @Out int[] ipiv, double[] b, @In int[] ldb, @Out int[] info);
-
-        double dlange_(@In byte[] norm, @In int[] m, @In int[] n, @In double[] a, @In int[] lda, @Out double[] work);
-
-        void dgecon_(@In byte[] norm, @In int[] n, @In double[] a, @In int[] lda, @In double[] anorm, @Out double[] rcond, @Out double[] work, @Out int[] iwork, @Out int[] info);
-
-    }
-
-    private static class LapackProvider {
-        private static Lapack lapack;
-
-        @TruffleBoundary
-        private static Lapack createAndLoadLib() {
-            return LibraryLoader.create(Lapack.class).load("Rlapack");
-        }
-
-        static Lapack lapack() {
-            if (lapack == null) {
-                lapack = createAndLoadLib();
-            }
-            return lapack;
-        }
-    }
-
-    public static Lapack lapack() {
-        return LapackProvider.lapack();
-    }
-
-    @Override
-    @TruffleBoundary
-    public void ilaver(int[] version) {
-        int[] major = new int[1];
-        int[] minor = new int[1];
-        int[] patch = new int[1];
-        lapack().ilaver_(major, minor, patch);
-        version[0] = major[0];
-        version[1] = minor[0];
-        version[2] = patch[0];
-    }
-
-    @Override
-    @TruffleBoundary
-    public int dgeev(char jobVL, char jobVR, int n, double[] a, int lda, double[] wr, double[] wi, double[] vl, int ldvl, double[] vr, int ldvr, double[] work, int lwork) {
-        int[] info = new int[1];
-        lapack().dgeev_(wrapChar(jobVL), wrapChar(jobVR), wrapInt(n), a, wrapInt(lda), wr, wi, vl, wrapInt(ldvl), vr, wrapInt(ldvr), work, wrapInt(lwork), info);
-        return info[0];
-    }
-
-    @Override
-    @TruffleBoundary
-    public int dgeqp3(int m, int n, double[] a, int lda, int[] jpvt, double[] tau, double[] work, int lwork) {
-        int[] info = new int[1];
-        lapack().dgeqp3_(wrapInt(m), wrapInt(n), a, wrapInt(lda), jpvt, tau, work, wrapInt(lwork), info);
-        return info[0];
-    }
-
-    @Override
-    @TruffleBoundary
-    public int dormqr(char side, char trans, int m, int n, int k, double[] a, int lda, double[] tau, double[] c, int ldc, double[] work, int lwork) {
-        int[] info = new int[1];
-        lapack().dormqr_(wrapChar(side), wrapChar(trans), wrapInt(m), wrapInt(n), wrapInt(k), a, wrapInt(lda), tau, c, wrapInt(ldc), work, wrapInt(lwork), info);
-        return info[0];
-    }
-
-    @Override
-    @TruffleBoundary
-    public int dtrtrs(char uplo, char trans, char diag, int n, int nrhs, double[] a, int lda, double[] b, int ldb) {
-        int[] info = new int[1];
-        lapack().dtrtrs_(wrapChar(uplo), wrapChar(trans), wrapChar(diag), wrapInt(n), wrapInt(nrhs), a, wrapInt(lda), b, wrapInt(ldb), info);
-        return info[0];
-    }
-
-    @Override
-    @TruffleBoundary
-    public int dgetrf(int m, int n, double[] a, int lda, int[] ipiv) {
-        int[] info = new int[1];
-        lapack().dgetrf_(wrapInt(m), wrapInt(n), a, wrapInt(lda), ipiv, info);
-        return info[0];
-    }
-
-    @Override
-    @TruffleBoundary
-    public int dpotrf(char uplo, int n, double[] a, int lda) {
-        int[] info = new int[1];
-        lapack().dpotrf_(wrapChar(uplo), wrapInt(n), a, wrapInt(lda), info);
-        return info[0];
-    }
-
-    @Override
-    @TruffleBoundary
-    public int dpstrf(char uplo, int n, double[] a, int lda, int[] piv, int[] rank, double tol, double[] work) {
-        int[] info = new int[1];
-        lapack().dpstrf_(wrapChar(uplo), wrapInt(n), a, wrapInt(lda), piv, rank, wrapDouble(tol), work, info);
-        return info[0];
-    }
-
-    @Override
-    @TruffleBoundary
-    public int dgesv(int n, int nrhs, double[] a, int lda, int[] ipiv, double[] b, int ldb) {
-        int[] info = new int[1];
-        lapack().dgesv_(wrapInt(n), wrapInt(nrhs), a, wrapInt(lda), ipiv, b, wrapInt(ldb), info);
-        return info[0];
-    }
-
-    @Override
-    @TruffleBoundary
-    public double dlange(char norm, int m, int n, double[] a, int lda, double[] work) {
-        return lapack().dlange_(wrapChar(norm), wrapInt(m), wrapInt(n), a, wrapInt(lda), work);
-    }
-
-    @Override
-    @TruffleBoundary
-    public int dgecon(char norm, int n, double[] a, int lda, double anorm, double[] rcond, double[] work, int[] iwork) {
-        int[] info = new int[1];
-        lapack().dgecon_(wrapChar(norm), wrapInt(n), a, wrapInt(lda), wrapDouble(anorm), rcond, work, iwork, info);
-        return info[0];
-    }
-}
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_PCRE.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_PCRE.java
deleted file mode 100644
index 13cae21398ccdcf4a69361c7bad7119f33d8eea3..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_PCRE.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 2015, 2016, 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.jnr;
-
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.ffi.LibPaths;
-import com.oracle.truffle.r.runtime.ffi.PCRERFFI;
-
-import jnr.ffi.LibraryLoader;
-import jnr.ffi.annotations.In;
-import jnr.ffi.annotations.Out;
-
-/**
- * PCRE support using JNR.
- */
-// Checkstyle: stop method name
-public class JNR_PCRE implements PCRERFFI {
-    public interface PCRE {
-        long fastr_pcre_maketables();
-
-        long fastr_pcre_compile(byte[] pattern, int options, @Out byte[] errorMessage, @Out int[] errOffset, long tables);
-
-        int fastr_pcre_exec(long code, long extra, @In byte[] subject, int subjectLength, int startOffset, int options, @Out int[] ovector, int ovecSize);
-    }
-
-    private static class PCREProvider {
-        private static PCRE pcre;
-
-        @TruffleBoundary
-        private static PCRE createAndLoadLib() {
-            return LibraryLoader.create(PCRE.class).library(LibPaths.getBuiltinLibPath("R")).library("pcre").load();
-        }
-
-        static PCRE pcre() {
-            if (pcre == null) {
-                pcre = createAndLoadLib();
-            }
-            return pcre;
-        }
-    }
-
-    private static PCRE pcre() {
-        return PCREProvider.pcre();
-    }
-
-    @Override
-    public long maketables() {
-        return pcre().fastr_pcre_maketables();
-    }
-
-    @Override
-    public Result compile(String pattern, int options, long tables) {
-        int[] errOffset = new int[1];
-        byte[] errorMessage = new byte[512];
-        long result = pcre().fastr_pcre_compile(pattern.getBytes(), options, errorMessage, errOffset, tables);
-        if (result == 0) {
-            return new Result(result, new String(errorMessage), errOffset[0]);
-        } else {
-            return new Result(result, null, 0);
-        }
-    }
-
-    @Override
-    public int exec(long code, long extra, String subject, int offset, int options, int[] ovector) {
-        return pcre().fastr_pcre_exec(code, extra, subject.getBytes(), subject.length(), offset, options, ovector, ovector.length);
-    }
-
-    @Override
-    public Result study(long code, int options) {
-        throw RInternalError.unimplemented("pcre_study");
-    }
-}
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_RAppl.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_RAppl.java
deleted file mode 100644
index bee80bd631e5f05959bb6fdc30393a0a13a7118f..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_RAppl.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2014, 2016, 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.jnr;
-
-import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.wrapDouble;
-import static com.oracle.truffle.r.runtime.ffi.RFFIUtils.wrapInt;
-
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.r.runtime.ffi.RApplRFFI;
-
-import jnr.ffi.LibraryLoader;
-import jnr.ffi.annotations.In;
-import jnr.ffi.annotations.Out;
-
-//Checkstyle: stop method name
-public class JNR_RAppl implements RApplRFFI {
-    public interface Linpack {
-        void dqrdc2_(double[] x, @In int[] ldx, @In int[] n, @In int[] p, @In double[] tol, int[] rank, double[] qraux, int[] pivot, @Out double[] work);
-
-        void dqrcf_(double[] x, @In int[] n, @In int[] k, double[] qraux, double[] y, @In int[] ny, double[] b, int[] info);
-
-        void dqrls_(double[] x, @In int[] n, @In int[] p, @In double[] y, @In int[] ny, @In double[] tol, @Out double[] b, @Out double[] rsd, @Out double[] qty, @Out int[] k, int[] jpvt,
-                        @Out double[] qraux, @In double[] work);
-    }
-
-    private static class LinpackProvider {
-        private static Linpack linpack;
-
-        @TruffleBoundary
-        private static Linpack createAndLoadLib() {
-            // need to load blas lib as Fortran functions in appl lib need it
-            return LibraryLoader.create(Linpack.class).library("Rblas").library("R").load();
-        }
-
-        static Linpack linpack() {
-            if (linpack == null) {
-                linpack = createAndLoadLib();
-            }
-            return linpack;
-        }
-    }
-
-    public static Linpack linpack() {
-        return LinpackProvider.linpack();
-    }
-
-    @Override
-    @TruffleBoundary
-    public void dqrdc2(double[] x, int ldx, int n, int p, double tol, int[] rank, double[] qraux, int[] pivot, double[] work) {
-        linpack().dqrdc2_(x, wrapInt(ldx), wrapInt(n), wrapInt(p), wrapDouble(tol), rank, qraux, pivot, work);
-    }
-
-    @Override
-    @TruffleBoundary
-    public void dqrcf(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] b, int[] info) {
-        linpack().dqrcf_(x, wrapInt(n), wrapInt(k), qraux, y, wrapInt(ny), b, info);
-    }
-
-    @Override
-    @TruffleBoundary
-    public void dqrls(double[] x, int n, int p, double[] y, int ny, double tol, double[] b, double[] rsd, double[] qty, int[] k, int[] jpvt, double[] qraux, double[] work) {
-        linpack().dqrls_(x, wrapInt(n), wrapInt(p), y, wrapInt(ny), wrapDouble(tol), b, rsd, qty, k, jpvt, qraux, work);
-    }
-}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCompression.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCompression.java
index 48f915a75aa80d1c987ff58395aa36534cbf8a6f..785970bd521f4d6985aa39935494d65c5a51df3a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCompression.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCompression.java
@@ -123,16 +123,12 @@ public class RCompression {
     }
 
     private static boolean gzipCompress(byte[] udata, byte[] cdata) {
-        long[] cdatalen = new long[1];
-        cdatalen[0] = cdata.length;
-        int rc = RFFIFactory.getRFFI().getZipRFFI().compress(cdata, cdatalen, udata);
+        int rc = RFFIFactory.getRFFI().getZipRFFI().compress(cdata, udata);
         return rc == 0;
     }
 
     private static boolean gzipUncompress(byte[] udata, byte[] data) {
-        long[] destlen = new long[1];
-        destlen[0] = udata.length;
-        int rc = RFFIFactory.getRFFI().getZipRFFI().uncompress(udata, destlen, data);
+        int rc = RFFIFactory.getRFFI().getZipRFFI().uncompress(udata, data);
         return rc == 0;
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CallRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CallRFFI.java
index 96d6bc3ad112816ecc3013c3b7ff26a52b2fce59..76c8f10cd072e5f36abdb14b96dbb7566140a538 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CallRFFI.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CallRFFI.java
@@ -43,8 +43,9 @@ public interface CallRFFI {
     void invokeVoidCall(long address, String name, Object[] args);
 
     /**
-     * This interface is initialized very early, before the {@code tempDir} is established. This
-     * call sets the value.
+     * This interface is instantiated very early and sets the FFI global variables as part of that
+     * process. However, at that stage {@code tempDir} is not established so this call exists to set
+     * the value later.
      */
     void setTempDir(String tempDir);
 
@@ -53,5 +54,4 @@ public interface CallRFFI {
      */
     void setInteractive(boolean interactive);
 
-    double exactSum(double[] values, boolean hasNa, boolean naRm);
 }
diff --git a/com.oracle.truffle.r.native/osextras/src/doglob.c b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/MiscRFFI.java
similarity index 55%
rename from com.oracle.truffle.r.native/osextras/src/doglob.c
rename to com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/MiscRFFI.java
index a26e7f67eac0d6d3b29e98627b9efe51e9752523..28ad96a3b65095f9363cfab470a76e9078a8a576 100644
--- a/com.oracle.truffle.r.native/osextras/src/doglob.c
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/MiscRFFI.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2016, 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
@@ -20,28 +20,13 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-#include <string.h>
-#include <glob.h>
-#include <jni.h>
+package com.oracle.truffle.r.runtime.ffi;
 
-static jmethodID addPathID = 0;
-
-JNIEXPORT void JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jnr_JNI_1Glob_doglob(JNIEnv *env, jobject obj, jstring pattern) {
-	glob_t globstruct;
-
-	if (addPathID == 0) {
-		addPathID = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, obj), "addPath", "(Ljava/lang/String;)V");
-	}
+/**
+ * Miscellaneous methods implemented in native code.
+ *
+ */
+public interface MiscRFFI {
+    double exactSum(double[] values, boolean hasNa, boolean naRm);
 
-	const char *patternChars = (*env)->GetStringUTFChars(env, pattern, NULL);
-	int rc = glob(patternChars, 0, NULL, &globstruct);
-	if (rc == 0) {
-		int i;
-		for (i = 0; i < globstruct.gl_pathc; i++) {
-			char *path = globstruct.gl_pathv[i];
-			jstring pathString = (*env)->NewStringUTF(env, path);
-			(*env)->CallVoidMethod(env, obj, addPathID, pathString);
-		}
-	}
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFI.java
index 841567fef07f38e99e8b1554a47de817c8e0028b..a88e98267e13b5ad8847235b47cb76fc1fbdf153 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFI.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFI.java
@@ -40,6 +40,7 @@ package com.oracle.truffle.r.runtime.ffi;
  * <li>{@link PCRERFFI}: interface to PCRE library (Perl regexp).</li>
  * <li>{@link ZipRFFI}: interface to zip compression</li>
  * <li>{@link REmbedRFFI}: interface to embedded support</li>
+ * <li>{@link MiscRFFI}: interface to miscellaneous native functions</li>
  * </ul>
  *
  * These interfaces may be implemented by one or more providers, specified either when the FastR
@@ -70,4 +71,6 @@ public interface RFFI {
 
     REmbedRFFI getREmbedRFFI();
 
+    MiscRFFI getMiscRFFI();
+
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java
index c20087b3659bc3ec93056bf5704afe7a88eb2ae3..8a873a05f00693e453823f745b46d6bcd8d54b89 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java
@@ -66,49 +66,5 @@ public abstract class RFFIFactory {
      */
     protected abstract RFFI createRFFI();
 
-    public LapackRFFI getLapackRFFI() {
-        throw missing("Lapack");
-    }
-
-    public StatsRFFI getStatsRFFI() {
-        throw missing("Stats");
-    }
-
-    public ToolsRFFI getToolsRFFI() {
-        throw missing("Tools");
-    }
-
-    public GridRFFI getGridRFFI() {
-        throw missing("Grid");
-    }
-
-    public RApplRFFI getRApplRFFI() {
-        throw missing("RDerived");
-    }
-
-    public CRFFI getCRFFI() {
-        throw missing("C");
-    }
-
-    public CallRFFI getCallRFFI() {
-        throw missing("Call");
-    }
-
-    public UserRngRFFI getUserRngRFFI() {
-        throw missing("UserRNG");
-    }
-
-    public PCRERFFI getPCRERFFI() {
-        throw missing("PCRE");
-    }
-
-    public ZipRFFI getZipRFFI() {
-        throw missing("Zip");
-    }
-
-    private static RuntimeException missing(String ffi) throws RuntimeException {
-        throw Utils.rSuicide(ffi + " FFI not implemented");
-    }
-
     public abstract ContextState newContextState();
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/ZipRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/ZipRFFI.java
index a6b88ffe667a4f7a9fb538496fefb7f378330435..a829c8c9277e68a30da76529ed5d09df4127ad76 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/ZipRFFI.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/ZipRFFI.java
@@ -30,13 +30,13 @@ public interface ZipRFFI {
      *
      * @return standard return code (0 ok)
      */
-    int compress(byte[] dest, long[] destlen, byte[] source);
+    int compress(byte[] dest, byte[] source);
 
     /**
      * uncompress {@code source} into {@code dest}.
      *
      * @return standard return code (0 ok)
      */
-    int uncompress(byte[] dest, long[] destlen, byte[] source);
+    int uncompress(byte[] dest, byte[] source);
 
 }
diff --git a/mx.fastr/mx_fastr.py b/mx.fastr/mx_fastr.py
index 21c7f2a7e6c9b09094360af739fbcdbd7f2ec0fb..d7d3804ec6c5c531dbe9a72be681639b7ec8aac3 100644
--- a/mx.fastr/mx_fastr.py
+++ b/mx.fastr/mx_fastr.py
@@ -28,6 +28,7 @@ import mx_gate
 import mx_fastr_pkgs
 import mx_fastr_dists
 from mx_fastr_dists import FastRNativeProject, FastRTestNativeProject, FastRReleaseProject #pylint: disable=unused-import
+import mx_findlib
 import os
 
 '''
@@ -533,6 +534,7 @@ _commands = {
     'pkgtest' : [mx_fastr_pkgs.pkgtest, ['options']],
     'installpkgs' : [mx_fastr_pkgs.installpkgs, '[options]'],
     'mkgramrd': [mx_fastr_mkgramrd.mkgramrd, '[options]'],
+    'rfindlib' : [mx_findlib.findlib, '[]'],
     }
 
 mx.update_commands(_fastr_suite, _commands)
diff --git a/mx.fastr/mx_findlib.py b/mx.fastr/mx_findlib.py
new file mode 100644
index 0000000000000000000000000000000000000000..c5b07cc67ca9d83887fd07a9dddbd1ad6ddb9ce4
--- /dev/null
+++ b/mx.fastr/mx_findlib.py
@@ -0,0 +1,52 @@
+#
+# Copyright (c) 2016, 2016, 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.
+#
+import os
+import platform
+import mx
+
+def findlib(args):
+    '''
+    GNU R is built using GNUR_LDFLAGS_OVERRIDE to specify the location of necessary external libraries,
+    but this isn't captured anywhere, so we re-analyze here
+    '''
+    if not os.environ.has_key('GNUR_LDFLAGS_OVERRIDE'):
+        mx.abort('GNUR_LDFLAGS_OVERRIDE is not set')
+    parts = os.environ['GNUR_LDFLAGS_OVERRIDE'].split(' ')
+    ext = '.dylib' if platform.system() == 'Darwin' else '.so'
+    name = 'lib' + args[0] + ext
+    for part in parts:
+        path = part.lstrip('-I')
+        for f in os.listdir(path):
+            if name == f:
+                mx.log(os.path.join(path, f))
+                return 0
+    # if Linux try LD_LBRARY_PATH
+    if platform.system() == 'Linux':
+        if os.environ.has_key('LD_LIBRARY_PATH'):
+            ldpaths = os.environ['LD_LIBRARY_PATH'].split(":")
+            for ldpath in ldpaths:
+                for f in os.listdir(ldpath):
+                    if name == f:
+                        mx.log(os.path.join(ldpath, f))
+                        return 0
+    mx.abort(name + ' not found')
diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py
index 86b02137658883cbf7d6b8f9c31a7bb090c24348..90ac4b2f66d2b57da1f2803ca4ebc958660053a5 100644
--- a/mx.fastr/suite.py
+++ b/mx.fastr/suite.py
@@ -90,95 +90,6 @@ suite = {
       "sha1" : "ebb4b995fd67a9b291ea5b19379509160f56e154",
     },
 
-    "JNR_POSIX" : {
-      "urls" : [
-        "https://search.maven.org/remotecontent?filepath=com/github/jnr/jnr-posix/3.0.29/jnr-posix-3.0.29.jar",
-      ],
-      "sha1" : "bc3d222cb0eae5bc59f733ee8ca9d005e3d2666f",
-    },
-
-    "JNR_CONSTANTS" : {
-      "urls" : [
-        "https://search.maven.org/remotecontent?filepath=com/github/jnr/jnr-constants/0.9.2/jnr-constants-0.9.2.jar",
-      ],
-      "sha1" : "9392eabda021cfc4ca202c762ddebf1b5afb147e",
-    },
-
-    "JNR_FFI" : {
-      "path" : "lib/jnr-ffi-2.0.9.jar",
-      "urls" : [
-        "https://search.maven.org/remotecontent?filepath=com/github/jnr/jnr-ffi/2.0.9/jnr-ffi-2.0.9.jar",
-      ],
-      "sha1" : "f1306974f7a56de98fb816f30d40fdc199590b63",
-    },
-
-    "JFFI" : {
-      "urls" : [
-        "https://search.maven.org/remotecontent?filepath=com/github/jnr/jffi/1.2.12/jffi-1.2.12.jar",
-      ],
-      "sha1" : "a9f12011e9f5c1b363ecf3b51998058a18a48d26",
-    },
-
-    "JFFI_NATIVE" : {
-      "urls" : [
-        "https://search.maven.org/remotecontent?filepath=com/github/jnr/jffi/1.2.12/jffi-1.2.12-native.jar",
-      ],
-      "sha1" : "f3bd969534ea4a743cb736f09fb7ec2a35405bc1",
-    },
-
-    "JNR_INVOKE" : {
-      "urls" : ["https://search.maven.org/remotecontent?filepath=com/github/jnr/jnr-invoke/0.1/jnr-invoke-0.1.jar"],
-      "sha1" : "d0f846c3d3cb98dfd5e2bbd3cca236337fb0afa1",
-    },
-
-    "JNR_UDIS86" : {
-      "urls" : ["https://search.maven.org/remotecontent?filepath=com/github/jnr/jnr-udis86/0.1/jnr-udis86-0.1.jar"],
-      "sha1" : "88accfa82203ea74a4a82237061c28ac8b4224af",
-    },
-
-    "JNR_X86ASM" : {
-      "urls" : [
-        "https://search.maven.org/remotecontent?filepath=com/github/jnr/jnr-x86asm/1.0.2/jnr-x86asm-1.0.2.jar",
-      ],
-      "sha1" : "006936bbd6c5b235665d87bd450f5e13b52d4b48",
-    },
-
-    "ASM" : {
-      "urls" : [
-        "https://search.maven.org/remotecontent?filepath=org/ow2/asm/asm/5.0.3/asm-5.0.3.jar",
-      ],
-      "sha1" : "dcc2193db20e19e1feca8b1240dbbc4e190824fa",
-    },
-
-    "ASM_ANALYSIS" : {
-      "urls" : [
-        "https://search.maven.org/remotecontent?filepath=org/ow2/asm/asm-analysis/4.0/asm-analysis-4.0.jar",
-      ],
-      "sha1" : "1c45d52b6f6c638db13cf3ac12adeb56b254cdd7",
-    },
-
-    "ASM_COMMONS" : {
-      "urls" : [
-        "https://search.maven.org/remotecontent?filepath=org/ow2/asm/asm-commons/4.0/asm-commons-4.0.jar",
-      ],
-      "sha1" : "a839ec6737d2b5ba7d1878e1a596b8f58aa545d9",
-    },
-
-    "ASM_TREE" : {
-      "urls" : [
-        "https://search.maven.org/remotecontent?filepath=org/ow2/asm/asm-tree/4.0/asm-tree-4.0.jar",
-      ],
-      "sha1" : "67bd266cd17adcee486b76952ece4cc85fe248b8",
-    },
-
-    "ASM_UTIL" : {
-      "urls" : [
-        "https://search.maven.org/remotecontent?filepath=org/ow2/asm/asm-util/4.0/asm-util-4.0.jar",
-      ],
-      "sha1" : "d7a65f54cda284f9706a750c23d64830bb740c39",
-    },
-
-
   },
 
   "projects" : {
@@ -313,20 +224,6 @@ suite = {
       "sourceDirs" : ["src"],
       "dependencies" : [
         "com.oracle.truffle.r.runtime",
-        "ASM",
-        "ASM_ANALYSIS",
-        "JNR_POSIX",
-        "ASM_UTIL",
-        "JFFI",
-        "JNR_FFI",
-        "JNR_CONSTANTS",
-        "JFFI_NATIVE",
-        "JNR_INVOKE",
-        "JNR_UDIS86",
-        "ASM",
-        "ASM_TREE",
-        "ASM_COMMONS",
-        "JNR_X86ASM",
       ],
       "checkstyle" : "com.oracle.truffle.r.runtime",
       "javaCompliance" : "1.8",
@@ -390,20 +287,6 @@ suite = {
       "mainClass" : "com.oracle.truffle.r.engine.shell.RCommand",
       "exclude" : [
         "JDK_TOOLS",
-        "ASM",
-        "ASM_UTIL",
-        "ASM_TREE",
-        "ASM_COMMONS",
-        "ASM_ANALYSIS",
-        "ASM",
-        "JNR_X86ASM",
-        "JFFI_NATIVE",
-        "JFFI",
-        "JNR_FFI",
-        "JNR_CONSTANTS",
-        "JNR_POSIX",
-        "JNR_INVOKE",
-        "JNR_UDIS86",
         "truffle:JLINE",
         "ANTLR-C-3.5",
         "ANTLR-3.5",