diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/CaptureNamesImplMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/CaptureNamesImplMR.java
new file mode 100644
index 0000000000000000000000000000000000000000..5063771196f2e8e7d5113cced1325945a591b61e
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/CaptureNamesImplMR.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2017, 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.engine.interop;
+
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.interop.CanResolve;
+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.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.engine.TruffleRLanguage;
+import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_PCRE;
+import com.oracle.truffle.r.runtime.RInternalError;
+
+@MessageResolution(receiverType = TruffleNFI_PCRE.TruffleNFI_GetCaptureNamesNode.CaptureNamesImpl.class, language = TruffleRLanguage.class)
+public class CaptureNamesImplMR {
+    @CanResolve
+    public abstract static class CaptureNamesImplCheck extends Node {
+
+        protected static boolean test(TruffleObject receiver) {
+            return receiver instanceof TruffleNFI_PCRE.TruffleNFI_GetCaptureNamesNode.CaptureNamesImpl;
+        }
+    }
+
+    @Resolve(message = "EXECUTE")
+    public abstract static class CaptureNamesImplExecute extends Node {
+        protected Object access(@SuppressWarnings("unused") VirtualFrame frame, TruffleNFI_PCRE.TruffleNFI_GetCaptureNamesNode.CaptureNamesImpl receiver, Object[] arguments) {
+            try {
+                Object arg1 = arguments[1];
+                if (arg1 instanceof TruffleObject) {
+                    if (ForeignAccess.sendIsNull(Message.IS_NULL.createNode(), (TruffleObject) arg1)) {
+                        arg1 = null;
+                    } else {
+                        arg1 = ForeignAccess.sendUnbox(Message.UNBOX.createNode(), (TruffleObject) arg1);
+                    }
+                }
+                receiver.addName((int) arguments[0], (String) arg1);
+                return receiver;
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+    }
+
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/GlobUpCallImplMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/GlobUpCallImplMR.java
new file mode 100644
index 0000000000000000000000000000000000000000..3a614c0a7bcdaff7838f6f5a0e33b78a235ccab8
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/GlobUpCallImplMR.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017, 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.engine.interop;
+
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.interop.CanResolve;
+import com.oracle.truffle.api.interop.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.engine.TruffleRLanguage;
+import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_Base;
+
+@MessageResolution(receiverType = TruffleNFI_Base.TruffleNFI_GlobNode.GlobUpCallImpl.class, language = TruffleRLanguage.class)
+public class GlobUpCallImplMR {
+    @CanResolve
+    public abstract static class GlobUpCallImplCheck extends Node {
+
+        protected static boolean test(TruffleObject receiver) {
+            return receiver instanceof TruffleNFI_Base.TruffleNFI_GlobNode.GlobUpCallImpl;
+        }
+    }
+
+    @Resolve(message = "EXECUTE")
+    public abstract static class GlobUpCallImplExecute extends Node {
+        protected Object access(@SuppressWarnings("unused") VirtualFrame frame, TruffleNFI_Base.TruffleNFI_GlobNode.GlobUpCallImpl receiver, Object[] arguments) {
+            receiver.addPath((String) arguments[0]);
+            return receiver;
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/MakeResultImplMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/MakeResultImplMR.java
new file mode 100644
index 0000000000000000000000000000000000000000..34c97f9c38af9280a2cee84030ce905b28957ae9
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/MakeResultImplMR.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2017, 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.engine.interop;
+
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.interop.CanResolve;
+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.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.engine.TruffleRLanguage;
+import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_PCRE;
+import com.oracle.truffle.r.runtime.RInternalError;
+
+@MessageResolution(receiverType = TruffleNFI_PCRE.TruffleNFI_CompileNode.MakeResultImpl.class, language = TruffleRLanguage.class)
+public class MakeResultImplMR {
+    @CanResolve
+    public abstract static class MakeResultImplCheck extends Node {
+
+        protected static boolean test(TruffleObject receiver) {
+            return receiver instanceof TruffleNFI_PCRE.TruffleNFI_CompileNode.MakeResultImpl;
+        }
+    }
+
+    @Resolve(message = "EXECUTE")
+    public abstract static class MakeResultImplExecute extends Node {
+        protected Object access(@SuppressWarnings("unused") VirtualFrame frame, TruffleNFI_PCRE.TruffleNFI_CompileNode.MakeResultImpl receiver, Object[] arguments) {
+            try {
+                Object arg1 = arguments[1];
+                if (arg1 instanceof TruffleObject) {
+                    if (ForeignAccess.sendIsNull(Message.IS_NULL.createNode(), (TruffleObject) arg1)) {
+                        arg1 = null;
+                    } else {
+                        arg1 = ForeignAccess.sendUnbox(Message.UNBOX.createNode(), (TruffleObject) arg1);
+                    }
+                }
+                receiver.makeresult((long) arguments[0], (String) arg1, (int) arguments[2]);
+                return receiver;
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+    }
+
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
index 428399f41fd83bad08cf5d86c59d0f6e86287b1f..2eb7170790e20a410781997e6930993b4e825aff 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
@@ -27,6 +27,8 @@ import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.MessageResolution;
 import com.oracle.truffle.r.engine.TruffleRLanguage;
+import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_Base;
+import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_PCRE;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.conn.RConnection;
 import com.oracle.truffle.r.runtime.context.RContext;
@@ -95,6 +97,16 @@ public final class RForeignAccessFactoryImpl implements RForeignAccessFactory {
             return CharSXPWrapperMRForeign.ACCESS;
         } else if (obj instanceof RConnection) {
             return RConnectionMRForeign.ACCESS;
+        } else if (obj instanceof TruffleNFI_Base.TruffleNFI_UnameNode.UnameUpCallImpl) {
+            return UnameUpCallImplMRForeign.ACCESS;
+        } else if (obj instanceof TruffleNFI_Base.TruffleNFI_ReadlinkNode.SetResultImpl) {
+            return SetResultImplMRForeign.ACCESS;
+        } else if (obj instanceof TruffleNFI_Base.TruffleNFI_GlobNode.GlobUpCallImpl) {
+            return GlobUpCallImplMRForeign.ACCESS;
+        } else if (obj instanceof TruffleNFI_PCRE.TruffleNFI_CompileNode.MakeResultImpl) {
+            return MakeResultImplMRForeign.ACCESS;
+        } else if (obj instanceof TruffleNFI_PCRE.TruffleNFI_GetCaptureNamesNode.CaptureNamesImpl) {
+            return CaptureNamesImplMRForeign.ACCESS;
         } else {
             if (obj instanceof RAbstractVector) {
                 return ForeignAccess.create(RAbstractVector.class, new RAbstractVectorAccessFactory());
@@ -102,6 +114,7 @@ public final class RForeignAccessFactoryImpl implements RForeignAccessFactory {
                 throw RInternalError.unimplemented("missing foreign access factory for " + obj.getClass().getSimpleName());
             }
         }
+
     }
 
     @Override
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RNullMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RNullMR.java
index be1ae97f401b4cccd3808ec0589258dfe4ac4298..4fa755eacc68df01dd1bf4a5989e5431245c27d8 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RNullMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RNullMR.java
@@ -32,6 +32,11 @@ import com.oracle.truffle.r.runtime.data.RNull;
 
 @MessageResolution(receiverType = RNull.class, language = TruffleRLanguage.class)
 public class RNullMR {
+    /**
+     * Workaround to avoid NFI converting {@link RNull} to {@code null}.
+     */
+    private static boolean isNull = true;
+
     @Resolve(message = "IS_BOXED")
     public abstract static class RNullIsBoxedNode extends Node {
         protected Object access(@SuppressWarnings("unused") RNull receiver) {
@@ -49,7 +54,7 @@ public class RNullMR {
     @Resolve(message = "IS_NULL")
     public abstract static class RNullIsNullNode extends Node {
         protected Object access(@SuppressWarnings("unused") RNull receiver) {
-            return true;
+            return isNull;
         }
     }
 
@@ -60,4 +65,10 @@ public class RNullMR {
             return receiver instanceof RNull;
         }
     }
+
+    public static boolean setIsNull(boolean value) {
+        boolean prev = isNull;
+        isNull = value;
+        return prev;
+    }
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/SetResultImplMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/SetResultImplMR.java
new file mode 100644
index 0000000000000000000000000000000000000000..69cf41035975ae5e192aa05979df3225a1e74749
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/SetResultImplMR.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017, 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.engine.interop;
+
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.interop.CanResolve;
+import com.oracle.truffle.api.interop.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.engine.TruffleRLanguage;
+import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_Base;
+
+@MessageResolution(receiverType = TruffleNFI_Base.TruffleNFI_ReadlinkNode.SetResultImpl.class, language = TruffleRLanguage.class)
+public class SetResultImplMR {
+    @CanResolve
+    public abstract static class SetResultImplCheck extends Node {
+
+        protected static boolean test(TruffleObject receiver) {
+            return receiver instanceof TruffleNFI_Base.TruffleNFI_ReadlinkNode.SetResultImpl;
+        }
+    }
+
+    @Resolve(message = "EXECUTE")
+    public abstract static class SetResultImplExecute extends Node {
+        protected Object access(@SuppressWarnings("unused") VirtualFrame frame, TruffleNFI_Base.TruffleNFI_ReadlinkNode.SetResultImpl receiver, Object[] arguments) {
+            receiver.setResult((String) arguments[0], (int) arguments[1]);
+            return receiver;
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/UnameUpCallImplMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/UnameUpCallImplMR.java
new file mode 100644
index 0000000000000000000000000000000000000000..6382443b4fd3d6aec17eba4afd4cd3e1b9ed9316
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/UnameUpCallImplMR.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop;
+
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.interop.CanResolve;
+import com.oracle.truffle.api.interop.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.engine.TruffleRLanguage;
+import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_Base;
+
+@MessageResolution(receiverType = TruffleNFI_Base.TruffleNFI_UnameNode.UnameUpCallImpl.class, language = TruffleRLanguage.class)
+public class UnameUpCallImplMR {
+    @CanResolve
+    public abstract static class UnameUpCallImplCheck extends Node {
+
+        protected static boolean test(TruffleObject receiver) {
+            return receiver instanceof TruffleNFI_Base.TruffleNFI_UnameNode.UnameUpCallImpl;
+        }
+    }
+
+    @Resolve(message = "EXECUTE")
+    public abstract static class UnameUpCallImplExecute extends Node {
+        protected Object access(@SuppressWarnings("unused") VirtualFrame frame, TruffleNFI_Base.TruffleNFI_UnameNode.UnameUpCallImpl receiver, Object[] arguments) {
+            receiver.unameUpCall((String) arguments[0], (String) arguments[1], (String) arguments[2], (String) arguments[3], (String) arguments[4]);
+            return receiver;
+        }
+    }
+
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Base.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Base.java
index 33ab050e3c75c6babe7a0eefeba65101d0ccca1d..7e9c053144dc427043a3127e060ff3151515de07 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Base.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Base.java
@@ -32,6 +32,7 @@ import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
 import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
 
 public class TruffleNFI_Base implements BaseRFFI {
@@ -145,7 +146,7 @@ public class TruffleNFI_Base implements BaseRFFI {
             void setResult(String link, int errno);
         }
 
-        private static class SetResultImpl implements SetResult {
+        public static class SetResultImpl implements SetResult, RTruffleObject {
             private String link;
             private int errno;
 
@@ -162,7 +163,7 @@ public class TruffleNFI_Base implements BaseRFFI {
             Function.call_readlink.initialize();
             try {
                 SetResultImpl setResultImpl = new SetResultImpl();
-                ForeignAccess.sendExecute(Function.call_readlink.message, Function.call_readlink.function, JavaInterop.asTruffleFunction(SetResult.class, setResultImpl), path);
+                ForeignAccess.sendExecute(Function.call_readlink.message, Function.call_readlink.function, setResultImpl, path);
                 if (setResultImpl.link == null) {
                     if (setResultImpl.errno == EINVAL) {
                         return path;
@@ -256,7 +257,7 @@ public class TruffleNFI_Base implements BaseRFFI {
             void unameUpCall(String sysname, String release, String version, String machine, String nodename);
         }
 
-        private class UnameUpCallImpl implements UnameUpCall, UtsName {
+        public static class UnameUpCallImpl implements UnameUpCall, UtsName, RTruffleObject {
             private String sysname;
             private String release;
             private String version;
@@ -305,7 +306,7 @@ public class TruffleNFI_Base implements BaseRFFI {
             if (unameUpCallImpl == null) {
                 unameUpCallImpl = new UnameUpCallImpl();
                 try {
-                    ForeignAccess.sendExecute(Function.call_uname.message, Function.call_uname.function, JavaInterop.asTruffleFunction(UnameUpCall.class, unameUpCallImpl));
+                    ForeignAccess.sendExecute(Function.call_uname.message, Function.call_uname.function, unameUpCallImpl);
                 } catch (InteropException e) {
                     throw RInternalError.shouldNotReachHere(e);
                 }
@@ -319,7 +320,7 @@ public class TruffleNFI_Base implements BaseRFFI {
             void addPath(String path);
         }
 
-        private static class GlobUpCallImpl implements GlobUpCall {
+        public static class GlobUpCallImpl implements GlobUpCall, RTruffleObject {
             private ArrayList<String> paths = new ArrayList<>();
 
             @Override
@@ -333,7 +334,7 @@ public class TruffleNFI_Base implements BaseRFFI {
             Function.call_glob.initialize();
             GlobUpCallImpl globUpCallImpl = new GlobUpCallImpl();
             try {
-                ForeignAccess.sendExecute(Function.call_glob.message, Function.call_glob.function, pattern, JavaInterop.asTruffleFunction(GlobUpCall.class, globUpCallImpl));
+                ForeignAccess.sendExecute(Function.call_glob.message, Function.call_glob.function, pattern, globUpCallImpl);
             } catch (InteropException e) {
                 throw RInternalError.shouldNotReachHere(e);
             }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_C.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_C.java
new file mode 100644
index 0000000000000000000000000000000000000000..dbb6ece117d9ea866e4f85229fe517678b073a94
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_C.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2017, 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.engine.interop.ffi.nfi;
+
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Specialization;
+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.engine.interop.ffi.nfi.TruffleNFI_CFactory.TruffleNFI_InvokeCNodeGen;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.ffi.CRFFI;
+import com.oracle.truffle.r.runtime.ffi.NativeCallInfo;
+
+public class TruffleNFI_C implements CRFFI {
+    public abstract static class TruffleNFI_InvokeCNode extends InvokeCNode {
+
+        @Child Node bindNode = Message.createInvoke(1).createNode();
+
+        @Specialization(guards = "args.length == 0")
+        protected void invokeCall0(NativeCallInfo nativeCallInfo, @SuppressWarnings("unused") Object[] args,
+                        @Cached("createExecute(args.length)") Node executeNode) {
+            synchronized (TruffleNFI_Call.class) {
+                try {
+                    TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
+                                    nativeCallInfo.address.asTruffleObject(), "bind", "(): object");
+                    ForeignAccess.sendExecute(executeNode, callFunction);
+                } catch (InteropException ex) {
+                    throw RInternalError.shouldNotReachHere(ex);
+                }
+            }
+        }
+
+        public static Node createExecute(int n) {
+            return Message.createExecute(n).createNode();
+        }
+
+    }
+
+    @Override
+    public InvokeCNode createInvokeCNode() {
+        return TruffleNFI_InvokeCNodeGen.create();
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Call.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Call.java
index cd65b42fb813f671836fea44e66ab154874ca5f4..85f48b8d1d6c152574a5ab756c6fe8e8d6421956 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Call.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Call.java
@@ -34,6 +34,7 @@ import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.engine.interop.RNullMR;
 import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_CallFactory.TruffleNFI_InvokeCallNodeGen;
 import com.oracle.truffle.r.nodes.ffi.RFFIUpCallMethod;
 import com.oracle.truffle.r.nodes.ffi.RFFIUtils;
@@ -234,7 +235,7 @@ public class TruffleNFI_Call implements CallRFFI {
                         @Cached("createExecute(args.length)") Node executeNode) {
             synchronized (TruffleNFI_Call.class) {
                 Object result = null;
-                prepareCall(nativeCallInfo.name, args);
+                boolean isNullSetting = prepareCall(nativeCallInfo.name, args);
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(): object");
@@ -243,7 +244,7 @@ public class TruffleNFI_Call implements CallRFFI {
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 } finally {
-                    prepareReturn(nativeCallInfo.name, result);
+                    prepareReturn(nativeCallInfo.name, result, isNullSetting);
                 }
             }
         }
@@ -253,7 +254,7 @@ public class TruffleNFI_Call implements CallRFFI {
                         @Cached("createExecute(args.length)") Node executeNode) {
             synchronized (TruffleNFI_Call.class) {
                 Object result = null;
-                prepareCall(nativeCallInfo.name, args);
+                boolean isNullSetting = prepareCall(nativeCallInfo.name, args);
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object): object");
@@ -262,7 +263,7 @@ public class TruffleNFI_Call implements CallRFFI {
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 } finally {
-                    prepareReturn(nativeCallInfo.name, result);
+                    prepareReturn(nativeCallInfo.name, result, isNullSetting);
                 }
             }
         }
@@ -272,7 +273,7 @@ public class TruffleNFI_Call implements CallRFFI {
                         @Cached("createExecute(args.length)") Node executeNode) {
             synchronized (TruffleNFI_Call.class) {
                 Object result = null;
-                prepareCall(nativeCallInfo.name, args);
+                boolean isNullSetting = prepareCall(nativeCallInfo.name, args);
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object, object): object");
@@ -281,7 +282,7 @@ public class TruffleNFI_Call implements CallRFFI {
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 } finally {
-                    prepareReturn(nativeCallInfo.name, result);
+                    prepareReturn(nativeCallInfo.name, result, isNullSetting);
                 }
             }
         }
@@ -291,7 +292,7 @@ public class TruffleNFI_Call implements CallRFFI {
                         @Cached("createExecute(args.length)") Node executeNode) {
             synchronized (TruffleNFI_Call.class) {
                 Object result = null;
-                prepareCall(nativeCallInfo.name, args);
+                boolean isNullSetting = prepareCall(nativeCallInfo.name, args);
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object): object");
@@ -300,7 +301,7 @@ public class TruffleNFI_Call implements CallRFFI {
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 } finally {
-                    prepareReturn(nativeCallInfo.name, result);
+                    prepareReturn(nativeCallInfo.name, result, isNullSetting);
                 }
             }
         }
@@ -310,7 +311,7 @@ public class TruffleNFI_Call implements CallRFFI {
                         @Cached("createExecute(args.length)") Node executeNode) {
             synchronized (TruffleNFI_Call.class) {
                 Object result = null;
-                prepareCall(nativeCallInfo.name, args);
+                boolean isNullSetting = prepareCall(nativeCallInfo.name, args);
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object): object");
@@ -320,7 +321,7 @@ public class TruffleNFI_Call implements CallRFFI {
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 } finally {
-                    prepareReturn(nativeCallInfo.name, result);
+                    prepareReturn(nativeCallInfo.name, result, isNullSetting);
                 }
             }
         }
@@ -330,7 +331,7 @@ public class TruffleNFI_Call implements CallRFFI {
                         @Cached("createExecute(args.length)") Node executeNode) {
             synchronized (TruffleNFI_Call.class) {
                 Object result = null;
-                prepareCall(nativeCallInfo.name, args);
+                boolean isNullSetting = prepareCall(nativeCallInfo.name, args);
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object): object");
@@ -340,7 +341,7 @@ public class TruffleNFI_Call implements CallRFFI {
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 } finally {
-                    prepareReturn(nativeCallInfo.name, result);
+                    prepareReturn(nativeCallInfo.name, result, isNullSetting);
                 }
             }
         }
@@ -350,7 +351,7 @@ public class TruffleNFI_Call implements CallRFFI {
                         @Cached("createExecute(args.length)") Node executeNode) {
             synchronized (TruffleNFI_Call.class) {
                 Object result = null;
-                prepareCall(nativeCallInfo.name, args);
+                boolean isNullSetting = prepareCall(nativeCallInfo.name, args);
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object, object): object");
@@ -360,7 +361,7 @@ public class TruffleNFI_Call implements CallRFFI {
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 } finally {
-                    prepareReturn(nativeCallInfo.name, result);
+                    prepareReturn(nativeCallInfo.name, result, isNullSetting);
                 }
             }
         }
@@ -370,7 +371,7 @@ public class TruffleNFI_Call implements CallRFFI {
                         @Cached("createExecute(args.length)") Node executeNode) {
             synchronized (TruffleNFI_Call.class) {
                 Object result = null;
-                prepareCall(nativeCallInfo.name, args);
+                boolean isNullSetting = prepareCall(nativeCallInfo.name, args);
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object, object, object): object");
@@ -381,7 +382,7 @@ public class TruffleNFI_Call implements CallRFFI {
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 } finally {
-                    prepareReturn(nativeCallInfo.name, result);
+                    prepareReturn(nativeCallInfo.name, result, isNullSetting);
                 }
             }
         }
@@ -391,7 +392,7 @@ public class TruffleNFI_Call implements CallRFFI {
                         @Cached("createExecute(args.length)") Node executeNode) {
             synchronized (TruffleNFI_Call.class) {
                 Object result = null;
-                prepareCall(nativeCallInfo.name, args);
+                boolean isNullSetting = prepareCall(nativeCallInfo.name, args);
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object, object, object, object): object");
@@ -402,7 +403,7 @@ public class TruffleNFI_Call implements CallRFFI {
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 } finally {
-                    prepareReturn(nativeCallInfo.name, result);
+                    prepareReturn(nativeCallInfo.name, result, isNullSetting);
                 }
             }
         }
@@ -423,7 +424,7 @@ public class TruffleNFI_Call implements CallRFFI {
         @Override
         public void execute(NativeCallInfo nativeCallInfo, Object[] args) {
             synchronized (TruffleNFI_Call.class) {
-                prepareCall(nativeCallInfo.name, args);
+                boolean isNullSetting = prepareCall(nativeCallInfo.name, args);
                 try {
                     switch (args.length) {
                         case 0:
@@ -440,25 +441,28 @@ public class TruffleNFI_Call implements CallRFFI {
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 } finally {
-                    prepareReturn(nativeCallInfo.name, null);
+                    prepareReturn(nativeCallInfo.name, null, isNullSetting);
                 }
             }
         }
     }
 
-    private static void prepareCall(String name, Object[] args) {
+    private static boolean prepareCall(String name, Object[] args) {
         if (traceEnabled()) {
             traceDownCall(name, args);
         }
+        boolean isNullSetting = RNullMR.setIsNull(false);
         TruffleNFI_NativeArray.callEnter(callDepth);
         callDepth++;
+        return isNullSetting;
     }
 
-    private static void prepareReturn(String name, Object result) {
+    private static void prepareReturn(String name, Object result, boolean isNullSetting) {
         if (traceEnabled()) {
             traceDownCallReturn(name, result);
         }
         TruffleNFI_NativeArray.callEnter(callDepth);
+        RNullMR.setIsNull(isNullSetting);
         callDepth--;
     }
 
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Misc.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Misc.java
new file mode 100644
index 0000000000000000000000000000000000000000..9baa8a501139a8b5267323d2151848e71733c1fa
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Misc.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2017, 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.engine.interop.ffi.nfi;
+
+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.interop.java.JavaInterop;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.ffi.MiscRFFI;
+
+public class TruffleNFI_Misc implements MiscRFFI {
+
+    private static class TruffleNFI_ExactSumNode extends ExactSumNode {
+        @Child Node messageNode = Message.createExecute(4).createNode();
+        private TruffleObject function;
+
+        @Override
+        public double execute(double[] values, boolean hasNa, boolean naRm) {
+            if (function == null) {
+                function = TruffleNFI_Utils.lookupAndBind("exactSumFunc", false, "([double], sint32, sint32, sint32): double");
+            }
+            try {
+                return (double) ForeignAccess.sendExecute(messageNode, function, JavaInterop.asTruffleObject(values), values.length, hasNa ? 1 : 0, naRm ? 1 : 0);
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+
+    }
+
+    @Override
+    public ExactSumNode createExactSumNode() {
+        return new TruffleNFI_ExactSumNode();
+    }
+
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PCRE.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PCRE.java
index f9a3e37eaadfa3903fe819873173e8403d9c0bb6..50b713e9625588e2f5ef4eff05da7647d9f8f8be 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PCRE.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PCRE.java
@@ -33,6 +33,7 @@ import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
 import com.oracle.truffle.r.runtime.ffi.PCRERFFI;
 
 public class TruffleNFI_PCRE implements PCRERFFI {
@@ -95,12 +96,12 @@ public class TruffleNFI_PCRE implements PCRERFFI {
         }
     }
 
-    private static class TruffleNFI_GetCaptureNamesNode extends GetCaptureNamesNode {
+    public static class TruffleNFI_GetCaptureNamesNode extends GetCaptureNamesNode {
         interface CaptureNames {
             void addName(int i, String name);
         }
 
-        final class CaptureNamesImpl implements CaptureNames {
+        public static final class CaptureNamesImpl implements CaptureNames, RTruffleObject {
             private final String[] captureNames;
 
             private CaptureNamesImpl(int captureCount) {
@@ -120,7 +121,7 @@ public class TruffleNFI_PCRE implements PCRERFFI {
             try {
                 CaptureNamesImpl captureNamesImpl = new CaptureNamesImpl(captureCount);
                 int result = (int) ForeignAccess.sendExecute(Function.getcapturenames.executeNode, Function.getcapturenames.function,
-                                JavaInterop.asTruffleFunction(CaptureNames.class, captureNamesImpl), code, extra);
+                                captureNamesImpl, code, extra);
                 if (result < 0) {
                     CompilerDirectives.transferToInterpreter();
                     throw RError.error(RError.NO_CALLER, RError.Message.WRONG_PCRE_INFO, result);
@@ -134,12 +135,12 @@ public class TruffleNFI_PCRE implements PCRERFFI {
 
     }
 
-    private static class TruffleNFI_CompileNode extends CompileNode {
+    public static class TruffleNFI_CompileNode extends CompileNode {
         interface MakeResult {
             void makeresult(long pcreResult, String errorMessage, int errOffset);
         }
 
-        private static class MakeResultImpl implements MakeResult {
+        public static class MakeResultImpl implements MakeResult, RTruffleObject {
             private PCRERFFI.Result result;
 
             @Override
@@ -153,7 +154,7 @@ public class TruffleNFI_PCRE implements PCRERFFI {
             Function.compile.initialize();
             try {
                 MakeResultImpl makeResultImpl = new MakeResultImpl();
-                ForeignAccess.sendExecute(Function.compile.executeNode, Function.compile.function, JavaInterop.asTruffleFunction(MakeResult.class, makeResultImpl),
+                ForeignAccess.sendExecute(Function.compile.executeNode, Function.compile.function, makeResultImpl,
                                 pattern, options, tables);
                 return makeResultImpl.result;
             } catch (InteropException e) {
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_REmbed.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_REmbed.java
new file mode 100644
index 0000000000000000000000000000000000000000..798001ff8989ec95277b675732adea59fc3471a3
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_REmbed.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2017, 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.engine.interop.ffi.nfi;
+
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.ffi.REmbedRFFI;
+
+public class TruffleNFI_REmbed implements REmbedRFFI {
+
+    @Override
+    public void suicide(String x) {
+        throw RInternalError.unimplemented();
+
+    }
+
+    @Override
+    public void cleanUp(int type, int x, int y) {
+        throw RInternalError.unimplemented();
+
+    }
+
+    @Override
+    public String readConsole(String prompt) {
+        throw RInternalError.unimplemented();
+    }
+
+    @Override
+    public void writeConsole(String x) {
+        throw RInternalError.unimplemented();
+
+    }
+
+    @Override
+    public void writeErrConsole(String x) {
+        throw RInternalError.unimplemented();
+
+    }
+
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RFFIFactory.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RFFIFactory.java
index d884490e87e76daa0068ddb3955e69443bbeac11..fba810c5c1bc36e0ad45a45f88f02650201e2792 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RFFIFactory.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RFFIFactory.java
@@ -27,21 +27,26 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 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;
+import com.oracle.truffle.r.runtime.ffi.CRFFI;
 import com.oracle.truffle.r.runtime.ffi.CallRFFI;
 import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.ffi.DLLRFFI;
+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;
 import com.oracle.truffle.r.runtime.ffi.RFFI;
+import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
 import com.oracle.truffle.r.runtime.ffi.StatsRFFI;
 import com.oracle.truffle.r.runtime.ffi.ToolsRFFI;
 import com.oracle.truffle.r.runtime.ffi.UserRngRFFI;
 import com.oracle.truffle.r.runtime.ffi.ZipRFFI;
-import com.oracle.truffle.r.runtime.ffi.jni.JNI_RFFIFactory;
+import com.oracle.truffle.r.runtime.ffi.generic.Generic_Grid;
 
-public class TruffleNFI_RFFIFactory extends JNI_RFFIFactory implements RFFI {
+public class TruffleNFI_RFFIFactory extends RFFIFactory implements RFFI {
     private static class ContextStateImpl implements RContext.ContextState {
         @Override
         public ContextState initialize(RContext context) {
@@ -58,7 +63,21 @@ public class TruffleNFI_RFFIFactory extends JNI_RFFIFactory implements RFFI {
         return new ContextStateImpl();
     }
 
-    @CompilationFinal private CallRFFI callRFFI;
+    @Override
+    protected RFFI createRFFI() {
+        return this;
+    }
+
+    @CompilationFinal private CRFFI cRFFI;
+
+    @Override
+    public CRFFI getCRFFI() {
+        if (cRFFI == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            cRFFI = new TruffleNFI_C();
+        }
+        return cRFFI;
+    }
 
     @CompilationFinal private BaseRFFI baseRFFI;
 
@@ -71,6 +90,8 @@ public class TruffleNFI_RFFIFactory extends JNI_RFFIFactory implements RFFI {
         return baseRFFI;
     }
 
+    @CompilationFinal private CallRFFI callRFFI;
+
     @Override
     public CallRFFI getCallRFFI() {
         if (callRFFI == null) {
@@ -165,4 +186,35 @@ public class TruffleNFI_RFFIFactory extends JNI_RFFIFactory implements RFFI {
         return toolsRFFI;
     }
 
+    private REmbedRFFI rEmbedRFFI;
+
+    @Override
+    public REmbedRFFI getREmbedRFFI() {
+        if (rEmbedRFFI == null) {
+            rEmbedRFFI = new TruffleNFI_REmbed();
+        }
+        return rEmbedRFFI;
+    }
+
+    @CompilationFinal private GridRFFI gridRFFI;
+
+    @Override
+    public GridRFFI getGridRFFI() {
+        if (gridRFFI == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            gridRFFI = new Generic_Grid();
+        }
+        return gridRFFI;
+    }
+
+    private MiscRFFI miscRFFI;
+
+    @Override
+    public MiscRFFI getMiscRFFI() {
+        if (miscRFFI == null) {
+            miscRFFI = new TruffleNFI_Misc();
+        }
+        return miscRFFI;
+    }
+
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Tools.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Tools.java
index 6eb12e4527d4507ff724b59f089e145d89506565..dd72b7e5e0c62a09f94850a41a4c0dcb20711f06 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Tools.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Tools.java
@@ -35,6 +35,7 @@ import com.oracle.truffle.r.runtime.RInternalError;
 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.ToolsRFFI;
@@ -50,7 +51,7 @@ public class TruffleNFI_Tools implements ToolsRFFI {
             int getc(RConnection conn);
         }
 
-        private static class RConnGetCImpl implements RConnGetC {
+        private static class RConnGetCImpl implements RConnGetC, RTruffleObject {
             @Override
             public int getc(RConnection conn) {
                 RFFIUtils.traceUpCall("getc");
@@ -87,7 +88,7 @@ public class TruffleNFI_Tools implements ToolsRFFI {
             Node executeNode = Message.createExecute(1).createNode();
             try {
                 TruffleObject function = (TruffleObject) ForeignAccess.sendInvoke(bind, symbolHandle.asTruffleObject(), "bind", "((object): sint32): void");
-                ForeignAccess.sendExecute(executeNode, function, JavaInterop.asTruffleFunction(RConnGetC.class, new RConnGetCImpl()));
+                ForeignAccess.sendExecute(executeNode, function, new RConnGetCImpl());
             } catch (InteropException t) {
                 throw RInternalError.shouldNotReachHere(t);
             }
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/call_rffi.c.not b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/call_rffi.c.not
deleted file mode 100644
index c52ed611c670afffde2298524409505473c85b7c..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/call_rffi.c.not
+++ /dev/null
@@ -1,26 +0,0 @@
-#include <rffiutils.h>
-
-typedef void (*callVoid0func)();
-
-Call_callVoid0(long address) {
-//	jmp_buf error_jmpbuf;
-//	callEnter(env, &error_jmpbuf);
-//	if (!setjmp(error_jmpbuf)) {
-		callVoid0func call1 = (callVoid0func) address;
-		(*call1)();
-//	}
-//	callExit(env);
-}
-
-typedef void (*callVoid1func)(SEXP arg1);
-
-
-Call_callVoid1(long address, TruffleObject *arg1) {
-//	jmp_buf error_jmpbuf;
-//	callEnter(env, &error_jmpbuf);
-//	if (!setjmp(error_jmpbuf)) {
-		callVoid0func call1 = (callVoid0func) address;
-		(*call1)(arg1);
-//	}
-//	callExit(env);
-}
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/misc_rffi.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/misc_rffi.c
new file mode 100644
index 0000000000000000000000000000000000000000..f5ccdf078a392ded6981cb6032556e655d169c39
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/misc_rffi.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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>
+
+double exactSumFunc(double* contents, int length, int hasNa, int naRm) {
+
+	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++) {
+		double value = contents[i];
+		if (R_IsNA(value)) {
+			if (!naRm) {
+				return R_NaReal;
+			}
+		} else {
+			sum += value;
+		}
+	}
+
+	return sum;
+}