diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/tools/RConnGetCCall.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/tools/RConnGetCCall.java
new file mode 100644
index 0000000000000000000000000000000000000000..d1843bda4ef40b23f6e3340e25745bacf0a19454
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/tools/RConnGetCCall.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.ffi.impl.interop.tools;
+
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
+
+public class RConnGetCCall implements RTruffleObject {
+    public static boolean isInstance(TruffleObject value) {
+        return value instanceof RConnGetCCall;
+    }
+
+    @Override
+    public ForeignAccess getForeignAccess() {
+        return RConnGetCCallMRForeign.ACCESS;
+    }
+
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/tools/RConnGetCCallMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/tools/RConnGetCCallMR.java
new file mode 100644
index 0000000000000000000000000000000000000000..77605f4c403f993ae9de6040cabe805c4285e872
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/tools/RConnGetCCallMR.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.ffi.impl.interop.tools;
+
+import java.io.IOException;
+
+import com.oracle.truffle.api.interop.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.conn.RConnection;
+
+@MessageResolution(receiverType = RConnGetCCall.class)
+public class RConnGetCCallMR {
+    @Resolve(message = "EXECUTE")
+    public abstract static class RConnGetCCallExecute extends Node {
+        protected java.lang.Object access(@SuppressWarnings("unused") RConnGetCCall receiver, Object[] arguments) {
+            try {
+                return ((RConnection) arguments[0]).getc();
+            } catch (IOException ex) {
+                return -1;
+            }
+        }
+    }
+
+    @Resolve(message = "IS_EXECUTABLE")
+    public abstract static class RConnGetCCallIsExecutable extends Node {
+        protected Object access(@SuppressWarnings("unused") RConnGetCCall receiver) {
+            return true;
+        }
+    }
+
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Lapack.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Lapack.java
index f176f495f889174f351dd6c8e117949a838ababc..bb37da5ddb5a1226022cce5129b39349ea01e459 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Lapack.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Lapack.java
@@ -32,6 +32,7 @@ import com.oracle.truffle.r.ffi.impl.common.LibPaths;
 import com.oracle.truffle.r.ffi.impl.interop.NativeDoubleArray;
 import com.oracle.truffle.r.ffi.impl.interop.NativeIntegerArray;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
 import com.oracle.truffle.r.runtime.ffi.DLLRFFI;
@@ -75,8 +76,7 @@ public class TruffleLLVM_Lapack implements LapackRFFI {
     }
 
     private static RootCallTarget openLLVMLibraries() {
-        DLLRFFI.DLOpenRootNode rootNode = DLLRFFI.DLOpenRootNode.create();
-        return rootNode.getCallTarget();
+        return DLLRFFI.DLOpenRootNode.create(RContext.getInstance());
     }
 
     private static RootCallTarget openNativeLibraries() {
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_CAccess.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_CAccess.java
index 455749f2a40242522a4a3f6bf2eb8b8c49eff301..abf88e618ab4b4038d2ffe8163b34cba7854ec85 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_CAccess.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_CAccess.java
@@ -29,6 +29,7 @@ import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.ffi.impl.common.LibPaths;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.ffi.DLLRFFI;
 
@@ -51,7 +52,7 @@ public class TruffleNFI_CAccess {
 
         public TruffleObject getSymbolFunction() {
             if (handle == null) {
-                handle = (TruffleNFI_DLL.NFIHandle) DLLRFFI.DLOpenRootNode.create().getCallTarget().call(LibPaths.getBuiltinLibPath("caccess"), true, true);
+                handle = (TruffleNFI_DLL.NFIHandle) DLLRFFI.DLOpenRootNode.create(RContext.getInstance()).call(LibPaths.getBuiltinLibPath("caccess"), true, true);
             }
             if (symbolFunction == null) {
                 DLL.SymbolHandle symbolHandle = (DLL.SymbolHandle) DLLRFFI.DLSymRootNode.create().getCallTarget().call(handle, cName());
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Call.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Call.java
index b23501a1d05665284eda1bb6c5036f8c122948af..c9c523c07ce5356ce16f41b62efb46204283c54b 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Call.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Call.java
@@ -50,7 +50,7 @@ import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
 public class TruffleNFI_Call implements CallRFFI {
 
     private enum INIT_VAR_FUN {
-        OBJ("(sint32, object) : void"),
+        OBJ("(env, sint32, object) : void"),
         DOUBLE("(sint32, double): void"),
         STRING("(sint32, string): void"),
         INT("(sint32, sint32) : void");
@@ -122,7 +122,7 @@ public class TruffleNFI_Call implements CallRFFI {
         try {
             Callbacks.createCalls(upCallsImpl);
             for (Callbacks callback : Callbacks.values()) {
-                String addCallbackSignature = String.format("(sint32, %s): void", callback.nfiSignature);
+                String addCallbackSignature = String.format("(env, sint32, %s): void", callback.nfiSignature);
                 TruffleObject addCallbackFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, symbolHandle.asTruffleObject(), "bind", addCallbackSignature);
                 ForeignAccess.sendExecute(executeNode, addCallbackFunction, callback.ordinal(), callback.call);
             }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_PkgInit.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_PkgInit.java
index bab18c4333a12d42a732c7379d8247b52f033353..cac38b61b9f97b3ef7d41731f27f212ce182311c 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_PkgInit.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_PkgInit.java
@@ -133,7 +133,7 @@ public final class TruffleNFI_PkgInit {
         try {
             for (UpCall upCall : UpCall.values()) {
                 Object upCallMethodObject = ForeignAccess.sendRead(readNode, upCallsObject, upCall.name());
-                String addCallbackSignature = String.format("(sint32, %s): void", upCall.signature);
+                String addCallbackSignature = String.format("(env, sint32, %s): void", upCall.signature);
                 TruffleObject addCallbackFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, symbolHandle.asTruffleObject(), "bind", addCallbackSignature);
                 ForeignAccess.sendExecute(executeNode, addCallbackFunction, upCall.ordinal(), upCallMethodObject);
             }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_RFFIFactory.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_RFFIFactory.java
index 3cd9176a1b7776ec495f379862cb761974075f1b..bde10e1f4de16e30ac8c5560515c5b0bab8f899e 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_RFFIFactory.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_RFFIFactory.java
@@ -48,9 +48,12 @@ public class TruffleNFI_RFFIFactory extends RFFIFactory implements RFFI {
     private static class ContextStateImpl implements RContext.ContextState {
         @Override
         public ContextState initialize(RContext context) {
+            String librffiPath = LibPaths.getBuiltinLibPath("R");
             if (context.isInitial()) {
-                String librffiPath = LibPaths.getBuiltinLibPath("R");
                 DLL.loadLibR(librffiPath);
+            } else {
+                // force initialization of NFI
+                DLLRFFI.DLOpenRootNode.create(context).call(librffiPath, false, false);
             }
             return this;
         }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Tools.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Tools.java
index 1d4d9c202ad4f136f2ea9e7d3536e98e6e2a672c..d9fa3345f779223257c442449a99c63ca25c2365 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Tools.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Tools.java
@@ -22,20 +22,17 @@
  */
 package com.oracle.truffle.r.ffi.impl.nfi;
 
-import java.io.IOException;
-
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.InteropException;
 import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.ffi.impl.common.Generic_Tools;
-import com.oracle.truffle.r.ffi.impl.common.RFFIUtils;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.ffi.impl.interop.tools.RConnGetCCall;
 import com.oracle.truffle.r.runtime.conn.RConnection;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.data.RStringVector;
-import com.oracle.truffle.r.runtime.data.RTruffleObject;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo;
@@ -46,24 +43,6 @@ import com.oracle.truffle.r.runtime.ffi.ToolsRFFI;
 public class TruffleNFI_Tools implements ToolsRFFI {
 
     private static class TruffleNFI_ToolsRFFINode extends Generic_Tools.Generic_ToolsRFFINode {
-        private interface RConnGetC {
-            int getc(RConnection conn);
-        }
-
-        private static class RConnGetCImpl implements RConnGetC, RTruffleObject {
-            @Override
-            public int getc(RConnection conn) {
-                RFFIUtils.traceUpCall("getc");
-                try {
-                    int r = conn.getc();
-                    RFFIUtils.traceUpCallReturn("getc", r);
-                    return r;
-                } catch (IOException ex) {
-                    return -1;
-                }
-            }
-        }
-
         private static boolean initialized;
 
         @Child private DLLRFFI.DLSymNode dysymNode = DLLRFFI.DLSymNode.create();
@@ -86,8 +65,8 @@ public class TruffleNFI_Tools implements ToolsRFFI {
             Node bind = Message.createInvoke(1).createNode();
             Node executeNode = Message.createExecute(1).createNode();
             try {
-                TruffleObject function = (TruffleObject) ForeignAccess.sendInvoke(bind, symbolHandle.asTruffleObject(), "bind", "((object): sint32): void");
-                ForeignAccess.sendExecute(executeNode, function, new RConnGetCImpl());
+                TruffleObject function = (TruffleObject) ForeignAccess.sendInvoke(bind, symbolHandle.asTruffleObject(), "bind", "(env, (object): sint32): void");
+                ForeignAccess.sendExecute(executeNode, function, new RConnGetCCall());
             } catch (InteropException t) {
                 throw RInternalError.shouldNotReachHere(t);
             }
diff --git a/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/FFIProcessor.java b/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/FFIProcessor.java
index e413931ca4d468f9fba2698305c89380133e0d49..a4623218d73a45941398777933459fb8fa86935f 100644
--- a/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/FFIProcessor.java
+++ b/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/FFIProcessor.java
@@ -341,12 +341,16 @@ public final class FFIProcessor extends AbstractProcessor {
                 return "uint8";
             case "int":
                 return "sint32";
+            case "long":
+                return "sint64";
             case "double":
                 return "double";
             case "void":
                 return "void";
             case "int[]":
                 return "[sint32]";
+            case "long[]":
+                return "[sint64]";
             case "double[]":
                 return "[double]";
             case "byte[]":
diff --git a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h
index a064a07ce8f21f2e372eedfc7aa32c4baa0946f5..48d0c6dc45acf72d59a8346ce01fcc188e5dd07b 100644
--- a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h
+++ b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h
@@ -270,7 +270,7 @@ typedef SEXP (*call_R_BaseNamespace)();
 typedef SEXP (*call_R_MethodsNamespace)();
 typedef SEXP (*call_R_GlobalEnv)();
 typedef SEXP (*call_R_NamespaceRegistry)();
-typedef SEXP (*call_R_Interactive)();
+typedef int (*call_R_Interactive)();
 typedef SEXP (*call_R_GlobalContext)();
 typedef SEXP (*call_R_CHAR)(SEXP x);
 typedef char *(*call_R_HomeDir)();
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rdynload_fastr.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rdynload_fastr.c
index 4a0ffaaae603d76c60e22df03ca9641d731431a9..1969c0253b620eda6c3f70831768ac87cd019436 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rdynload_fastr.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rdynload_fastr.c
@@ -23,8 +23,8 @@ static int (*call_forceSymbols)(DllInfo *dllInfo, Rboolean value);
 #define setDotSymbolValues_x 2
 #define forceSymbols_x 3
 
-void Rdynload_init(int index, void* closure) {
-	newClosureRef(closure);
+void Rdynload_init(TruffleEnv* env, int index, void* closure) {
+	(*env)->newClosureRef(env, closure);
 	switch (index) {
 	case registerRoutines_x: call_registerRoutines = closure; break;
 	case useDynamicSymbols_x: call_useDynamicSymbols = closure; break;
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rinternals.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rinternals.c
index 3b3f98f0e92d49c839336c08bcb25a2c7c6941a2..6b5569d2973f0d2bf0b3b963739adfe56a445955 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rinternals.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rinternals.c
@@ -27,11 +27,16 @@
 
 void **callbacks = NULL;
 
-void Rinternals_addCallback(int index, void *closure) {
+static TruffleContext* truffleContext = NULL;
+
+void Rinternals_addCallback(TruffleEnv* env, int index, void *closure) {
+    if (truffleContext == NULL) {
+        truffleContext = (*env)->getTruffleContext(env);
+    }
 	if (callbacks == NULL) {
 		callbacks = malloc(UPCALLS_TABLE_SIZE * sizeof(void*));
 	}
-	newClosureRef(closure);
+	(*env)->newClosureRef(env, closure);
 	callbacks[index] = closure;
 }
 
@@ -104,7 +109,7 @@ CTXT FASTR_GlobalContext() {
 }
 
 Rboolean FASTR_R_Interactive() {
-	return (int) ((call_R_Interactive) callbacks[R_Interactive_x])();
+	return ((call_R_Interactive) callbacks[R_Interactive_x])();
 }
 
 SEXP CAR(SEXP e) {
@@ -368,7 +373,7 @@ SEXP Rf_shallow_duplicate(SEXP x) {
 }
 
 R_xlen_t Rf_any_duplicated(SEXP x, Rboolean from_last) {
-	return (R_xlen_t) ((call_Rf_any_duplicated) callbacks[Rf_any_duplicated_x])(x, from_last);
+	return ((call_Rf_any_duplicated) callbacks[Rf_any_duplicated_x])(x, from_last);
 }
 
 SEXP Rf_duplicated(SEXP x, Rboolean y) {
@@ -389,11 +394,12 @@ void Rf_copyVector(SEXP x, SEXP y) {
 }
 
 int Rf_countContexts(int x, int y) {
-	return (int) unimplemented("Rf_countContexts");
+	unimplemented("Rf_countContexts");
+	return 0;
 }
 
 Rboolean Rf_inherits(SEXP x, const char * klass) {
-	return (Rboolean) ((call_Rf_inherits) callbacks[Rf_inherits_x])(x, klass);
+	return ((call_Rf_inherits) callbacks[Rf_inherits_x])(x, klass);
 }
 
 Rboolean Rf_isObject(SEXP s) {
@@ -414,16 +420,16 @@ SEXP Rf_installChar(SEXP charsxp) {
 }
 
 Rboolean Rf_isNull(SEXP s) {
-	return (Rboolean) ((call_Rf_isNull) callbacks[Rf_isNull_x])(s);
+	return ((call_Rf_isNull) callbacks[Rf_isNull_x])(s);
 }
 
 Rboolean Rf_isString(SEXP s) {
-	return (Rboolean) ((call_Rf_isString) callbacks[Rf_isString_x])(s);
+	return ((call_Rf_isString) callbacks[Rf_isString_x])(s);
 }
 
 Rboolean R_cycle_detected(SEXP s, SEXP child) {
 	unimplemented("R_cycle_detected");
-	return 0;
+	return FALSE;
 }
 
 cetype_t Rf_getCharCE(SEXP x) {
@@ -438,11 +444,11 @@ const char *Rf_reEnc(const char *x, cetype_t ce_in, cetype_t ce_out, int subst)
 }
 
 int Rf_ncols(SEXP x) {
-	return (int) ((call_Rf_ncols) callbacks[Rf_ncols_x])(x);
+	return ((call_Rf_ncols) callbacks[Rf_ncols_x])(x);
 }
 
 int Rf_nrows(SEXP x) {
-	return (int) ((call_Rf_nrows) callbacks[Rf_nrows_x])(x);
+	return ((call_Rf_nrows) callbacks[Rf_nrows_x])(x);
 }
 
 
@@ -856,11 +862,12 @@ double Rf_asReal(SEXP x) {
 
 Rcomplex Rf_asComplex(SEXP x){
 	unimplemented("Rf_asComplex");
-	Rcomplex c; return c;
+	Rcomplex c;
+	return c;
 }
 
 int TYPEOF(SEXP x) {
-	return (int) ((call_TYPEOF) callbacks[TYPEOF_x])(x);
+	return ((call_TYPEOF) callbacks[TYPEOF_x])(x);
 }
 
 SEXP ATTRIB(SEXP x){
@@ -869,7 +876,7 @@ SEXP ATTRIB(SEXP x){
 }
 
 int OBJECT(SEXP x){
-	return (int) ((call_OBJECT) callbacks[OBJECT_x])(x);
+	return ((call_OBJECT) callbacks[OBJECT_x])(x);
 }
 
 int MARK(SEXP x){
@@ -878,7 +885,7 @@ int MARK(SEXP x){
 }
 
 int NAMED(SEXP x){
-	return (int) ((call_NAMED) callbacks[NAMED_x])(x);
+	return ((call_NAMED) callbacks[NAMED_x])(x);
 }
 
 int REFCNT(SEXP x){
@@ -919,11 +926,12 @@ void R_qsort_int_I(int *iv, int *II, int i, int j) {
 }
 
 R_len_t R_BadLongVector(SEXP x, const char *y, int z) {
-	return (R_len_t) unimplemented("R_BadLongVector");
+    unimplemented("R_BadLongVector");
+	return 0;
 }
 
 int IS_S4_OBJECT(SEXP x) {
-	return (int) ((call_IS_S4_OBJECT) callbacks[IS_S4_OBJECT_x])(x);
+	return ((call_IS_S4_OBJECT) callbacks[IS_S4_OBJECT_x])(x);
 }
 
 void SET_S4_OBJECT(SEXP x) {
@@ -935,7 +943,8 @@ void UNSET_S4_OBJECT(SEXP x) {
 }
 
 Rboolean R_ToplevelExec(void (*fun)(void *), void *data) {
-	return (Rboolean) unimplemented("R_ToplevelExec");
+	unimplemented("R_ToplevelExec");
+	return FALSE;
 }
 
 SEXP R_ExecWithCleanup(SEXP (*fun)(void *), void *data,
@@ -961,7 +970,8 @@ SEXP R_FindPackageEnv(SEXP info) {
 }
 
 Rboolean R_IsNamespaceEnv(SEXP rho) {
-	return (Rboolean) unimplemented("R_IsNamespaceEnv");
+	unimplemented("R_IsNamespaceEnv");
+	return FALSE;
 }
 
 SEXP R_FindNamespace(SEXP info) {
@@ -993,16 +1003,17 @@ void R_MakeActiveBinding(SEXP sym, SEXP fun, SEXP env) {
 }
 
 Rboolean R_BindingIsLocked(SEXP sym, SEXP env) {
-	return (Rboolean) ((call_R_BindingIsLocked) callbacks[R_BindingIsLocked_x])(sym, env);
+	return ((call_R_BindingIsLocked) callbacks[R_BindingIsLocked_x])(sym, env);
 }
 
 Rboolean R_BindingIsActive(SEXP sym, SEXP env) {
     // TODO: for now, I believe all bindings are false
-    return (Rboolean)0;
+    return FALSE;
 }
 
 Rboolean R_HasFancyBindings(SEXP rho) {
-	return (Rboolean) unimplemented("R_HasFancyBindings");
+    unimplemented("R_HasFancyBindings");
+	return FALSE;
 }
 
 Rboolean Rf_isS4(SEXP x) {
@@ -1011,10 +1022,12 @@ Rboolean Rf_isS4(SEXP x) {
 
 SEXP Rf_asS4(SEXP x, Rboolean b, int i) {
 	unimplemented("Rf_asS4");
+	return NULL;
 }
 
 static SEXP R_tryEvalInternal(SEXP x, SEXP y, int *ErrorOccurred, int silent) {
 	unimplemented("R_tryEvalInternal");
+	return NULL;
 }
 
 SEXP R_tryEval(SEXP x, SEXP y, int *ErrorOccurred) {
@@ -1088,7 +1101,6 @@ void R_RegisterCFinalizer(SEXP s, R_CFinalizer_t fun) {
 
 void R_RegisterFinalizerEx(SEXP s, SEXP fun, Rboolean onexit) {
 	// TODO implement, but not fail for now
-
 }
 
 void R_RegisterCFinalizerEx(SEXP s, R_CFinalizer_t fun, Rboolean onexit) {
@@ -1101,18 +1113,22 @@ void R_RunPendingFinalizers(void) {
 
 SEXP R_MakeWeakRef(SEXP key, SEXP val, SEXP fin, Rboolean onexit) {
 	unimplemented("R_MakeWeakRef");
+	return NULL;
 }
 
 SEXP R_MakeWeakRefC(SEXP key, SEXP val, R_CFinalizer_t fin, Rboolean onexit) {
 	unimplemented("R_MakeWeakRefC");
+	return NULL;
 }
 
 SEXP R_WeakRefKey(SEXP w) {
 	unimplemented("R_WeakRefKey");
+	return NULL;
 }
 
 SEXP R_WeakRefValue(SEXP w) {
 	unimplemented("R_WeakRefValue");
+	return NULL;
 }
 
 void R_RunWeakRefFinalizer(SEXP w) {
@@ -1128,7 +1144,8 @@ SEXP R_do_slot_assign(SEXP obj, SEXP name, SEXP value) {
 }
 
 int R_has_slot(SEXP obj, SEXP name) {
-	return (int) unimplemented("R_has_slot");
+	unimplemented("R_has_slot");
+	return 0;
 }
 
 SEXP R_do_MAKE_CLASS(const char *what) {
@@ -1152,11 +1169,13 @@ int R_check_class_etc (SEXP x, const char **valid) {
 }
 
 SEXP R_PreserveObject(SEXP x) {
-	return newObjectRef(x);
+    TruffleEnv* env = (*truffleContext)->getTruffleEnv(truffleContext);
+	return (*env)->newObjectRef(env, x);
 }
 
 void R_ReleaseObject(SEXP x) {
-	releaseObjectRef(x);
+    TruffleEnv* env = (*truffleContext)->getTruffleEnv(truffleContext);
+	(*env)->releaseObjectRef(env, x);
 }
 
 void R_dot_Last(void) {
@@ -1165,7 +1184,7 @@ void R_dot_Last(void) {
 
 
 Rboolean R_compute_identical(SEXP x, SEXP y, int flags) {
-	return (Rboolean) ((call_R_compute_identical) callbacks[R_compute_identical_x])(x, y, flags);
+	return ((call_R_compute_identical) callbacks[R_compute_identical_x])(x, y, flags);
 }
 
 void Rf_copyListMatrix(SEXP s, SEXP t, Rboolean byrow) {
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.c
index fd2a3c2d49c781dc7c559269498e46bc465c222e..7e45c3b7b5164611720dde1f6cbda7cd34bc7c4e 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.c
@@ -34,24 +34,28 @@ typedef struct globalRefTable_struct {
 } GlobalRefElem;
 
 #define CACHED_GLOBALREFS_INITIAL_SIZE 64
+
 static GlobalRefElem *cachedGlobalRefs = NULL;
 static int cachedGlobalRefsHwm;
 static int cachedGlobalRefsLength;
+static TruffleContext* truffleContext;
 
-void init_utils() {
+void init_utils(TruffleEnv* env) {
 	if (cachedGlobalRefs == NULL) {
+	    truffleContext = (*env)->getTruffleContext(env);
 		cachedGlobalRefs = calloc(CACHED_GLOBALREFS_INITIAL_SIZE, sizeof(GlobalRefElem));
 		cachedGlobalRefsLength = CACHED_GLOBALREFS_INITIAL_SIZE;
 		cachedGlobalRefsHwm = 0;
 	}
 }
 static SEXP findCachedGlobalRef(SEXP obj) {
+    TruffleEnv* env = (*truffleContext)->getTruffleEnv(truffleContext);
     for (int i = 0; i < cachedGlobalRefsHwm; i++) {
         GlobalRefElem elem = cachedGlobalRefs[i];
         if (elem.gref == NULL) {
             continue;
         }
-        if (isSameObject(elem.gref, obj)) {
+        if ((*env)->isSameObject(env, elem.gref, obj)) {
             return elem.gref;
         }
     }
@@ -71,7 +75,8 @@ SEXP addGlobalRef(SEXP obj, int permanent) {
         cachedGlobalRefs = newCachedGlobalRefs;
         cachedGlobalRefsLength = newLength;
     }
-    gref = newObjectRef(obj);
+    TruffleEnv* env = (*truffleContext)->getTruffleEnv(truffleContext);
+    gref = (*env)->newObjectRef(env, obj);
     cachedGlobalRefs[cachedGlobalRefsHwm].gref = gref;
     cachedGlobalRefs[cachedGlobalRefsHwm].permanent = permanent;
     cachedGlobalRefsHwm++;
@@ -96,13 +101,14 @@ SEXP createGlobalRef(SEXP obj, int permanent) {
 }
 
 void releaseGlobalRef(SEXP obj) {
+    TruffleEnv* env = (*truffleContext)->getTruffleEnv(truffleContext);
     for (int i = 0; i < cachedGlobalRefsHwm; i++) {
         GlobalRefElem elem = cachedGlobalRefs[i];
         if (elem.gref == NULL || elem.permanent) {
             continue;
         }
-        if (isSameObject(elem.gref, obj)) {
-        	releaseObjectRef(elem.gref);
+        if ((*env)->isSameObject(env, elem.gref, obj)) {
+        	(*env)->releaseObjectRef(env, elem.gref);
             cachedGlobalRefs[i].gref = NULL;
         }
     }
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.h b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.h
index 72765550b53b2e4e08f39d1a3465ac32ce16c608..1997890c2b17c6cb45a7a324e35d37be5cd764f9 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.h
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.h
@@ -30,7 +30,7 @@
 #include <trufflenfi.h>
 
 extern void init_memory();
-extern void init_utils();
+extern void init_utils(TruffleEnv* env);
 
 // use for an unimplemented API function
 void *unimplemented(char *msg) __attribute__((noreturn));
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/variables.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/variables.c
index 00fd6647fd50160d255aff8d55a4d1cd589e3997..0b4db6c0ac10227c85ef5fdcba64a2afde9dea9d 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/variables.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/variables.c
@@ -300,8 +300,8 @@ void Call_initvar_string(int index, char *value) {
 	}
 }
 
-void Call_initvar_obj(int index, void* value) {
-	init_utils();
+void Call_initvar_obj(TruffleEnv* env, int index, void* value) {
+	init_utils(env);
 	switch (index) {
     case R_NilValue_x: R_NilValue_static = createGlobalRef(value, 1); break;
     case R_UnboundValue_x: R_UnboundValue_static = createGlobalRef(value, 1); break;
diff --git a/com.oracle.truffle.r.native/library/tools/Makefile b/com.oracle.truffle.r.native/library/tools/Makefile
index bd62cb85150fc07d1b2c525e58b6811481f03501..9c415e7f92e967f064f4844ba8170c6043556189 100644
--- a/com.oracle.truffle.r.native/library/tools/Makefile
+++ b/com.oracle.truffle.r.native/library/tools/Makefile
@@ -65,7 +65,7 @@ $(OBJ)/%.o: $(GNUR_SRC)/%.c
 	$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
 
 $(OBJ)/gramRd_nfi.o: $(SRC)/truffle_nfi/gramRd_nfi.c
-	$(CC) $(CFLAGS) $(FFI_INCLUDES) -c $< -o $@
+	$(CC) $(CFLAGS) $(FFI_INCLUDES) $(NFI_INCLUDES) -c $< -o $@
 
 $(OBJ)/gramRd_llvm.o: $(SRC)/truffle_llvm/gramRd_llvm.c
 	$(CC) $(CFLAGS) $(FFI_INCLUDES) $(SULONG_INCLUDES) -c $< -o $@
diff --git a/com.oracle.truffle.r.native/library/tools/src/truffle_nfi/gramRd_nfi.c b/com.oracle.truffle.r.native/library/tools/src/truffle_nfi/gramRd_nfi.c
index c5716bb4c39a020499f69b2c1d97ecc4edb3d2a1..db70c16af36dc2bf5c8f571fa2d5e8c9a4c1bcbb 100644
--- a/com.oracle.truffle.r.native/library/tools/src/truffle_nfi/gramRd_nfi.c
+++ b/com.oracle.truffle.r.native/library/tools/src/truffle_nfi/gramRd_nfi.c
@@ -21,10 +21,12 @@
  * questions.
  */
 #include "../gramRd_fastr.h"
+#include <trufflenfi.h>
 
 static int (*call_RConnGetC)(void *conn);
 
-void gramRd_nfi_init(void *closure) {
+void gramRd_nfi_init(TruffleEnv* env, void *closure) {
+	(*env)->newClosureRef(env, closure);
 	call_RConnGetC = closure;
 }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
index 5edca517e3f581854ba40b093adbf42254b22eee..a921bd0a56251c74bad87338690aadc9d1880957 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
@@ -42,13 +42,17 @@ import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.EnumSet;
 import java.util.HashMap;
+import java.util.Map;
 import java.util.TimeZone;
 import java.util.WeakHashMap;
 import java.util.concurrent.Executor;
+import java.util.function.Supplier;
 
 import com.oracle.truffle.api.Assumption;
+import com.oracle.truffle.api.CallTarget;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.RootCallTarget;
 import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.TruffleLanguage.Env;
@@ -237,6 +241,16 @@ public final class RContext implements RTruffleObject {
     private final String[] environment;
     private final RContext.ContextKind contextKind;
     private final TimeZone systemTimeZone;
+    public final Map<Class<?>, RootCallTarget> nativeCallTargets = new HashMap<>();
+
+    public RootCallTarget getOrCreateNativeCallTarget(Class<?> clazz, Supplier<RootCallTarget> creatFunction) {
+        RootCallTarget result = nativeCallTargets.get(clazz);
+        if (result == null) {
+            result = creatFunction.get();
+            nativeCallTargets.put(clazz, result);
+        }
+        return result;
+    }
 
     /**
      * Any context created by another has a parent. When such a context is destroyed we must reset
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java
index e9c3c18299f0a77df1b9e728ac9e2543c33e14a5..37031964a37ad06ce86e6ccf85ec0b34b7bb898f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java
@@ -406,7 +406,7 @@ public class DLL {
      */
     public static void loadLibR(String path) {
         RContext context = RContext.getInstance();
-        Object handle = DLLRFFI.DLOpenRootNode.create().getCallTarget().call(path, false, false);
+        Object handle = DLLRFFI.DLOpenRootNode.create(context).call(path, false, false);
         if (handle == null) {
             throw Utils.rSuicide("error loading libR from: " + path + "\n");
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLLRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLLRFFI.java
index fecf157ec83894882d71052ca23f81d31f587cf8..81eeb2d2aa308a8d0443e2addc20d78dce0f1934 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLLRFFI.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLLRFFI.java
@@ -22,8 +22,11 @@
  */
 package com.oracle.truffle.r.runtime.ffi;
 
+import com.oracle.truffle.api.CallTarget;
+import com.oracle.truffle.api.RootCallTarget;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
 
 public interface DLLRFFI {
@@ -74,8 +77,6 @@ public interface DLLRFFI {
     // RootNodes
 
     final class DLOpenRootNode extends RFFIRootNode<DLOpenNode> {
-        private static DLOpenRootNode dlOpenRootNode;
-
         private DLOpenRootNode() {
             super(RFFIFactory.getRFFI().getDLLRFFI().createDLOpenNode());
         }
@@ -86,11 +87,8 @@ public interface DLLRFFI {
             return rffiNode.execute((String) args[0], (boolean) args[1], (boolean) args[2]);
         }
 
-        public static DLOpenRootNode create() {
-            if (dlOpenRootNode == null) {
-                dlOpenRootNode = new DLOpenRootNode();
-            }
-            return dlOpenRootNode;
+        public static RootCallTarget create(RContext context) {
+            return context.getOrCreateNativeCallTarget(DLOpenRootNode.class, () -> new DLOpenRootNode().getCallTarget());
         }
     }
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/shell/TestJLineConsoleCompleter.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/shell/TestJLineConsoleCompleter.java
index 62c394af99bc92277b408f3d7c395590b61cf656..eaabb32efebf6e106e3d3b75a0b94911d2edf486 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/shell/TestJLineConsoleCompleter.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/shell/TestJLineConsoleCompleter.java
@@ -32,6 +32,7 @@ import org.graalvm.polyglot.Context;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 
 import com.oracle.truffle.r.launcher.JLineConsoleCompleter;
@@ -55,6 +56,8 @@ public class TestJLineConsoleCompleter {
         }
     }
 
+    // disabled because it uses Engine, which clashes with other tests that use PolyglotEngine
+    @Ignore
     @Test
     public void testCompl() {
         assertCompl("", 0);
diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py
index d0cbb8486c0ec3b5d3eebcf9d0417cf6a96366f1..2cdaca86d260da7b39d40e97e669cd90d61c58ec 100644
--- a/mx.fastr/suite.py
+++ b/mx.fastr/suite.py
@@ -29,7 +29,7 @@ suite = {
             {
                "name" : "truffle",
                "subdir" : True,
-               "version" : "90f29df947c052acb20be84e4278c8e522d0fa63",
+               "version" : "b7848be486a979673f6f695b9b0ca78b2e0d9164",
                "urls" : [
                     {"url" : "https://github.com/graalvm/graal", "kind" : "git"},
                     {"url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind" : "binary"},