diff --git a/ci.hocon b/ci.hocon
index 259a0e142ed2dc363b896a521cd05bed462b7e61..4c97461fc140d1de63becdf5323cd0dcb8e08801 100644
--- a/ci.hocon
+++ b/ci.hocon
@@ -6,7 +6,7 @@
 # java 7 is needed by Truffle (for now)
 java7 : {name : oraclejdk, version : "7",    platformspecific: true}
 # java 8 must be a jvmci enabled variant
-java8 : {name : labsjdk, version : "8-jvmci-latest", platformspecific: true}
+java8 : {name : labsjdk, version : "8u161-jvmci-0.41", platformspecific: true}
 java9 : {name : labsjdk, version : "9-ea+168", platformspecific: true}
 
 java8Downloads : {
@@ -146,7 +146,7 @@ gateTestLinuxLLVM : ${common} ${requireGCC} {
   environment :  {
       TZDIR: "/usr/share/zoneinfo"
       FASTR_RFFI : "llvm"
-      FASTR_LLVM_HOME : "$DRAGONEGG_LLVM/bin"
+      FASTR_LLVM_TOOLS : "$DRAGONEGG_LLVM/bin"
       FASTR_LLVM_GFORTRAN_LLVM_AS : "$DRAGONEGG_LLVM/bin/llvm-as"
       FASTR_LLVM_GFORTRAN : "$DRAGONEGG_GCC/bin/gfortran"
       FASTR_LLVM_DRAGONEGG : "$DRAGONEGG_GCC/lib/dragonegg.so"
@@ -192,7 +192,7 @@ gateTestDarwinLLVM: ${common} ${darwinEnvironment} ${requireGCC} {
 
   environment :  {
       FASTR_RFFI : "llvm"
-      FASTR_LLVM_HOME : "$DRAGONEGG_LLVM/bin"
+      FASTR_LLVM_TOOLS : "$DRAGONEGG_LLVM/bin"
       FASTR_LLVM_GFORTRAN_LLVM_AS : "$DRAGONEGG_LLVM/bin/llvm-as"
       FASTR_LLVM_GFORTRAN : "$DRAGONEGG_GCC/bin/gfortran"
       FASTR_LLVM_DRAGONEGG : "$DRAGONEGG_GCC/lib/dragonegg.so"
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java
index c7984a2e4953a5c1b80e11efebc6db76bc7f5180..523b80e3b1e3fd1e07026931e2e2f47a1c1caffa 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java
@@ -31,7 +31,6 @@ import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.IdentityHashMap;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.Function;
@@ -234,18 +233,14 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
 
     @Override
     @TruffleBoundary
-    public Object R_getClassDef(String clazz) {
-        String name = "getClassDef";
-        RFunction getClass = (RFunction) RContext.getRRuntimeASTAccess().forcePromise(name, REnvironment.getRegisteredNamespace("methods").get(name));
-        return RContext.getEngine().evalFunction(getClass, null, RCaller.createInvalid(null), true, null, clazz);
+    public Object R_getClassDef(Object clazz) {
+        throw implementedAsNode();
     }
 
     @Override
     @TruffleBoundary
-    public Object R_do_MAKE_CLASS(String clazz) {
-        String name = "getClass";
-        RFunction getClass = (RFunction) RContext.getRRuntimeASTAccess().forcePromise(name, REnvironment.getRegisteredNamespace("methods").get(name));
-        return RContext.getEngine().evalFunction(getClass, null, RCaller.createInvalid(null), true, null, clazz);
+    public Object R_do_MAKE_CLASS(Object clazz) {
+        throw implementedAsNode();
     }
 
     @Override
@@ -1517,48 +1512,10 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
         }
     }
 
-    private static HashMap<String, Integer> name2typeTable;
-
-    static {
-        name2typeTable = new HashMap<>(26);
-        name2typeTable.put("NULL", SEXPTYPE.NILSXP.code);
-        /* real types */
-        name2typeTable.put("symbol", SEXPTYPE.SYMSXP.code);
-        name2typeTable.put("pairlist", SEXPTYPE.LISTSXP.code);
-        name2typeTable.put("closure", SEXPTYPE.CLOSXP.code);
-        name2typeTable.put("environment", SEXPTYPE.ENVSXP.code);
-        name2typeTable.put("promise", SEXPTYPE.PROMSXP.code);
-        name2typeTable.put("language", SEXPTYPE.LANGSXP.code);
-        name2typeTable.put("special", SEXPTYPE.SPECIALSXP.code);
-        name2typeTable.put("builtin", SEXPTYPE.BUILTINSXP.code);
-        name2typeTable.put("char", SEXPTYPE.CHARSXP.code);
-        name2typeTable.put("logical", SEXPTYPE.LGLSXP.code);
-        name2typeTable.put("integer", SEXPTYPE.INTSXP.code);
-        name2typeTable.put("double", SEXPTYPE.REALSXP.code);
-        /*-  "real", for R <= 0.61.x */
-        name2typeTable.put("complex", SEXPTYPE.CPLXSXP.code);
-        name2typeTable.put("character", SEXPTYPE.STRSXP.code);
-        name2typeTable.put("...", SEXPTYPE.DOTSXP.code);
-        name2typeTable.put("any", SEXPTYPE.ANYSXP.code);
-        name2typeTable.put("expression", SEXPTYPE.EXPRSXP.code);
-        name2typeTable.put("list", SEXPTYPE.VECSXP.code);
-        name2typeTable.put("externalptr", SEXPTYPE.EXTPTRSXP.code);
-        name2typeTable.put("bytecode", SEXPTYPE.BCODESXP.code);
-        name2typeTable.put("weakref", SEXPTYPE.WEAKREFSXP.code);
-        name2typeTable.put("raw", SEXPTYPE.RAWSXP.code);
-        name2typeTable.put("S4", SEXPTYPE.S4SXP.code);
-        name2typeTable.put("numeric", SEXPTYPE.REALSXP.code);
-        name2typeTable.put("name", SEXPTYPE.SYMSXP.code);
-    }
-
-    @Override
-    @TruffleBoundary
-    public int Rf_str2type(String name) {
-        if (name == null) {
-            return -1;
-        }
-        Integer result = name2typeTable.get(name);
-        return result != null ? result : -1;
+    @Override
+    @TruffleBoundary
+    public int Rf_str2type(Object name) {
+        throw implementedAsNode();
     }
 
     @Override
@@ -1949,7 +1906,8 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
 
             protected Object access(VectorWrapper receiver, Object[] arguments) {
                 try {
-                    // Currently, there is only one "executable" object, which is CharSXPWrapper.
+                    // Currently, there is only one "executable" object, which is
+                    // CharSXPWrapper.
                     // See CharSXPWrapperMR for the EXECUTABLE message handler.
                     assert arguments.length == 0 && receiver.vector instanceof CharSXPWrapper;
                     return ForeignAccess.sendExecute(execMsg, receiver.vector);
@@ -1972,7 +1930,22 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
         private final TruffleObject vector;
 
         public VectorWrapper(TruffleObject vector) {
+            assert vector instanceof RObject;
             this.vector = vector;
+            NativeDataAccess.setNativeWrapper((RObject) vector, this);
+        }
+
+        static Object get(TruffleObject x) {
+            assert x instanceof RObject;
+            Object wrapper = NativeDataAccess.getNativeWrapper((RObject) x);
+            if (wrapper != null) {
+                return wrapper;
+            } else {
+                wrapper = new VectorWrapper(x);
+                // Establish the 1-1 relationship between the object and its native wrapper
+                NativeDataAccess.setNativeWrapper((RObject) x, wrapper);
+                return wrapper;
+            }
         }
 
         public TruffleObject getVector() {
@@ -1983,38 +1956,44 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
         public ForeignAccess getForeignAccess() {
             return VectorWrapperMRForeign.ACCESS;
         }
+
+        @Override
+        public int hashCode() {
+            return vector.hashCode();
+        }
+
     }
 
     @Override
     public Object INTEGER(Object x) {
         // also handles LOGICAL
         assert x instanceof RIntVector || x instanceof RLogicalVector || x == RNull.instance;
-        return new VectorWrapper(guaranteeVectorOrNull(x, RVector.class));
+        return VectorWrapper.get(guaranteeVectorOrNull(x, RVector.class));
     }
 
     @Override
     public Object LOGICAL(Object x) {
-        return new VectorWrapper(guaranteeVectorOrNull(x, RLogicalVector.class));
+        return VectorWrapper.get(guaranteeVectorOrNull(x, RLogicalVector.class));
     }
 
     @Override
     public Object REAL(Object x) {
-        return new VectorWrapper(guaranteeVectorOrNull(x, RDoubleVector.class));
+        return VectorWrapper.get(guaranteeVectorOrNull(x, RDoubleVector.class));
     }
 
     @Override
     public Object RAW(Object x) {
-        return new VectorWrapper(guaranteeVectorOrNull(x, RRawVector.class));
+        return VectorWrapper.get(guaranteeVectorOrNull(x, RRawVector.class));
     }
 
     @Override
     public Object COMPLEX(Object x) {
-        return new VectorWrapper(guaranteeVectorOrNull(x, RComplexVector.class));
+        return VectorWrapper.get(guaranteeVectorOrNull(x, RComplexVector.class));
     }
 
     @Override
     public Object R_CHAR(Object x) {
-        return new VectorWrapper(guaranteeVectorOrNull(x, CharSXPWrapper.class));
+        return VectorWrapper.get(guaranteeVectorOrNull(x, CharSXPWrapper.class));
     }
 
     @Override
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/package-info.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/package-info.java
index 19ebc60087b43aa9e717c0a82e3ff6f7027e67be..fc661a180f319a6b2b04c8bccec9318a9bd04788 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/package-info.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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
@@ -23,10 +23,5 @@
 /**
  * A collection of types and {@link com.oracle.truffle.api.interop.MessageResolution} classes that
  * support the implementations.
- *
- * See {@link com.oracle.truffle.r.ffi.impl.interop.base} and
- * {@link com.oracle.truffle.r.ffi.impl.interop.pcre} for similar classes specific to the
- * {@link com.oracle.truffle.r.runtime.ffi.BaseRFFI} and
- * {@link com.oracle.truffle.r.runtime.ffi.PCRERFFI} interfaces.
  */
 package com.oracle.truffle.r.ffi.impl.interop;
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Call.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Call.java
index 1075ab3f6368df16c2638431abd54e1193c5e20b..27448accd62d39405390e1353a3fe5ea079a1d5f 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Call.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Call.java
@@ -41,6 +41,7 @@ import com.oracle.truffle.r.ffi.impl.llvm.upcalls.BytesToNativeCharArrayCall;
 import com.oracle.truffle.r.ffi.impl.llvm.upcalls.CharSXPToNativeArrayCall;
 import com.oracle.truffle.r.ffi.impl.upcalls.Callbacks;
 import com.oracle.truffle.r.ffi.impl.upcalls.FFIUnwrapNode;
+import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.context.RContext;
@@ -162,12 +163,12 @@ final class TruffleLLVM_Call implements CallRFFI {
 
         @Specialization
         protected static Object convert(int value) {
-            return RDataFactory.createIntVector(new int[]{value}, RRuntime.isNA(value));
+            return RDataFactory.createIntVector(new int[]{value}, !RRuntime.isNA(value));
         }
 
         @Specialization
         protected static Object convert(double value) {
-            return RDataFactory.createDoubleVector(new double[]{value}, RRuntime.isNA(value));
+            return RDataFactory.createDoubleVector(new double[]{value}, !RRuntime.isNA(value));
         }
 
         @Specialization
@@ -182,12 +183,12 @@ final class TruffleLLVM_Call implements CallRFFI {
 
         @Specialization
         protected static Object convert(byte value) {
-            return RDataFactory.createLogicalVector(new byte[]{value}, RRuntime.isNA(value));
+            return RDataFactory.createLogicalVector(new byte[]{value}, !RRuntime.isNA(value));
         }
 
         @Specialization
         protected static Object convert(String value) {
-            return RDataFactory.createStringVector(new String[]{value}, RRuntime.isNA(value));
+            return RDataFactory.createStringVector(new String[]{value}, !RRuntime.isNA(value));
         }
 
         @Fallback
@@ -259,6 +260,14 @@ final class TruffleLLVM_Call implements CallRFFI {
                 return result;
             } catch (InteropException ex) {
                 throw RInternalError.shouldNotReachHere(ex);
+            } catch (Exception ex) {
+                if (ex.getCause() instanceof RError) {
+                    // Sulong wraps an error having occurred in an upcall, so let's propagate the
+                    // wrapped one instead of the Sulong one.
+                    throw (RError) ex.getCause();
+                } else {
+                    throw ex;
+                }
             } finally {
                 RContext.getRForeignAccessFactory().setIsNull(isNullSetting);
             }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_DLL.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_DLL.java
index 568b273a72b0de402d520a02798a4940a67f643b..f934408376f508f80b0035af089d84c9f1622f2f 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_DLL.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_DLL.java
@@ -23,14 +23,22 @@
 package com.oracle.truffle.r.ffi.impl.llvm;
 
 import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStreamReader;
 import java.io.PrintStream;
 import java.nio.file.FileSystems;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
 
@@ -39,6 +47,8 @@ import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RPlatform;
+import com.oracle.truffle.r.runtime.RPlatform.OSInfo;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.context.RContext.ContextState;
 import com.oracle.truffle.r.runtime.ffi.DLL;
@@ -63,6 +73,18 @@ import com.oracle.truffle.r.runtime.ffi.DLLRFFI;
  *
  */
 public class TruffleLLVM_DLL implements DLLRFFI {
+    /*
+     * The LIBS file, which is included in the LLVM archive, enumerates native dynamic libraries to
+     * be linked with the LLVM library in the archive.
+     */
+    private static final String LIBS = "LIBS";
+
+    private static final Set<String> ignoredNativeLibs = new HashSet<>();
+    static {
+        ignoredNativeLibs.add("Rblas");
+        ignoredNativeLibs.add("Rlapack");
+    }
+
     static class ContextStateImpl implements RContext.ContextState {
         /**
          * When a new {@link RContext} is created we have to re-parse the libR modules,
@@ -121,7 +143,19 @@ public class TruffleLLVM_DLL implements DLLRFFI {
         boolean match(String name);
     }
 
-    public static LLVM_IR[] getZipLLVMIR(String path) {
+    public static final class LLVMArchive {
+        public final LLVM_IR[] irs;
+        public final List<String> nativeLibs;
+
+        private LLVMArchive(LLVM_IR[] irs, List<String> nativeLibs) {
+            super();
+            this.irs = irs;
+            this.nativeLibs = nativeLibs;
+        }
+    }
+
+    public static LLVMArchive getZipLLVMIR(String path) {
+        List<String> nativeLibs = Collections.emptyList();
         try (ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(path)))) {
             ArrayList<LLVM_IR> irList = new ArrayList<>();
             while (true) {
@@ -130,24 +164,28 @@ public class TruffleLLVM_DLL implements DLLRFFI {
                     break;
                 }
                 int size = (int) entry.getSize();
-                byte[] bc = new byte[size];
+                byte[] bytes = new byte[size];
                 int n;
                 int totalRead = 0;
-                while (totalRead < size && (n = zis.read(bc, totalRead, size - totalRead)) != -1) {
+                while (totalRead < size && (n = zis.read(bytes, totalRead, size - totalRead)) != -1) {
                     totalRead += n;
                 }
+                if (LIBS.equals(entry.getName())) {
+                    nativeLibs = getNativeLibs(bytes);
+                    continue;
+                }
                 Path zipName = Paths.get(entry.getName());
                 String name = zipName.getFileName().toString();
                 int ix = name.indexOf('.');
                 if (ix > 0) {
                     name = name.substring(0, ix);
                 }
-                LLVM_IR.Binary ir = new LLVM_IR.Binary(name, bc);
+                LLVM_IR.Binary ir = new LLVM_IR.Binary(name, bytes);
                 irList.add(ir);
                 // debugging
                 if (System.getenv("FASTR_LLVM_DEBUG") != null) {
                     try (FileOutputStream bs = new FileOutputStream(Paths.get("tmpzip", name).toString())) {
-                        bs.write(bc);
+                        bs.write(bytes);
                     }
                     try (PrintStream bs = new PrintStream(new FileOutputStream(Paths.get("tmpb64", name).toString()))) {
                         bs.print(ir.base64);
@@ -156,13 +194,24 @@ public class TruffleLLVM_DLL implements DLLRFFI {
             }
             LLVM_IR[] result = new LLVM_IR[irList.size()];
             irList.toArray(result);
-            return result;
+            return new LLVMArchive(result, nativeLibs);
         } catch (IOException ex) {
             // not a zip file
             return null;
         }
     }
 
+    private static List<String> getNativeLibs(byte[] bytes) throws IOException {
+        List<String> libs = new LinkedList<>();
+        try (BufferedReader libReader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(bytes)))) {
+            String lib = null;
+            while ((lib = libReader.readLine()) != null) {
+                libs.add(lib);
+            }
+        }
+        return libs;
+    }
+
     private static class TruffleLLVM_DLOpenNode extends Node implements DLOpenNode {
         @Child private TruffleLLVM_NativeDLL.TruffleLLVM_NativeDLOpen nativeDLLOpenNode;
 
@@ -175,7 +224,8 @@ public class TruffleLLVM_DLL implements DLLRFFI {
         @Override
         public Object execute(String path, boolean local, boolean now) {
             try {
-                LLVM_IR[] irs = getZipLLVMIR(path);
+                LLVMArchive ar = getZipLLVMIR(path);
+                LLVM_IR[] irs = ar.irs;
                 if (irs == null) {
                     return tryOpenNative(path, local, now);
                 }
@@ -183,6 +233,8 @@ public class TruffleLLVM_DLL implements DLLRFFI {
                 if (libName.equals("libR")) {
                     // save for new RContexts
                     truffleDLL.libRModules = irs;
+                } else {
+                    loadNativeLibs(ar.nativeLibs);
                 }
                 for (LLVM_IR ir : irs) {
                     parseLLVM(libName, ir);
@@ -199,10 +251,22 @@ public class TruffleLLVM_DLL implements DLLRFFI {
                     sb.append(t.getMessage());
                     t = t.getCause();
                 }
+                ex.printStackTrace();
                 throw new UnsatisfiedLinkError(sb.toString());
             }
         }
 
+        private void loadNativeLibs(List<String> nativeLibs) {
+            OSInfo osInfo = RPlatform.getOSInfo();
+            for (String nativeLib : nativeLibs) {
+                if (ignoredNativeLibs.contains(nativeLib)) {
+                    continue;
+                }
+                String nativeLibName = "lib" + nativeLib + "." + osInfo.libExt;
+                tryOpenNative(nativeLibName, false, true);
+            }
+        }
+
         private long tryOpenNative(String path, boolean local, boolean now) throws UnsatisfiedLinkError {
             if (nativeDLLOpenNode == null) {
                 nativeDLLOpenNode = insert(new TruffleLLVM_NativeDLL.TruffleLLVM_NativeDLOpen());
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_UpCallsRFFIImpl.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_UpCallsRFFIImpl.java
index d6a1f4b67f5d8153fc01a3d1bf6abb775ef4b247..ad6eed382d4b3c7322dc5fbefc3d4fddc11ec70c 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_UpCallsRFFIImpl.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_UpCallsRFFIImpl.java
@@ -40,6 +40,7 @@ import com.oracle.truffle.r.runtime.data.RDouble;
 import com.oracle.truffle.r.runtime.data.RInteger;
 import com.oracle.truffle.r.runtime.data.RLogical;
 import com.oracle.truffle.r.runtime.data.RScalar;
+import com.oracle.truffle.r.runtime.data.RString;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.ffi.DLL.CEntry;
@@ -108,6 +109,8 @@ public class TruffleLLVM_UpCallsRFFIImpl extends JavaUpCallsRFFIImpl {
             return RInteger.valueOf((int) x);
         } else if (x instanceof Byte) {
             return RLogical.valueOf((byte) x);
+        } else if (x instanceof String) {
+            return RString.valueOf((String) x);
         } else {
             throw RInternalError.shouldNotReachHere();
         }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/tools/ShowLLVMIR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/tools/ShowLLVMIR.java
index 91acc85892f4595697ed8dc15351271b23478039..a606291213ba4c953413408904d4b63850e00cdb 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/tools/ShowLLVMIR.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/tools/ShowLLVMIR.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, 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
@@ -28,6 +28,7 @@ import java.io.OutputStream;
 
 import com.oracle.truffle.r.ffi.impl.llvm.LLVM_IR;
 import com.oracle.truffle.r.ffi.impl.llvm.TruffleLLVM_DLL;
+import com.oracle.truffle.r.ffi.impl.llvm.TruffleLLVM_DLL.LLVMArchive;
 import com.oracle.truffle.r.runtime.ProcessOutputManager;
 
 public class ShowLLVMIR {
@@ -64,7 +65,8 @@ public class ShowLLVMIR {
             usage();
         }
         try {
-            LLVM_IR[] irs = TruffleLLVM_DLL.getZipLLVMIR(objPath);
+            LLVMArchive ar = TruffleLLVM_DLL.getZipLLVMIR(objPath);
+            LLVM_IR[] irs = ar.irs;
             if (irs == null) {
                 System.out.printf("no llvm ir in %s\n", objPath);
                 System.exit(1);
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/upcalls/BytesToNativeCharArrayCallMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/upcalls/BytesToNativeCharArrayCallMR.java
index dc51516b4fccfc8c95208324e32a5781c659ed12..96e7f6e18b8d8a2fc17ed4597feaf5211878d49b 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/upcalls/BytesToNativeCharArrayCallMR.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/upcalls/BytesToNativeCharArrayCallMR.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,6 +30,7 @@ import com.oracle.truffle.api.nodes.Node;
 
 @MessageResolution(receiverType = BytesToNativeCharArrayCall.class)
 public class BytesToNativeCharArrayCallMR {
+
     @Resolve(message = "EXECUTE")
     public abstract static class BytesToNativeCharArrayCallExecute extends Node {
         protected java.lang.Object access(BytesToNativeCharArrayCall receiver, Object[] arguments) {
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/DoMakeClassNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/DoMakeClassNode.java
new file mode 100644
index 0000000000000000000000000000000000000000..1abceefaded81c425d756a971bee4a98a59e020b
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/DoMakeClassNode.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2018, 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.nodes;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.runtime.RCaller;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.env.REnvironment;
+
+public abstract class DoMakeClassNode extends FFIUpCallNode.Arg1 {
+
+    public static DoMakeClassNode create() {
+        return DoMakeClassNodeGen.create();
+    }
+
+    @Specialization
+    @TruffleBoundary
+    Object handleString(Object cls, @Cached("create()") NativeStringCastNode nscn) {
+        String clazz = nscn.executeObject(cls);
+        String name = "getClass";
+        RFunction getClass = (RFunction) RContext.getRRuntimeASTAccess().forcePromise(name, REnvironment.getRegisteredNamespace("methods").get(name));
+        return RContext.getEngine().evalFunction(getClass, null, RCaller.createInvalid(null), true, null, clazz);
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/GetClassDefNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/GetClassDefNode.java
new file mode 100644
index 0000000000000000000000000000000000000000..05f10669c977a2aa5206913e784749c7f3064553
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/GetClassDefNode.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2018, 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.nodes;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.runtime.RCaller;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.env.REnvironment;
+
+public abstract class GetClassDefNode extends FFIUpCallNode.Arg1 {
+
+    public static GetClassDefNode create() {
+        return GetClassDefNodeGen.create();
+    }
+
+    @Specialization
+    @TruffleBoundary
+    Object handleString(Object cls, @Cached("create()") NativeStringCastNode nscn) {
+        String clazz = nscn.executeObject(cls);
+        String name = "getClassDef";
+        RFunction getClass = (RFunction) RContext.getRRuntimeASTAccess().forcePromise(name, REnvironment.getRegisteredNamespace("methods").get(name));
+        return RContext.getEngine().evalFunction(getClass, null, RCaller.createInvalid(null), true, null, clazz);
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/NativeStringCastNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/NativeStringCastNode.java
new file mode 100644
index 0000000000000000000000000000000000000000..92d7e734174965433a9a453dff0308b3106c4968
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/NativeStringCastNode.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2018, 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.nodes;
+
+import static com.oracle.truffle.r.runtime.data.NativeDataAccess.readNativeString;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+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.Message;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.UnsupportedMessageException;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.RInternalError;
+
+public abstract class NativeStringCastNode extends Node {
+
+    @Child private Node isPtrNode;
+
+    public static NativeStringCastNode create() {
+        return NativeStringCastNodeGen.create();
+    }
+
+    public abstract String executeObject(Object s);
+
+    @Specialization
+    @TruffleBoundary
+    String handleString(String s) {
+        return s;
+    }
+
+    protected static Node createAsPointerNode() {
+        return Message.AS_POINTER.createNode();
+    }
+
+    protected static Node createToNativeNode() {
+        return Message.TO_NATIVE.createNode();
+    }
+
+    protected boolean isPointerNode(TruffleObject s) {
+        if (isPtrNode == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            isPtrNode = insert(Message.IS_POINTER.createNode());
+        }
+        return ForeignAccess.sendIsPointer(isPtrNode, s);
+    }
+
+    @Specialization(guards = "isPointerNode(s)")
+    String handlePointerAddress(TruffleObject s, @Cached("createAsPointerNode()") Node sAsPtrNode) {
+        try {
+            return readNativeString(ForeignAccess.sendAsPointer(sAsPtrNode, s));
+        } catch (UnsupportedMessageException e) {
+            throw RInternalError.shouldNotReachHere(e);
+        }
+    }
+
+    @Specialization(guards = "!isPointerNode(s)")
+    String handleNonPointerAddress(TruffleObject s, @Cached("createToNativeNode()") Node sToNativeNode, @Cached("createAsPointerNode()") Node sAsPtrNode) {
+        try {
+            Object sNative = ForeignAccess.sendToNative(sToNativeNode, s);
+            return readNativeString(ForeignAccess.sendAsPointer(sAsPtrNode, (TruffleObject) sNative));
+        } catch (UnsupportedMessageException e) {
+            throw RInternalError.shouldNotReachHere(e);
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/NewCustomConnectionNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/NewCustomConnectionNode.java
index dc8e816a7d5ae6cf967e8facb8c3683e1b13f0c8..6378bf00df6df13562e6ff0e3f66194cd0bfb477 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/NewCustomConnectionNode.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/NewCustomConnectionNode.java
@@ -22,19 +22,11 @@
  */
 package com.oracle.truffle.r.ffi.impl.nodes;
 
-import static com.oracle.truffle.r.runtime.data.NativeDataAccess.readNativeString;
-
 import java.io.IOException;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 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.Message;
-import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.interop.UnsupportedMessageException;
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.InvalidConnection;
 import com.oracle.truffle.r.runtime.conn.NativeConnections.NativeRConnection;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
@@ -47,36 +39,11 @@ public abstract class NewCustomConnectionNode extends FFIUpCallNode.Arg4 {
 
     @Specialization
     @TruffleBoundary
-    Object handleStrings(String description, String mode, String className, RExternalPtr connAddr) {
-        try {
-            return new NativeRConnection(description, mode, className, connAddr).asVector();
-        } catch (IOException e) {
-            return InvalidConnection.instance.asVector();
-        }
-    }
-
-    protected static Node createAsPointerNode() {
-        return Message.AS_POINTER.createNode();
-    }
-
-    @Specialization
-    @TruffleBoundary
-    Object handleAddresses(TruffleObject description, TruffleObject mode, TruffleObject className, RExternalPtr connAddr,
-                    @Cached("createAsPointerNode()") Node descriptionAsPtrNode, @Cached("createAsPointerNode()") Node modeAsPtrNode, @Cached("createAsPointerNode()") Node classNameAsPtrNode) {
-        try {
-            return handleAddresses(ForeignAccess.sendAsPointer(descriptionAsPtrNode, description), ForeignAccess.sendAsPointer(modeAsPtrNode, mode),
-                            ForeignAccess.sendAsPointer(classNameAsPtrNode, className), connAddr);
-        } catch (UnsupportedMessageException e) {
-            throw RInternalError.shouldNotReachHere(e);
-        }
-    }
-
-    private static Object handleAddresses(long description, long mode, long className, RExternalPtr connAddr) {
+    Object handleStrings(Object description, Object mode, Object className, RExternalPtr connAddr, @Cached("create()") NativeStringCastNode nscn) {
         try {
-            return new NativeRConnection(readNativeString(description), readNativeString(mode), readNativeString(className), connAddr).asVector();
+            return new NativeRConnection(nscn.executeObject(description), nscn.executeObject(mode), nscn.executeObject(className), connAddr).asVector();
         } catch (IOException e) {
             return InvalidConnection.instance.asVector();
         }
     }
-
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/Str2TypeNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/Str2TypeNode.java
new file mode 100644
index 0000000000000000000000000000000000000000..cbc29c664e479ce754ebd79f06161476eb6e0200
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/Str2TypeNode.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2018, 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.nodes;
+
+import java.util.HashMap;
+
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
+
+public abstract class Str2TypeNode extends FFIUpCallNode.Arg1 {
+
+    private static HashMap<String, Integer> name2typeTable;
+
+    static {
+        name2typeTable = new HashMap<>(26);
+        name2typeTable.put("NULL", SEXPTYPE.NILSXP.code);
+        /* real types */
+        name2typeTable.put("symbol", SEXPTYPE.SYMSXP.code);
+        name2typeTable.put("pairlist", SEXPTYPE.LISTSXP.code);
+        name2typeTable.put("closure", SEXPTYPE.CLOSXP.code);
+        name2typeTable.put("environment", SEXPTYPE.ENVSXP.code);
+        name2typeTable.put("promise", SEXPTYPE.PROMSXP.code);
+        name2typeTable.put("language", SEXPTYPE.LANGSXP.code);
+        name2typeTable.put("special", SEXPTYPE.SPECIALSXP.code);
+        name2typeTable.put("builtin", SEXPTYPE.BUILTINSXP.code);
+        name2typeTable.put("char", SEXPTYPE.CHARSXP.code);
+        name2typeTable.put("logical", SEXPTYPE.LGLSXP.code);
+        name2typeTable.put("integer", SEXPTYPE.INTSXP.code);
+        name2typeTable.put("double", SEXPTYPE.REALSXP.code);
+        /*-  "real", for R <= 0.61.x */
+        name2typeTable.put("complex", SEXPTYPE.CPLXSXP.code);
+        name2typeTable.put("character", SEXPTYPE.STRSXP.code);
+        name2typeTable.put("...", SEXPTYPE.DOTSXP.code);
+        name2typeTable.put("any", SEXPTYPE.ANYSXP.code);
+        name2typeTable.put("expression", SEXPTYPE.EXPRSXP.code);
+        name2typeTable.put("list", SEXPTYPE.VECSXP.code);
+        name2typeTable.put("externalptr", SEXPTYPE.EXTPTRSXP.code);
+        name2typeTable.put("bytecode", SEXPTYPE.BCODESXP.code);
+        name2typeTable.put("weakref", SEXPTYPE.WEAKREFSXP.code);
+        name2typeTable.put("raw", SEXPTYPE.RAWSXP.code);
+        name2typeTable.put("S4", SEXPTYPE.S4SXP.code);
+        name2typeTable.put("numeric", SEXPTYPE.REALSXP.code);
+        name2typeTable.put("name", SEXPTYPE.SYMSXP.code);
+    }
+
+    @Child private Node clazzIsPtrNode;
+
+    public static Str2TypeNode create() {
+        return Str2TypeNodeGen.create();
+    }
+
+    @Specialization
+    Object handleString(Object n, @Cached("create()") NativeStringCastNode sc) {
+        String name = sc.executeObject(n);
+        if (name == null) {
+            return -1;
+        }
+        Integer result = name2typeTable.get(name);
+        return result != null ? result : -1;
+    }
+
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/FFIWrapNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/FFIWrapNode.java
index 115713fabac830b3415f1a145e1abde714fb6d5a..e6d51dbe8cf31523fe99b9882a4e1a984b8691ac 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/FFIWrapNode.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/FFIWrapNode.java
@@ -38,6 +38,7 @@ import com.oracle.truffle.r.runtime.data.RRaw;
 import com.oracle.truffle.r.runtime.data.RScalarList;
 import com.oracle.truffle.r.runtime.data.RScalarVector;
 import com.oracle.truffle.r.runtime.data.RSequence;
+import com.oracle.truffle.r.runtime.data.RString;
 
 public abstract class FFIWrapNode extends Node {
 
@@ -63,6 +64,11 @@ public abstract class FFIWrapNode extends Node {
         return wrap(RDataFactory.createStringVectorFromScalar(value));
     }
 
+    @Specialization
+    protected static Object wrap(RString value) {
+        return wrap(RDataFactory.createStringVectorFromScalar(value.getValue()));
+    }
+
     @Specialization
     protected static Object wrap(RInteger value) {
         return wrap(RDataFactory.createIntVectorFromScalar(value.getValue()));
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java
index 7151f48559114fb8d46b16b17ced7a418ab8e13e..a576084b4f92e967c536c75f70d17c849d4f3745 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java
@@ -32,7 +32,9 @@ import com.oracle.truffle.r.ffi.impl.nodes.AttributesAccessNodes.GetAttrib;
 import com.oracle.truffle.r.ffi.impl.nodes.AttributesAccessNodes.TAG;
 import com.oracle.truffle.r.ffi.impl.nodes.CoerceNodes.CoerceVectorNode;
 import com.oracle.truffle.r.ffi.impl.nodes.CoerceNodes.VectorToPairListNode;
+import com.oracle.truffle.r.ffi.impl.nodes.DoMakeClassNode;
 import com.oracle.truffle.r.ffi.impl.nodes.DuplicateNodes;
+import com.oracle.truffle.r.ffi.impl.nodes.GetClassDefNode;
 import com.oracle.truffle.r.ffi.impl.nodes.EnvNodes.LockBindingNode;
 import com.oracle.truffle.r.ffi.impl.nodes.EnvNodes.UnlockBindingNode;
 import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodes.CAARNode;
@@ -57,6 +59,7 @@ import com.oracle.truffle.r.ffi.impl.nodes.NewCustomConnectionNode;
 import com.oracle.truffle.r.ffi.impl.nodes.RMakeExternalPtrNode;
 import com.oracle.truffle.r.ffi.impl.nodes.RandFunctionsNodes;
 import com.oracle.truffle.r.ffi.impl.nodes.RfEvalNode;
+import com.oracle.truffle.r.ffi.impl.nodes.Str2TypeNode;
 import com.oracle.truffle.r.ffi.impl.nodes.TryRfEvalNode;
 import com.oracle.truffle.r.ffi.processor.RFFICpointer;
 import com.oracle.truffle.r.ffi.processor.RFFICstring;
@@ -111,9 +114,11 @@ public interface StdUpCallsRFFI {
 
     void Rf_defineVar(Object symbolArg, Object value, Object envArg);
 
-    Object R_getClassDef(@RFFICstring String clazz);
+    @RFFIUpCallNode(GetClassDefNode.class)
+    Object R_getClassDef(@RFFICstring(convert = false) Object clazz);
 
-    Object R_do_MAKE_CLASS(@RFFICstring String clazz);
+    @RFFIUpCallNode(DoMakeClassNode.class)
+    Object R_do_MAKE_CLASS(@RFFICstring(convert = false) Object clazz);
 
     @RFFIUpCallNode(MiscNodes.RDoNewObjectNode.class)
     Object R_do_new_object(Object classDef);
@@ -403,7 +408,8 @@ public interface StdUpCallsRFFI {
 
     Object R_MethodsNamespace();
 
-    int Rf_str2type(@RFFICstring String name);
+    @RFFIUpCallNode(Str2TypeNode.class)
+    int Rf_str2type(@RFFICstring(convert = false) Object name);
 
     int FASTR_getConnectionChar(Object obj);
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java
index e343e52ff66e7b26db4353a73881efad020312f3..921e6b763a09c3382814df79a335406a8b2c3b23 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, 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
@@ -208,7 +208,7 @@ public abstract class Rprof extends RExternalBuiltinNode.Arg8 implements MemoryC
             SourceSectionFilter.Builder builder = SourceSectionFilter.newBuilder();
             builder.tagIs(StandardTags.StatementTag.class);
             SourceSectionFilter filter = builder.build();
-            RInstrumentation.getInstrumenter().attachListener(filter, this);
+            RInstrumentation.getInstrumenter().attachExecutionEventListener(filter, this);
         }
 
         private void intervalElapsed() {
diff --git a/com.oracle.truffle.r.native/Makefile b/com.oracle.truffle.r.native/Makefile
index 514fd0857f73d08e6155749f40f68344b75049ce..159c2720d3a39a7032180944bd783e3d5d77db06 100644
--- a/com.oracle.truffle.r.native/Makefile
+++ b/com.oracle.truffle.r.native/Makefile
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -21,7 +21,7 @@
 # questions.
 #
 
-.PHONY: all clean 
+.PHONY: all clean
 
 export TOPDIR = $(CURDIR)
 export FASTR_R_HOME=$(abspath $(TOPDIR)/..)
@@ -30,6 +30,15 @@ export FASTR_NATIVE_DIR = $(TOPDIR)
 export R_VERSION = 3.4.0
 export GNUR_HOME = $(TOPDIR)/gnur/patch-build
 
+ifeq ($(FASTR_RFFI),llvm)
+ifndef FASTR_LLVM_TOOLS
+ifdef FASTR_LLVM_FOR_DRAGONEGG_HOME
+export FASTR_LLVM_TOOLS = $(FASTR_LLVM_FOR_DRAGONEGG_HOME)/bin
+$(info FASTR_LLVM_TOOLS set to $(FASTR_LLVM_TOOLS))
+endif
+endif
+endif
+
 $(info R_VERSION: $(R_VERSION))
 $(info GNUR_HOME: $(GNUR_HOME))
 
@@ -43,7 +52,7 @@ $(info GNUR_HOME_BINARY not set. Assuming the default location at $(GNUR_HOME_BI
 endif
 
 # Completely accurate dependency analysis is very difficult for this project, so use a version number
-# to force a clean build, and elsewhere use sentinels to avoid rebuilding when we can't compute the 
+# to force a clean build, and elsewhere use sentinels to avoid rebuilding when we can't compute the
 # dependencies accurately.
 
 all: checkversion
@@ -54,7 +63,7 @@ all: checkversion
 	$(MAKE) -C run
 	cp version.source version.built
 
-clean: 
+clean:
 	$(MAKE) -C include clean
 	$(MAKE) -C fficall clean
 	$(MAKE) -C run clean
diff --git a/com.oracle.truffle.r.native/fficall/Makefile b/com.oracle.truffle.r.native/fficall/Makefile
index f6176fd2d0aa5d3f78ee729487b1dfa2c7a38ecf..e6e0b6a202f5e7ebfec8c341944fe6501e0b5d8d 100644
--- a/com.oracle.truffle.r.native/fficall/Makefile
+++ b/com.oracle.truffle.r.native/fficall/Makefile
@@ -57,7 +57,7 @@ ifeq ($(FASTR_RFFI),managed)
 else
 ifeq ($(OS_NAME),Darwin)
 	$(DYLIB_LD) $(DYLIB_LDFLAGS) -Wl,-rpath,@loader_path/ -o $(R_LIB) $(wildcard lib/*.o) -L$(FASTR_LIB_DIR) -ldl -lRblas -lRlapack  -lpcre -lz $(VERSION_FLAGS)
-ifneq ($(FASTR_RFFI),llvm)	
+ifneq ($(FASTR_RFFI),llvm)
 	install_name_tool -change libRblas.dylib @rpath/libRblas.dylib $(R_LIB)
 	install_name_tool -change libRlapack.dylib @rpath/libRlapack.dylib $(R_LIB)
 	install_name_tool -id @rpath/libR.dylib $(R_LIB)
@@ -80,6 +80,7 @@ fficall.done: common.done
 
 else
 ifeq ($(FASTR_RFFI),llvm)
+export R_PACKAGE_DIR="lib"
 fficall.done: common.done
 	$(MAKE) -C src/truffle_llvm all
 	touch fficall.done
@@ -90,7 +91,7 @@ endif #nfi
 endif #managed
 
 common.done:
-	$(MAKE) -C src/common all	
+	$(MAKE) -C src/common all
 	touch common.done
 
 clean:
@@ -109,4 +110,3 @@ endif
 	rm -rf $(R_LIB)
 	rm -rf fficall.done
 	rm -rf common.done
-
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 307b1d2fcd52091e8055fa8d94262cfc8684ea77..1a6bc2c49b7a21559098ea7126a3d1a70ec9c902 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
@@ -288,9 +288,7 @@ typedef Rboolean (*call_Rf_NonNullStringMatch)(SEXP s, SEXP t);
 typedef SEXP (*call_getvar)();
 typedef SEXP (*call_R_ParseVector)(SEXP text, int n, SEXP srcFile);
 typedef SEXPTYPE (*call_Rf_str2type)(const char *s);
-typedef SEXP (*call_CLOENV)(SEXP closure);
 typedef SEXP (*call_octsize)(SEXP size);
-typedef void (*call_Rf_PrintValue)(SEXP x);
 
 // connections
 
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_llvm/Memory.c b/com.oracle.truffle.r.native/fficall/src/truffle_llvm/Memory.c
index 1f8079ac7515c46a009fe93d244ab87af3d2020d..734c99bdd75b19f40c5ac23027972176eedcb324 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_llvm/Memory.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_llvm/Memory.c
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1995-2015, The R Core Team
  * Copyright (c) 2003, The R Foundation
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -19,22 +19,25 @@
 // The table of transient objects that have been allocated dur the current FFI call
 static void **tMemTable;
 // hwm of tMemTable
-static int tMemTableIndex;
+static int tMemTableIndex = -1;
 static int tMemTableLength;
 
 void *R_chk_calloc(size_t nelem, size_t elsize);
 
 // Memory that is auto-reclaimed across FFI calls
 char *R_alloc(size_t n, int size) {
+	tMemTableIndex++;
     void *p = R_chk_calloc(n, size);
     if (tMemTableIndex >= tMemTableLength) {
-	int newLength = 2 * tMemTableLength;
+	int newLength = tMemTableLength == 0 ? 1 : 2 * tMemTableLength;
 	void *newtMemTable = malloc(sizeof(void*) * newLength);
 	if (newtMemTable == NULL) {
 	    fatalError("malloc failure");
 	}
-	memcpy(newtMemTable, tMemTable, tMemTableLength * sizeof(void*));
-	free(tMemTable);
+	if (tMemTableLength > 0) {
+		memcpy(newtMemTable, tMemTable, tMemTableLength * sizeof(void*));
+		free(tMemTable);
+	}
 	tMemTable = newtMemTable;
 	tMemTableLength = newLength;
     }
@@ -54,9 +57,10 @@ char* S_realloc(char *p, long a, long b, int size) {
 
 void allocExit() {
     int i;
-    for (i = 0; i < tMemTableIndex; i++) {
+    for (i = 0; i <= tMemTableIndex; i++) {
 	free(tMemTable[i]);
     }
+    tMemTableIndex = 0;
 }
 
 void *R_chk_calloc(size_t nelem, size_t elsize) {
@@ -116,4 +120,3 @@ SEXP Rf_allocS4Object() {
 	unimplemented("Rf_allocS4Object unimplemented");
 	return NULL;
 }
-
diff --git a/com.oracle.truffle.r.native/gnur/patch/src/library/Makefile b/com.oracle.truffle.r.native/gnur/patch/src/library/Makefile
index 7c53c00be0dd72304ec050614f070433a4c29214..6861f1ebc71f116b02a5461391cfce1a6ad9fbfd 100644
--- a/com.oracle.truffle.r.native/gnur/patch/src/library/Makefile
+++ b/com.oracle.truffle.r.native/gnur/patch/src/library/Makefile
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2014, 2018, 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
@@ -25,6 +25,7 @@
 
 SUBDIRS = base compiler datasets utils grDevices graphics grid parallel splines stats stats4 methods tools
 export FASTR_LIBRARY_DIR = $(abspath $(TOPDIR)/../library)
+export R_PACKAGE_DIR="."
 
 all: libdir make_subdirs
 
@@ -39,6 +40,6 @@ clean_subdirs:
 	for dir in $(SUBDIRS); do \
 		$(MAKE) PACKAGE=$$dir -C $$dir clean || exit 1; \
 	done
-	
+
 libdir:
 	mkdir -p $(FASTR_LIBRARY_DIR)
diff --git a/com.oracle.truffle.r.native/gnur/patch/src/library/stats/Makefile b/com.oracle.truffle.r.native/gnur/patch/src/library/stats/Makefile
index 20981356dc097eca04fb87403d78872f5ff8c180..ed0b9d2ac4dced1d261355f019cbb3d9b048894a 100644
--- a/com.oracle.truffle.r.native/gnur/patch/src/library/stats/Makefile
+++ b/com.oracle.truffle.r.native/gnur/patch/src/library/stats/Makefile
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2014, 2018, 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
@@ -33,5 +33,4 @@ endif
 
 PKG_LIBS := $(LAPACK_LIBS) $(BLAS_LIBS) -L$(FASTR_LIB_DIR) $(FLIBS)
 PKG_INCLUDES = -I src
-
 include ../lib.mk
diff --git a/com.oracle.truffle.r.native/llvm_tools/llvm-ar b/com.oracle.truffle.r.native/llvm_tools/llvm-ar
index 2462ea65edb0de5e818c42ebd2f05d7cb4263696..2045a4ef823ca58a12b1c07b6892882f551b0739 100755
--- a/com.oracle.truffle.r.native/llvm_tools/llvm-ar
+++ b/com.oracle.truffle.r.native/llvm_tools/llvm-ar
@@ -25,13 +25,6 @@
 SOURCE="$0"
 DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
 
-while [[ $# -gt 0 ]]
-do
-	f=`basename $1`
-	ext=${f##*.}
-	if [ $ext == 'o' ]
-	then
-		echo $1 >> $R_PACKAGE_DIR/libobjects
-	fi
-	shift
-done
+. $DIR/llvm-helper
+
+create_bc_archive $@
diff --git a/com.oracle.truffle.r.native/llvm_tools/llvm-c++ b/com.oracle.truffle.r.native/llvm_tools/llvm-c++
index ee6af85450f4d49ce68115f66c972da8fd3e8db7..ec93f97e3d15ef4168b0221b2e714401f2ef4b28 100755
--- a/com.oracle.truffle.r.native/llvm_tools/llvm-c++
+++ b/com.oracle.truffle.r.native/llvm_tools/llvm-c++
@@ -31,12 +31,23 @@ analyze_args "$@"
 
 if [ $is_link -eq 1 ]
 then
-  extraObj=`cat $R_PACKAGE_DIR/libobjects`
+  extraObj=""
+  if [ -f "$R_PACKAGE_DIR/libobjects" ]; then
+     extraObj=`cat "$R_PACKAGE_DIR/libobjects"`
+  fi
   create_bc_lib $@ $extraObj
 else
   llvm_tool=clang++
   get_llvm_tool
+  unamestr=`uname`
+  if [[ "$unamestr" == 'Linux' ]]; then
+    llvm_args="-stdlib=libc++ -I/usr/include/libcxxabi $llvm_args"
+  fi
   runit $llvm_tool_bin $llvm_args
-  mem2reg_opt
-  fake_obj
+
+  # the llvm_ir_file is empty if the result is sent to stdout
+  if [ -n "$llvm_ir_file" ]; then
+    mem2reg_opt
+    fake_obj
+  fi
 fi
diff --git a/com.oracle.truffle.r.native/llvm_tools/llvm-cc b/com.oracle.truffle.r.native/llvm_tools/llvm-cc
index 1d88276ba548d5963757f5e6d168930e76822097..42acf7a3271e7f3dc4c266c76d8928ce8940ae91 100755
--- a/com.oracle.truffle.r.native/llvm_tools/llvm-cc
+++ b/com.oracle.truffle.r.native/llvm_tools/llvm-cc
@@ -29,15 +29,20 @@ DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
 fortran=0
 analyze_args "$@"
 
-
 if [ $is_link -eq 1 ]
 then
-  extraObj=`cat $R_PACKAGE_DIR/libobjects`
+  extraObj=""
+  if [ -f "$R_PACKAGE_DIR/libobjects" ]; then
+     extraObj=`cat "$R_PACKAGE_DIR/libobjects"`
+  fi
   create_bc_lib $@ $extraObj
 else
   llvm_tool=clang
   get_llvm_tool
   runit $llvm_tool_bin $llvm_args
-  mem2reg_opt
-  fake_obj
+  # the llvm_ir_file is empty if the result is sent to stdout
+  if [ -n "$llvm_ir_file" ]; then
+    mem2reg_opt
+    fake_obj
+  fi
 fi
diff --git a/com.oracle.truffle.r.native/llvm_tools/llvm-fc b/com.oracle.truffle.r.native/llvm_tools/llvm-fc
index 084f68d2df945ab446df70d3df1a56f090f34770..03bd793753a3789d904cdb23a54af2d4c1d759e6 100755
--- a/com.oracle.truffle.r.native/llvm_tools/llvm-fc
+++ b/com.oracle.truffle.r.native/llvm_tools/llvm-fc
@@ -59,5 +59,8 @@ ll_to_bc
 runit $FASTR_LLVM_GFORTRAN_LLVM_AS $llvm_ir_file -o $llvm_ir_bc_file
 runit rm $llvm_ir_file
 llvm_ir_file=$llvm_ir_bc_file
-mem2reg_opt
-fake_obj
+# the llvm_ir_file is empty if the result is sent to stdout
+if [ -n "$llvm_ir_file" ]; then
+  mem2reg_opt
+  fake_obj
+fi
diff --git a/com.oracle.truffle.r.native/llvm_tools/llvm-helper b/com.oracle.truffle.r.native/llvm_tools/llvm-helper
index 598bb39e4058d6469a6d9d94fb69e5e0af4cb252..2f06ecefc74eeeb388e7254d19e9f884609e2195 100644
--- a/com.oracle.truffle.r.native/llvm_tools/llvm-helper
+++ b/com.oracle.truffle.r.native/llvm_tools/llvm-helper
@@ -62,26 +62,26 @@ function analyze_args() {
 
   is_link=0
   llvm_ir_file=""
-  
+
   while [[ $# -gt 0 ]]
   do
     llvm_args+="$1 "
     case $1 in
       -o)
         shift
-	p=$1
-	f=`basename $p`
-	d=`dirname $p`
-	ext=${f##*.}
-	if [ $ext == 'so' ] || [ $ext == 'dylib' ]
-	then
-	  is_link=1
-	elif [ $ext == 'o' ]
-	then
-	  llvm_ir_file=${d}/${f%%.*}
-	  llvm_ir_file+=$llvm_file_ext
-	  llvm_args+="$llvm_ir_file "
-	fi
+		p=$1
+		f=`basename $p`
+		d=`dirname $p`
+		ext=${f##*.}
+		if [ $ext == 'so' ] || [ $ext == 'dylib' ]
+		then
+		  is_link=1
+		elif [ $ext == 'o' ]
+		then
+		  llvm_ir_file=${d}/${f%%.*}
+		  llvm_ir_file+=$llvm_file_ext
+		  llvm_args+="$llvm_ir_file "
+		fi
       ;;
      *)
      ;;
@@ -96,9 +96,9 @@ function analyze_args() {
 # path to tool (defaults to plain ${llvm_tool}, assumed to be on the PATH)
 
 function get_llvm_tool() {
-  if [ -n "${FASTR_LLVM_HOME}" ]
+  if [ -n "${FASTR_LLVM_TOOLS}" ]
   then
-    llvm_tool_bin=${FASTR_LLVM_HOME}/${llvm_tool}
+    llvm_tool_bin=${FASTR_LLVM_TOOLS}/${llvm_tool}
   else
     llvm_tool_uc=`echo ${llvm_tool} | tr /a-z/ /A-Z/ | tr /+/ /P/`
     x=FASTR_LLVM_${llvm_tool_uc}
@@ -111,7 +111,6 @@ function get_llvm_tool() {
   fi
 }
 
-
 function mem2reg_opt() {
    llvm_tool="opt"
    get_llvm_tool
@@ -126,40 +125,118 @@ function mem2reg_opt() {
 function fake_obj() {
   f=`basename $llvm_ir_file`
   d=`dirname $llvm_ir_file`
-  runit touch ${d}/${f%%.*}.o 
+  runit touch ${d}/${f%%.*}.o
 }
 
 # Input: all the arguments to the original command line
 function create_bc_lib() {
   bcfiles=""
   lib=""
+  statlibs="$R_PACKAGE_DIR/statlibs"
+  linkedLibs="LIBS"
+  > $linkedLibs
   while [[ $# -gt 0 ]]
   do
     case $1 in
       -o)
         shift
-	lib=$1
-      ;;
+		    lib=$1
+        ;;
+      -l*)
+		    linkedLib=`echo $1 | cut -c 3-`
+        statLibFound='0'
+        if [ -f "$statlibs" ]; then
+          statLibFound=`cat "$statlibs" | grep "lib${linkedLib}.a" | wc -l`
+        fi
+        if [ $statLibFound == '0' ]
+		    then
+          echo $linkedLib >> $linkedLibs
+		    fi
+        ;;
+      -*)
+        # ignore other options
+        ;;
+      *)
+        f=$(basename $1)
+     	  ext=${f##*.}
+		    if [ $ext == 'o' ]
+		    then
+	  		   fn="$(dirname $1)/${f%%.*}.bc"
+			     bcfiles+="$fn "
+		    fi
+        ;;
+    esac
+    shift
+  done
+
+# we do not have the luxury of controlling the name of the entry (unlike in python)
+# it will be the pathname, which we will reduce to a module name on input in FastR
+
+# link the bitcode files into a single one using llvm-link before zipping it
+  llvm_tool=llvm-link
+  get_llvm_tool
+  echo "Linking $lib.bc from LLVM modules: $bcfiles"
+  runit $llvm_tool_bin $bcfiles -o $lib.bc
+  runit zip -r $lib $lib.bc $linkedLibs
+  rm $lib.bc
+}
+
+# It appends objects constituting a static library to the list of extra object files.
+# This list is maintained in $R_PACKAGE_DIR/libobjects and is later read in llvm-cc and
+# llvm-c++ to append the object files from the list to other objects when making
+# the package dynamic library. This mechanism is a workaround for the fact that the llvm
+# linker does not support linking to static libraries, as the standard linker does
+# through the -l and -L options.
+function create_bc_archive() {
+
+  # Create a CSV file containing all object files constituting the archive (i.e. the static library).
+  # The CSV has two columns: the object name in the archive and the full path of the object file.
+  # The object name columns serves as the join column when joining with the set of unique
+  # symbols objects (see below) to get the final list of objects to be linked with
+  # the package dynamic library in the end.
+  shift
+  archname=$1
+  arargs="rcs $archname "
+  shift
+
+  archObjCSVtmp="archived_objects.tmp"
+  archObjCSV="archived_objects.csv"
+  exportedObjCSV="exported_objects.csv"
+  > $archObjCSV
+
+  while [[ $# -gt 0 ]]
+  do
+    case $1 in
      *)
         f=$1
      	ext=${f##*.}
 	if [ $ext == 'o' ]
 	then
+	  fullPath=`echo $(cd $(dirname $1) && pwd -P)/$(basename $1)`
 	  fn=${f%%.*}.bc
-	  bcfiles+="$fn "
+	  arargs+="$fn "
+	  echo "$(basename $fn) $fullPath" >> $archObjCSVtmp
+	else
+	  arargs+="$1 "
 	fi
      ;;
     esac
     shift
   done
 
-# we do not have the luxury of controlling the name of the entry (unlike in python)
-# it will be the pathname, which we will reduce to a module name on input in FastR
+  sort -d --field-separator=' ' --key=1 $archObjCSVtmp > $archObjCSV
 
-# link the bitcode files into a single one using llvm-link before zipping it
-  llvm_tool=llvm-link
-  get_llvm_tool
-  runit $llvm_tool_bin $bcfiles -o $lib.bc
-  runit zip -r $lib $lib.bc
-  rm $lib.bc
+  # Create the archive (via llvm-ar) that is then used to read the symbol table via llvm-nm.
+  # The symbol table allows for selecting a set of objects exporting unique symbols.
+  llvm-ar $arargs
+
+  # This command extracts a set of objects from the archive that do not export duplicate symbols
+  llvm-nm -print-file-name $archname | grep "\-\-\-\-" | awk -F ' ' '{print $1" "$4}' | sort -d --field-separator=' ' --key=2 -u | awk -F ':' '{print $2}' | sort -d -u > $exportedObjCSV
+
+  # Join the archived objects CSV with the unique symbols objects CSV to get the list of objects to be statically linked to the package dynamic library.
+  # Append the result to the global list of extra object files.
+  join -t " " -1 1 -2 1 $archObjCSV $exportedObjCSV | awk -F ' ' '{print $2}' >> "$R_PACKAGE_DIR/libobjects"
+
+  # Record the archive (static library) name to distinguish between LLVM static libs and native libs when linking (via -l)
+  echo $archname >> "$R_PACKAGE_DIR/statlibs"
 }
diff --git a/com.oracle.truffle.r.native/run/edMakeconf.etc.llvm b/com.oracle.truffle.r.native/run/edMakeconf.etc.llvm
index d9a5864d77d6d0115a2d5ab58a250f6e39a18487..c4972785f1b97ace17efcf41e7d9d36f203e2910 100644
--- a/com.oracle.truffle.r.native/run/edMakeconf.etc.llvm
+++ b/com.oracle.truffle.r.native/run/edMakeconf.etc.llvm
@@ -8,6 +8,11 @@ d
 i
 CXX = $(R_HOME)/bin/llvm-c++
 .
+/^CXX11 =/
+d
+i
+CXX11 = $(R_HOME)/bin/llvm-c++
+.
 /^FC =/
 d
 i
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSyntaxTree.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSyntaxTree.java
index 0ca769eaa5f61d79ae53d718546f80371122e906..3fff34c2ad43ad22a05ba966c305c843cb4c8bfc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSyntaxTree.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSyntaxTree.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, 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
@@ -32,6 +32,7 @@ import java.io.IOException;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.instrumentation.Tag;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.NodeVisitor;
 import com.oracle.truffle.api.source.SourceSection;
@@ -226,8 +227,8 @@ public abstract class FastRSyntaxTree extends RBuiltinNode.Arg4 {
     private static void printTags(RNode node) {
         writeString(" # tags [ ", false);
         for (int i = 0; i < RSyntaxTags.ALL_TAGS.length; i++) {
-            Class<?> tag = RSyntaxTags.ALL_TAGS[i];
-            if (node.isTaggedWith(tag)) {
+            Class<? extends Tag> tag = RSyntaxTags.ALL_TAGS[i];
+            if (node.hasTag(tag)) {
                 writeString(tag.getSimpleName(), false);
                 writeString(" ", false);
             }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java
index 90e5649085cbc0b8717a5aa7c1d454462b6a2679..70bda866deda77c3008f5519f9c85339645824ce 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java
@@ -169,7 +169,7 @@ public class DebugHandling {
         SourceSection lineSourceSection = fdn.createSection(line);
         SourceSectionFilter.Builder functionBuilder = RInstrumentation.createLineFilter(fdn, line, StandardTags.StatementTag.class);
         LineBreakpointEventListener listener = new LineBreakpointEventListener(lineSourceSection);
-        listener.setBinding(instrumenter.attachListener(functionBuilder.build(), listener));
+        listener.setBinding(instrumenter.attachExecutionEventListener(functionBuilder.build(), listener));
         RContext.getInstance().stateInstrumentation.putDebugListener(lineSourceSection, listener);
     }
 
@@ -317,7 +317,7 @@ public class DebugHandling {
         @TruffleBoundary
         private void attachStepInto() {
             FunctionStatementsEventListener parentListener = getFunctionStatementsEventListener(functionDefinitionNode);
-            parentListener.stepIntoInstrument = RInstrumentation.getInstrumenter().attachListener(SourceSectionFilter.newBuilder().tagIs(StandardTags.RootTag.class).build(),
+            parentListener.stepIntoInstrument = RInstrumentation.getInstrumenter().attachExecutionEventListener(SourceSectionFilter.newBuilder().tagIs(StandardTags.RootTag.class).build(),
                             new StepIntoInstrumentListener(parentListener));
 
         }
@@ -400,7 +400,7 @@ public class DebugHandling {
                 SourceSectionFilter.Builder statementBuilder = RInstrumentation.createFunctionStatementFilter(functionDefinitionNode);
                 statementBuilder.tagIsNot(RSyntaxTags.LoopTag.class);
                 Instrumenter instrumenter = RInstrumentation.getInstrumenter();
-                statementListener.setBinding(instrumenter.attachListener(statementBuilder.build(), statementListener));
+                statementListener.setBinding(instrumenter.attachExecutionEventListener(statementBuilder.build(), statementListener));
             }
         }
 
@@ -408,7 +408,7 @@ public class DebugHandling {
             LoopStatementEventListener lser = new LoopStatementEventListener(functionDefinitionNode, text, condition, loopNode, this);
             loopStatementListeners.add(lser);
             Instrumenter instrumenter = RInstrumentation.getInstrumenter();
-            lser.setBinding(instrumenter.attachListener(ssf, lser));
+            lser.setBinding(instrumenter.attachExecutionEventListener(ssf, lser));
             return lser;
         }
 
@@ -432,7 +432,7 @@ public class DebugHandling {
 
             Instrumenter instrumenter = RInstrumentation.getInstrumenter();
             SourceSectionFilter.Builder functionBuilder = RInstrumentation.createFunctionFilter(functionDefinitionNode, StandardTags.RootTag.class);
-            setBinding(instrumenter.attachListener(functionBuilder.build(), this));
+            setBinding(instrumenter.attachExecutionEventListener(functionBuilder.build(), this));
 
             // Next attach statement handler to all STATEMENTs except LOOPs
             attachStatementListener();
@@ -621,7 +621,7 @@ public class DebugHandling {
                 // in case we did a step into that never called a function
                 clearStepInstrument();
                 RBaseNode node = (RBaseNode) context.getInstrumentedNode();
-                if (node.isTaggedWith(StandardTags.RootTag.class)) {
+                if (node.hasTag(StandardTags.RootTag.class)) {
                     // already handled
                     return;
                 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/TraceHandling.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/TraceHandling.java
index 2bfa09ae8d6570b1fe0e5df1b21f91527c6ec625..2d2ff936bc88918e43e503817ddc5e9a77538703 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/TraceHandling.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/TraceHandling.java
@@ -90,7 +90,7 @@ public class TraceHandling {
             SourceSectionFilter.Builder builder = SourceSectionFilter.newBuilder();
             builder.tagIs(StandardTags.RootTag.class);
             SourceSectionFilter filter = builder.build();
-            RInstrumentation.getInstrumenter().attachListener(filter, fser);
+            RInstrumentation.getInstrumenter().attachExecutionEventListener(filter, fser);
             setOutputHandler();
         }
     }
@@ -105,7 +105,7 @@ public class TraceHandling {
         if (at == RMissing.instance) {
             // simple case
             TracerFunctionEntryEventListener listener = new TracerFunctionEntryEventListener(tracer, print);
-            binding = RInstrumentation.getInstrumenter().attachListener(RInstrumentation.createFunctionStartFilter(func).build(), listener);
+            binding = RInstrumentation.getInstrumenter().attachExecutionEventListener(RInstrumentation.createFunctionStartFilter(func).build(), listener);
             setOutputHandler();
             RContext.getInstance().stateInstrumentation.putTraceBinding(RInstrumentation.getSourceSection(func), binding);
         }
@@ -114,7 +114,7 @@ public class TraceHandling {
 
     private static void attachPrimitiveTraceHandler(RFunction func) {
         PrimitiveFunctionEntryEventListener fser = new PrimitiveFunctionEntryEventListener();
-        EventBinding<TraceEventListener> binding = RInstrumentation.getInstrumenter().attachListener(RInstrumentation.createFunctionStartFilter(func).build(), fser);
+        EventBinding<TraceEventListener> binding = RInstrumentation.getInstrumenter().attachExecutionEventListener(RInstrumentation.createFunctionStartFilter(func).build(), fser);
         setOutputHandler();
         RContext.getInstance().stateInstrumentation.putTraceBinding(RInstrumentation.getSourceSection(func), binding);
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java
index 7a8ffc3795c5d8b0b2d4a18ca4e7ead80dca0a6a..ed58d2311b2c90105134cad2a1fd45e97ce7c9cd 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java
@@ -27,7 +27,7 @@ import com.oracle.truffle.api.RootCallTarget;
 import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.frame.FrameDescriptor;
 import com.oracle.truffle.api.frame.MaterializedFrame;
-import com.oracle.truffle.api.instrumentation.InstrumentableFactory.WrapperNode;
+import com.oracle.truffle.api.instrumentation.InstrumentableNode.WrapperNode;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.NodeUtil;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/AbstractLoopNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/AbstractLoopNode.java
index cc5a512ce2d6e324aeb8f00b5fbe3ace18c80135..f6a7f0db7d59992d0a2e306febecd6b53d6d05b5 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/AbstractLoopNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/AbstractLoopNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -23,7 +23,7 @@
 package com.oracle.truffle.r.nodes.control;
 
 import com.oracle.truffle.api.CompilerAsserts;
-import com.oracle.truffle.api.instrumentation.InstrumentableFactory.WrapperNode;
+import com.oracle.truffle.api.instrumentation.InstrumentableNode.WrapperNode;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.RepeatingNode;
 import com.oracle.truffle.api.nodes.RootNode;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallBaseNode.java
index 3b6ea6ba9905dfe5e19850e8b53ca7c302252a8e..c97c5fcd38bcca9e555c3f3d4f1037ac7af3edd9 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallBaseNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallBaseNode.java
@@ -24,7 +24,7 @@ package com.oracle.truffle.r.nodes.function;
 
 import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.instrumentation.Instrumentable;
+import com.oracle.truffle.api.instrumentation.ProbeNode;
 import com.oracle.truffle.r.runtime.Arguments;
 import com.oracle.truffle.r.runtime.data.RTypes;
 import com.oracle.truffle.r.runtime.nodes.RInstrumentableNode;
@@ -32,9 +32,13 @@ import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 @TypeSystemReference(RTypes.class)
-@Instrumentable(factory = com.oracle.truffle.r.nodes.function.RCallBaseNodeWrapperFactory.class)
 public abstract class RCallBaseNode extends RNode implements RInstrumentableNode {
 
+    @Override
+    public WrapperNode createWrapper(ProbeNode probe) {
+        return new RCallBaseNodeWrapper(this, probe);
+    }
+
     public abstract Object execute(VirtualFrame frame, Object function);
 
     public abstract Arguments<RSyntaxNode> getArguments();
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallBaseNodeWrapper.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallBaseNodeWrapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..3b90fa8871ecbaffbf190d3e2a1ddd3caeda14e5
--- /dev/null
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallBaseNodeWrapper.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2016, 2018, 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.nodes.function;
+
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.instrumentation.InstrumentableNode.WrapperNode;
+import com.oracle.truffle.api.instrumentation.ProbeNode;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.nodes.NodeCost;
+import com.oracle.truffle.api.nodes.NodeInfo;
+import com.oracle.truffle.api.source.SourceSection;
+import com.oracle.truffle.r.runtime.Arguments;
+import com.oracle.truffle.r.runtime.nodes.RNode;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
+
+@NodeInfo(cost = NodeCost.NONE)
+public final class RCallBaseNodeWrapper extends RCallBaseNode implements WrapperNode {
+    @Child private RCallBaseNode delegate;
+    @Child private ProbeNode probeNode;
+
+    public RCallBaseNodeWrapper(RCallBaseNode delegate, ProbeNode probeNode) {
+        assert delegate != null;
+        this.delegate = delegate;
+        this.probeNode = probeNode;
+    }
+
+    @Override
+    public Arguments<RSyntaxNode> getArguments() {
+        return delegate.getArguments();
+    }
+
+    @Override
+    public RNode getFunction() {
+        return delegate.getFunction();
+    }
+
+    @Override
+    public Node getDelegateNode() {
+        return delegate;
+    }
+
+    @Override
+    public ProbeNode getProbeNode() {
+        return probeNode;
+    }
+
+    @Override
+    public Object execute(VirtualFrame frame) {
+        Object returnValue;
+        for (;;) {
+            boolean wasOnReturnExecuted = false;
+            try {
+                probeNode.onEnter(frame);
+                returnValue = delegate.execute(frame);
+                wasOnReturnExecuted = true;
+                probeNode.onReturnValue(frame, returnValue);
+                break;
+            } catch (Throwable t) {
+                Object result = probeNode.onReturnExceptionalOrUnwind(frame, t, wasOnReturnExecuted);
+                if (result == ProbeNode.UNWIND_ACTION_REENTER) {
+                    continue;
+                } else if (result != null) {
+                    returnValue = result;
+                    break;
+                }
+                throw t;
+            }
+        }
+        return returnValue;
+    }
+
+    @Override
+    public Object visibleExecute(VirtualFrame frame) {
+        Object returnValue;
+        for (;;) {
+            boolean wasOnReturnExecuted = false;
+            try {
+                probeNode.onEnter(frame);
+                returnValue = delegate.visibleExecute(frame);
+                wasOnReturnExecuted = true;
+                probeNode.onReturnValue(frame, returnValue);
+                break;
+            } catch (Throwable t) {
+                Object result = probeNode.onReturnExceptionalOrUnwind(frame, t, wasOnReturnExecuted);
+                if (result == ProbeNode.UNWIND_ACTION_REENTER) {
+                    continue;
+                } else if (result != null) {
+                    returnValue = result;
+                    break;
+                }
+                throw t;
+            }
+        }
+        return returnValue;
+    }
+
+    @Override
+    public Object execute(VirtualFrame frame, Object function) {
+        Object returnValue;
+        for (;;) {
+            boolean wasOnReturnExecuted = false;
+            try {
+                probeNode.onEnter(frame);
+                returnValue = delegate.execute(frame, function);
+                wasOnReturnExecuted = true;
+                probeNode.onReturnValue(frame, returnValue);
+                break;
+            } catch (Throwable t) {
+                Object result = probeNode.onReturnExceptionalOrUnwind(frame, t, wasOnReturnExecuted);
+                if (result == ProbeNode.UNWIND_ACTION_REENTER) {
+                    continue;
+                } else if (result != null) {
+                    returnValue = result;
+                    break;
+                }
+                throw t;
+            }
+        }
+        return returnValue;
+    }
+
+    @Override
+    public RSyntaxNode getRSyntaxNode() {
+        return delegate.asRSyntaxNode();
+    }
+
+    @Override
+    public SourceSection getSourceSection() {
+        return delegate.getSourceSection();
+    }
+}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallBaseNodeWrapperFactory.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallBaseNodeWrapperFactory.java
deleted file mode 100644
index a3b54e872e40f1b8ba9ae3a81d7c5c6fad7f5fd6..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallBaseNodeWrapperFactory.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Copyright (c) 2016, 2018, 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.nodes.function;
-
-import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.instrumentation.InstrumentableFactory;
-import com.oracle.truffle.api.instrumentation.ProbeNode;
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.api.nodes.NodeCost;
-import com.oracle.truffle.api.nodes.NodeInfo;
-import com.oracle.truffle.api.source.SourceSection;
-import com.oracle.truffle.r.runtime.Arguments;
-import com.oracle.truffle.r.runtime.nodes.RNode;
-import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
-
-public class RCallBaseNodeWrapperFactory implements InstrumentableFactory<RCallBaseNode> {
-
-    @NodeInfo(cost = NodeCost.NONE)
-    public static final class RCallBaseNodeWrapper extends RCallBaseNode implements InstrumentableFactory.WrapperNode {
-        @Child private RCallBaseNode delegate;
-        @Child private ProbeNode probeNode;
-
-        public RCallBaseNodeWrapper(RCallBaseNode delegate, ProbeNode probeNode) {
-            assert delegate != null;
-            this.delegate = delegate;
-            this.probeNode = probeNode;
-        }
-
-        @Override
-        public Arguments<RSyntaxNode> getArguments() {
-            return delegate.getArguments();
-        }
-
-        @Override
-        public RNode getFunction() {
-            return delegate.getFunction();
-        }
-
-        @Override
-        public Node getDelegateNode() {
-            return delegate;
-        }
-
-        @Override
-        public ProbeNode getProbeNode() {
-            return probeNode;
-        }
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            Object returnValue;
-            for (;;) {
-                boolean wasOnReturnExecuted = false;
-                try {
-                    probeNode.onEnter(frame);
-                    returnValue = delegate.execute(frame);
-                    wasOnReturnExecuted = true;
-                    probeNode.onReturnValue(frame, returnValue);
-                    break;
-                } catch (Throwable t) {
-                    Object result = probeNode.onReturnExceptionalOrUnwind(frame, t, wasOnReturnExecuted);
-                    if (result == ProbeNode.UNWIND_ACTION_REENTER) {
-                        continue;
-                    } else if (result != null) {
-                        returnValue = result;
-                        break;
-                    }
-                    throw t;
-                }
-            }
-            return returnValue;
-        }
-
-        @Override
-        public Object visibleExecute(VirtualFrame frame) {
-            Object returnValue;
-            for (;;) {
-                boolean wasOnReturnExecuted = false;
-                try {
-                    probeNode.onEnter(frame);
-                    returnValue = delegate.visibleExecute(frame);
-                    wasOnReturnExecuted = true;
-                    probeNode.onReturnValue(frame, returnValue);
-                    break;
-                } catch (Throwable t) {
-                    Object result = probeNode.onReturnExceptionalOrUnwind(frame, t, wasOnReturnExecuted);
-                    if (result == ProbeNode.UNWIND_ACTION_REENTER) {
-                        continue;
-                    } else if (result != null) {
-                        returnValue = result;
-                        break;
-                    }
-                    throw t;
-                }
-            }
-            return returnValue;
-        }
-
-        @Override
-        public Object execute(VirtualFrame frame, Object function) {
-            Object returnValue;
-            for (;;) {
-                boolean wasOnReturnExecuted = false;
-                try {
-                    probeNode.onEnter(frame);
-                    returnValue = delegate.execute(frame, function);
-                    wasOnReturnExecuted = true;
-                    probeNode.onReturnValue(frame, returnValue);
-                    break;
-                } catch (Throwable t) {
-                    Object result = probeNode.onReturnExceptionalOrUnwind(frame, t, wasOnReturnExecuted);
-                    if (result == ProbeNode.UNWIND_ACTION_REENTER) {
-                        continue;
-                    } else if (result != null) {
-                        returnValue = result;
-                        break;
-                    }
-                    throw t;
-                }
-            }
-            return returnValue;
-        }
-
-        @Override
-        public RSyntaxNode getRSyntaxNode() {
-            return delegate.asRSyntaxNode();
-        }
-
-        @Override
-        public SourceSection getSourceSection() {
-            return delegate.getSourceSection();
-        }
-    }
-
-    @Override
-    public InstrumentableFactory.WrapperNode createWrapper(RCallBaseNode node, ProbeNode probe) {
-        return new RCallBaseNodeWrapper(node, probe);
-    }
-}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RSyntaxTags.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RSyntaxTags.java
index 7f5b694b06537f899f0304c8765607aed29d9f80..75e32fd0802a978710322964a28bb756e54b5277 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RSyntaxTags.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RSyntaxTags.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, 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
@@ -23,14 +23,16 @@
 package com.oracle.truffle.r.nodes.instrumentation;
 
 import com.oracle.truffle.api.instrumentation.StandardTags;
+import com.oracle.truffle.api.instrumentation.Tag;
 
 public class RSyntaxTags {
 
-    public final class LoopTag {
+    public final class LoopTag extends Tag {
         private LoopTag() {
 
         }
     }
 
-    public static final Class<?>[] ALL_TAGS = new Class<?>[]{StandardTags.CallTag.class, StandardTags.StatementTag.class, StandardTags.RootTag.class, RSyntaxTags.LoopTag.class};
+    @SuppressWarnings("unchecked") public static final Class<? extends Tag>[] ALL_TAGS = (Class<? extends Tag>[]) new Class<?>[]{StandardTags.CallTag.class, StandardTags.StatementTag.class,
+                    StandardTags.RootTag.class, LoopTag.class};
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
index e8738cd70ba23d5d831d231cf4b7597f037b8a7d..7bef648d8b4e38b0ad54d4f1de55b92c1c9b929b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java
@@ -15,6 +15,7 @@ import static java.nio.file.StandardOpenOption.CREATE_NEW;
 import static java.nio.file.StandardOpenOption.WRITE;
 
 import java.io.BufferedWriter;
+import java.io.File;
 import java.io.IOException;
 import java.nio.file.AccessDeniedException;
 import java.nio.file.FileAlreadyExistsException;
@@ -368,7 +369,7 @@ public class RDeparse {
 
                 // just use the first 10 hex digits to have a nicer file name
                 if (qualifiedFunctionName != null && !qualifiedFunctionName.isEmpty() && !qualifiedFunctionName.equals("<no source>")) {
-                    path = tmpDir.resolve(qualifiedFunctionName + "-" + printHexBinary.substring(0, 10) + ".r");
+                    path = tmpDir.resolve(qualifiedFunctionName.replace(File.separatorChar, '_') + "-" + printHexBinary.substring(0, 10) + ".r");
                 } else {
                     path = tmpDir.resolve(printHexBinary.substring(0, 10) + ".r");
                 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/CharSXPWrapper.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/CharSXPWrapper.java
index 1f7f724a112834a8b6167f6033fd92acd594c93b..cf4b856b0a456b684d605d25c2fb3a05fdcec023 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/CharSXPWrapper.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/CharSXPWrapper.java
@@ -41,7 +41,6 @@ import com.oracle.truffle.r.runtime.RRuntime;
  */
 public final class CharSXPWrapper extends RObject implements RTruffleObject {
     private static final CharSXPWrapper NA = new CharSXPWrapper(RRuntime.STRING_NA);
-
     private String contents;
     private byte[] bytes;
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java
index 970c53a91db9977ee5094312eddea7c689293683..09b82c05c43a5a1e6f9dbf57cceae1b0c579f59b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java
@@ -114,6 +114,16 @@ public final class NativeDataAccess {
          */
         private long length;
 
+        /**
+         * It maintains the <code>1-?</code> relationship between this object and its native wrapper
+         * through which the native code accesses it. For instance, Sulong implements the "pointer"
+         * equality of two objects that are not pointers (i.e. <code>IS_POINTER</code> returns
+         * <code>false</code>) as the reference equality of the objects. It follows that the pointer
+         * comparison would fail if the same <code>RObject</code> instance were wrapped by two
+         * different native wrappers.
+         */
+        private Object nativeWrapper;
+
         NativeMirror() {
             this.id = counter.incrementAndGet();
         }
@@ -204,8 +214,8 @@ public final class NativeDataAccess {
         if (arg instanceof RObject) {
             RObject obj = (RObject) arg;
             NativeMirror mirror = (NativeMirror) obj.getNativeMirror();
-            if (mirror == null) {
-                mirror = putMirrorObject(arg, obj);
+            if (mirror == null || mirror.id == 0) {
+                mirror = putMirrorObject(arg, obj, mirror);
             }
             return mirror.id;
         }
@@ -213,16 +223,19 @@ public final class NativeDataAccess {
     }
 
     @TruffleBoundary
-    private static NativeMirror putMirrorObject(Object arg, RObject obj) {
-        NativeMirror mirror;
-        obj.setNativeMirror(mirror = arg instanceof CustomNativeMirror ? new NativeMirror(((CustomNativeMirror) arg).getCustomMirrorAddress()) : new NativeMirror());
+    private static NativeMirror putMirrorObject(Object arg, RObject obj, NativeMirror oldMirror) {
+        NativeMirror newMirror;
+        obj.setNativeMirror(newMirror = arg instanceof CustomNativeMirror ? new NativeMirror(((CustomNativeMirror) arg).getCustomMirrorAddress()) : new NativeMirror());
+        if (oldMirror != null) {
+            newMirror.nativeWrapper = oldMirror.nativeWrapper;
+        }
         // System.out.println(String.format("adding %16x = %s", mirror.id,
         // obj.getClass().getSimpleName()));
-        nativeMirrors.put(mirror.id, new WeakReference<>(obj));
+        nativeMirrors.put(newMirror.id, new WeakReference<>(obj));
         if (TRACE_MIRROR_ALLOCATION_SITES) {
-            registerAllocationSite(arg, mirror);
+            registerAllocationSite(arg, newMirror);
         }
-        return mirror;
+        return newMirror;
     }
 
     @TruffleBoundary
@@ -662,6 +675,7 @@ public final class NativeDataAccess {
         return mirror.dataAddress;
     }
 
+    @TruffleBoundary
     public static String readNativeString(long addr) {
         int len;
         for (len = 0; UnsafeAdapter.UNSAFE.getByte(addr + len) != 0; len++) {
@@ -691,4 +705,23 @@ public final class NativeDataAccess {
         mirror.length = length;
 
     }
+
+    public static void setNativeWrapper(RObject obj, Object wrapper) {
+        NativeMirror mirror = (NativeMirror) obj.getNativeMirror();
+        if (mirror == null) {
+            mirror = new NativeMirror(0);
+            obj.setNativeMirror(mirror);
+        }
+        mirror.nativeWrapper = wrapper;
+    }
+
+    public static Object getNativeWrapper(RObject obj) {
+        NativeMirror mirror = (NativeMirror) obj.getNativeMirror();
+        if (mirror == null) {
+            return null;
+        } else {
+            return mirror.nativeWrapper;
+        }
+    }
+
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RObject.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RObject.java
index 1b3555e35bade73c1fea251848d3169a5205df5d..d80f67f4bfb92aa100155117965e7870442e499f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RObject.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RObject.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -33,4 +33,5 @@ public abstract class RObject {
     public final Object getNativeMirror() {
         return nativeMirror;
     }
+
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java
index e3be9c96ea3e37a40fd7df240ff2bfbe95fa3640..8ba6f70a6a9a78a99fd0fcf5609becef434cf1af 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java
@@ -390,6 +390,9 @@ public final class RPairList extends RSharingAttributeStorage implements RAbstra
 
             @Override
             public RPairList next() {
+                if (plt instanceof RLanguage) {
+                    plt = ((RLanguage) plt).getPairList();
+                }
                 assert plt instanceof RPairList;
                 RPairList curr = (RPairList) plt;
                 plt = curr.cdr;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/memprof/MemAllocProfilerInstrument.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/memprof/MemAllocProfilerInstrument.java
index 3237a99b260e4bb22c8ab79d99a8e7e38f1c1110..9d3ea450bc17547d7f86ed6c4e782e227e6e8558 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/memprof/MemAllocProfilerInstrument.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/memprof/MemAllocProfilerInstrument.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
@@ -53,7 +53,7 @@ public class MemAllocProfilerInstrument extends TruffleInstrument {
         MemAllocEventFactory eventFactory = new MemAllocEventFactory(env);
         SourceSectionFilter.Builder builder = SourceSectionFilter.newBuilder();
         SourceSectionFilter filter = builder.tagIs(StandardTags.StatementTag.class).build();
-        instrumenter.attachFactory(filter, eventFactory);
+        instrumenter.attachExecutionEventFactory(filter, eventFactory);
         allocationEventBinding = instrumenter.attachAllocationListener(AllocationEventFilter.newBuilder().build(), eventFactory);
 
         env.registerService(eventFactory.memAllocStacks);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java
index b5ca21981bfe53d4b6a49a9e5651c54fe5a52bd6..c42a6dbd1eece79cc3d085fc7fbb8901d62a8ed8 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, 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
@@ -24,6 +24,7 @@ package com.oracle.truffle.r.runtime.nodes;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.instrumentation.Tag;
 import com.oracle.truffle.api.nodes.LoopNode;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.NodeVisitor;
@@ -184,9 +185,9 @@ public abstract class RBaseNode extends Node {
         return getRSyntaxNode().getSourceSection();
     }
 
-    @Override
-    public boolean isTaggedWith(Class<?> tag) {
-        return RContext.getRRuntimeASTAccess().isTaggedWith(this, tag);
+    public boolean hasTag(Class<? extends Tag> tag) {
+        // RNode, which is instrumentable, overrides this to actually check if the node has the tag
+        return false;
     }
 
     private static final long WORK_SCALE_FACTOR = 100;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RInstrumentableNode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RInstrumentableNode.java
index 063887490c149cf79700490b6a29fe3796f5754e..333fbe9f21a37cc6b34b24ee6b7d8d5bce7b3fa2 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RInstrumentableNode.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RInstrumentableNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, 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
@@ -22,13 +22,17 @@
  */
 package com.oracle.truffle.r.runtime.nodes;
 
-import com.oracle.truffle.api.instrumentation.InstrumentableFactory.WrapperNode;
+import com.oracle.truffle.api.instrumentation.InstrumentableNode.WrapperNode;
+import com.oracle.truffle.api.instrumentation.InstrumentableNode;
+import com.oracle.truffle.api.instrumentation.Tag;
 import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.RRuntimeASTAccess;
+import com.oracle.truffle.r.runtime.context.RContext;
 
 /**
  * Some additional support for instrumentable nodes.
  */
-public interface RInstrumentableNode {
+public interface RInstrumentableNode extends InstrumentableNode {
 
     /**
      * Unwrap a (potentially) wrapped node, returning the child. Since an AST may contain wrapper
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RNode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RNode.java
index 76d4203238bc32d70b2ea1fa11c66df3a36834e4..d585d0de6206aa59094ed82bbaffe231a7aae8ce 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RNode.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, 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
@@ -25,17 +25,33 @@ package com.oracle.truffle.r.runtime.nodes;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.instrumentation.Instrumentable;
+import com.oracle.truffle.api.instrumentation.ProbeNode;
+import com.oracle.truffle.api.instrumentation.Tag;
 import com.oracle.truffle.api.nodes.UnexpectedResultException;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RTypes;
 import com.oracle.truffle.r.runtime.data.RTypesGen;
-import com.oracle.truffle.r.runtime.nodes.instrumentation.RNodeWrapperFactory;
+import com.oracle.truffle.r.runtime.nodes.instrumentation.RNodeWrapper;
 
 @TypeSystemReference(RTypes.class)
-@Instrumentable(factory = RNodeWrapperFactory.class)
 public abstract class RNode extends RBaseNode implements RInstrumentableNode {
 
+    @Override
+    public boolean isInstrumentable() {
+        return true;
+    }
+
+    @Override
+    public boolean hasTag(Class<? extends Tag> tag) {
+        return RContext.getRRuntimeASTAccess().isTaggedWith(this, tag);
+    }
+
+    @Override
+    public WrapperNode createWrapper(ProbeNode probe) {
+        return new RNodeWrapper(this, probe);
+    }
+
     /**
      * Normal execute function that is called when the return value, but not its visibility is
      * needed.
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/instrumentation/RNodeWrapper.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/instrumentation/RNodeWrapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..f19f9fb1e8ac8b75f5e0576f7aaa846be78670fc
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/instrumentation/RNodeWrapper.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.runtime.nodes.instrumentation;
+
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.instrumentation.InstrumentableNode;
+import com.oracle.truffle.api.instrumentation.ProbeNode;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.nodes.NodeCost;
+import com.oracle.truffle.api.nodes.NodeInfo;
+import com.oracle.truffle.api.source.SourceSection;
+import com.oracle.truffle.r.runtime.nodes.RNode;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
+
+@NodeInfo(cost = NodeCost.NONE)
+public final class RNodeWrapper extends RNode implements InstrumentableNode.WrapperNode {
+    @Child private RNode delegate;
+    @Child private ProbeNode probeNode;
+
+    public RNodeWrapper(RNode delegate, ProbeNode probeNode) {
+        assert delegate != null;
+        assert !(delegate instanceof RNodeWrapper);
+        this.delegate = delegate;
+        this.probeNode = probeNode;
+    }
+
+    @Override
+    public Node getDelegateNode() {
+        return delegate;
+    }
+
+    @Override
+    public ProbeNode getProbeNode() {
+        return probeNode;
+    }
+
+    @Override
+    public Object execute(VirtualFrame frame) {
+        Object returnValue;
+        for (;;) {
+            boolean wasOnReturnExecuted = false;
+            try {
+                probeNode.onEnter(frame);
+                returnValue = delegate.execute(frame);
+                wasOnReturnExecuted = true;
+                probeNode.onReturnValue(frame, returnValue);
+                break;
+            } catch (Throwable t) {
+                Object result = probeNode.onReturnExceptionalOrUnwind(frame, t, wasOnReturnExecuted);
+                if (result == ProbeNode.UNWIND_ACTION_REENTER) {
+                    continue;
+                } else if (result != null) {
+                    returnValue = result;
+                    break;
+                }
+                throw t;
+            }
+        }
+        return returnValue;
+    }
+
+    @Override
+    public void voidExecute(VirtualFrame frame) {
+        for (;;) {
+            boolean wasOnReturnExecuted = false;
+            try {
+                probeNode.onEnter(frame);
+                delegate.voidExecute(frame);
+                wasOnReturnExecuted = true;
+                probeNode.onReturnValue(frame, null);
+                break;
+            } catch (Throwable t) {
+                Object result = probeNode.onReturnExceptionalOrUnwind(frame, t, wasOnReturnExecuted);
+                if (result == ProbeNode.UNWIND_ACTION_REENTER) {
+                    continue;
+                } else if (result != null) {
+                    break;
+                }
+                throw t;
+            }
+        }
+    }
+
+    @Override
+    public Object visibleExecute(VirtualFrame frame) {
+        Object returnValue;
+        for (;;) {
+            boolean wasOnReturnExecuted = false;
+            try {
+                probeNode.onEnter(frame);
+                returnValue = delegate.visibleExecute(frame);
+                wasOnReturnExecuted = true;
+                probeNode.onReturnValue(frame, returnValue);
+                break;
+            } catch (Throwable t) {
+                Object result = probeNode.onReturnExceptionalOrUnwind(frame, t, wasOnReturnExecuted);
+                if (result == ProbeNode.UNWIND_ACTION_REENTER) {
+                    continue;
+                } else if (result != null) {
+                    returnValue = result;
+                    break;
+                }
+                throw t;
+            }
+        }
+        return returnValue;
+    }
+
+    @Override
+    public RSyntaxNode getRSyntaxNode() {
+        return delegate.asRSyntaxNode();
+    }
+
+    @Override
+    public SourceSection getSourceSection() {
+        return delegate.getSourceSection();
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/instrumentation/RNodeWrapperFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/instrumentation/RNodeWrapperFactory.java
deleted file mode 100644
index fcc303d1a5dc57b82b70640a6330428418a5b24c..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/instrumentation/RNodeWrapperFactory.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.runtime.nodes.instrumentation;
-
-import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.instrumentation.InstrumentableFactory;
-import com.oracle.truffle.api.instrumentation.ProbeNode;
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.api.nodes.NodeCost;
-import com.oracle.truffle.api.nodes.NodeInfo;
-import com.oracle.truffle.api.source.SourceSection;
-import com.oracle.truffle.r.runtime.nodes.RNode;
-import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
-
-public final class RNodeWrapperFactory implements InstrumentableFactory<RNode> {
-
-    @NodeInfo(cost = NodeCost.NONE)
-    public static final class RNodeWrapper extends RNode implements InstrumentableFactory.WrapperNode {
-        @Child private RNode delegate;
-        @Child private ProbeNode probeNode;
-
-        public RNodeWrapper(RNode delegate, ProbeNode probeNode) {
-            assert delegate != null;
-            assert !(delegate instanceof RNodeWrapper);
-            this.delegate = delegate;
-            this.probeNode = probeNode;
-        }
-
-        @Override
-        public Node getDelegateNode() {
-            return delegate;
-        }
-
-        @Override
-        public ProbeNode getProbeNode() {
-            return probeNode;
-        }
-
-        @Override
-        public Object execute(VirtualFrame frame) {
-            Object returnValue;
-            for (;;) {
-                boolean wasOnReturnExecuted = false;
-                try {
-                    probeNode.onEnter(frame);
-                    returnValue = delegate.execute(frame);
-                    wasOnReturnExecuted = true;
-                    probeNode.onReturnValue(frame, returnValue);
-                    break;
-                } catch (Throwable t) {
-                    Object result = probeNode.onReturnExceptionalOrUnwind(frame, t, wasOnReturnExecuted);
-                    if (result == ProbeNode.UNWIND_ACTION_REENTER) {
-                        continue;
-                    } else if (result != null) {
-                        returnValue = result;
-                        break;
-                    }
-                    throw t;
-                }
-            }
-            return returnValue;
-        }
-
-        @Override
-        public void voidExecute(VirtualFrame frame) {
-            for (;;) {
-                boolean wasOnReturnExecuted = false;
-                try {
-                    probeNode.onEnter(frame);
-                    delegate.voidExecute(frame);
-                    wasOnReturnExecuted = true;
-                    probeNode.onReturnValue(frame, null);
-                    break;
-                } catch (Throwable t) {
-                    Object result = probeNode.onReturnExceptionalOrUnwind(frame, t, wasOnReturnExecuted);
-                    if (result == ProbeNode.UNWIND_ACTION_REENTER) {
-                        continue;
-                    } else if (result != null) {
-                        break;
-                    }
-                    throw t;
-                }
-            }
-        }
-
-        @Override
-        public Object visibleExecute(VirtualFrame frame) {
-            Object returnValue;
-            for (;;) {
-                boolean wasOnReturnExecuted = false;
-                try {
-                    probeNode.onEnter(frame);
-                    returnValue = delegate.visibleExecute(frame);
-                    wasOnReturnExecuted = true;
-                    probeNode.onReturnValue(frame, returnValue);
-                    break;
-                } catch (Throwable t) {
-                    Object result = probeNode.onReturnExceptionalOrUnwind(frame, t, wasOnReturnExecuted);
-                    if (result == ProbeNode.UNWIND_ACTION_REENTER) {
-                        continue;
-                    } else if (result != null) {
-                        returnValue = result;
-                        break;
-                    }
-                    throw t;
-                }
-            }
-            return returnValue;
-        }
-
-        @Override
-        public RSyntaxNode getRSyntaxNode() {
-            return delegate.asRSyntaxNode();
-        }
-
-        @Override
-        public SourceSection getSourceSection() {
-            return delegate.getSourceSection();
-        }
-    }
-
-    @Override
-    public com.oracle.truffle.api.instrumentation.InstrumentableFactory.WrapperNode createWrapper(RNode node, ProbeNode probe) {
-        return new RNodeWrapper(node, probe);
-    }
-}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
index 1b4bb7f3dbce5b9f8fd9783639ea61f2b818e9ba..1a21c8090a5a601bfb60f3d7df41906514cd2d50 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
@@ -150925,8 +150925,8 @@ NULL
 [1] "field"        "method"       "staticField"  "staticMethod"
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForForeignObject#
-#if (!any(R.version$engine == "FastR")) { c('staticField', 'staticMethod') } else { tc <- new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClass'); sort(names(tc)) }
-[1] "staticField"  "staticMethod"
+#if (!any(R.version$engine == "FastR")) { c(TRUE, TRUE) } else { tc <- new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClass'); c('staticField', 'staticMethod') %in% names(tc) }
+[1] TRUE TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
 #if (!any(R.version$engine == "FastR")) { '[B' } else { a <- new.java.array('byte', 10L); java.class(a); }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java
index 1782f4b2ef57276d7ccc638f17c53ac1acb80cd1..e37ea7538097fd365f84645c4c9845dbbe46919e 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java
@@ -134,7 +134,7 @@ public final class FastRSession implements RSession {
         ChildContextInfo ctx = ChildContextInfo.create(params, env, contextKind, contextKind == ContextKind.SHARE_NOTHING ? null : mainRContext, input, output, output);
         RContext.childInfo = ctx;
 
-        return Context.newBuilder("R").engine(mainEngine).build();
+        return Context.newBuilder("R", "llvm").engine(mainEngine).build();
     }
 
     private FastRSession() {
@@ -154,7 +154,7 @@ public final class FastRSession implements RSession {
             ChildContextInfo info = ChildContextInfo.create(params, null, ContextKind.SHARE_NOTHING, null, input, output, output);
             RContext.childInfo = info;
             mainEngine = Engine.newBuilder().in(input).out(output).err(output).build();
-            mainContext = Context.newBuilder("R").engine(mainEngine).build();
+            mainContext = Context.newBuilder("R", "llvm").engine(mainEngine).build();
             mainRContext = mainContext.eval(GET_CONTEXT).asHostObject();
         } finally {
             try {
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java
index b193df39c62b14f5ae9334ad9b60e32b5e7b2087..d232a891eb95bd3ecd01371eaadc88e6dd457806 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java
@@ -557,7 +557,7 @@ public class TestJavaInterop extends TestBase {
     public void testNamesForForeignObject() {
         assertEvalFastR("tc <- new.java.class('" + TestNamesClassNoMembers.class.getName() + "'); t <- new.external(tc); names(t)", "NULL");
         assertEvalFastR("tc <- new.java.class('" + TestNamesClassNoPublicMembers.class.getName() + "'); t <- new.external(tc); names(t)", "NULL");
-        assertEvalFastR("tc <- new.java.class('" + TestNamesClass.class.getName() + "'); sort(names(tc))", "c('staticField', 'staticMethod')");
+        assertEvalFastR("tc <- new.java.class('" + TestNamesClass.class.getName() + "'); c('staticField', 'staticMethod') %in% names(tc)", "c(TRUE, TRUE)");
         assertEvalFastR("tc <- new.java.class('" + TestNamesClass.class.getName() + "'); names(tc$staticField)", "NULL");
         assertEvalFastR("tc <- new.java.class('" + TestNamesClass.class.getName() + "'); names(tc$staticMethod)", "NULL");
         assertEvalFastR("tc <- new.java.class('" + TestNamesClass.class.getName() + "'); t <- new.external(tc); sort(names(t))", "c('field', 'method', 'staticField', 'staticMethod')");
diff --git a/documentation/dev/truffle_llvm_ffi.md b/documentation/dev/truffle_llvm_ffi.md
index c0cbb908c0ec77477037ff3386533ea9fb05fa80..bff8c9114a7b862b5262873317c8832898a08391 100644
--- a/documentation/dev/truffle_llvm_ffi.md
+++ b/documentation/dev/truffle_llvm_ffi.md
@@ -65,7 +65,7 @@ FastR necessarily provides very fine control over the versions of the llvm tools
 
 The tools needed to build FastR and to install packages containing native code are `clang`, `clang++` and `opt`. Precisely which versions of these tools are used can be controlled in two ways.
 
-1. Set `FASTR_LLVM_HOME` to a directory containing the tools, named as above. N.B. Since MacPorts uses names of the form `clang-mp-3.8` this requires using symbolic links. E.g. create a directory called, say, `llvm-3.8` and symlink to the MacPorts binary, e.g., `clang-mp-3.8` and name it as `clang`. Then set `FASTR_LLVM_HOME` to that directory.
+1. Set `FASTR_LLVM_TOOLS` to a directory containing the tools, named as above. N.B. Since MacPorts uses names of the form `clang-mp-3.8` this requires using symbolic links. E.g. create a directory called, say, `llvm-3.8` and symlink to the MacPorts binary, e.g., `clang-mp-3.8` and name it as `clang`. Then set `FASTR_LLVM_TOOLS` to that directory.
 2. Set `FASTR_LLVM_CLANG`, `FASTR_LLVM_CLANGPP` and `FASTR_LLVM_OPT` to the actual binary images, e.g., `export FASTR_LLVM_CLANG=/opt/local/bin/clang-mp-3.8`.
 
 Not all versions of the llvm tools can compile FastR. `clang-3.2` that is downloaded as part of the DragonEgg build is known to work. This currently is placed in `sulong/cache/tools/llvm/bin` by the DragonEgg build and, again, can be copied to a shared location. `clang-3.8` and `clang-4.0` are known not to work, but `clang-3.9` does.
diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py
index d3b790160193fc0f5e3a94d2849209ec7f9d7f90..e83bac692d6eff3c9784b117838ac20a6aa7e46c 100644
--- a/mx.fastr/suite.py
+++ b/mx.fastr/suite.py
@@ -7,7 +7,7 @@ suite = {
             {
                "name" : "truffle",
                "subdir" : True,
-               "version" : "3e12bec05f7a74f9fbdcd2d2f45f262492fd1306",
+               "version" : "440d89a72cdeb7bc7951e37462cd30bf12fa3ae6",
                "urls" : [
                     {"url" : "https://github.com/graalvm/graal", "kind" : "git"},
                     {"url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind" : "binary"},