diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
index 1e8fa828c18417547e78c25d7639c52e43615738..bfd35372edc84a5a0a6c3e5fd96bdd7cf16a07eb 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
@@ -67,6 +67,7 @@ import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RDeparse;
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntimeASTAccess;
 import com.oracle.truffle.r.runtime.RSrcref;
@@ -84,6 +85,7 @@ import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
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 523b80e3b1e3fd1e07026931e2e2f47a1c1caffa..b88e5f750fc84c9ccc9c4960e8e4f529b261f2ba 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
@@ -635,18 +635,20 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    @TruffleBoundary
     public long Rf_any_duplicated(Object x, int fromLast) {
-        RAbstractVector vec = (RAbstractVector) x;
-        if (vec.getLength() <= 1) {
-            return 0;
-        } else {
-            return DuplicationHelper.analyze(vec, null, true, fromLast != 0).getIndex();
-        }
+        throw implementedAsNode();
+    }
+
+    @Override
+    public long Rf_any_duplicated3(Object x, Object incomparables, int fromLast) {
+        throw implementedAsNode();
     }
 
     @Override
     public Object PRINTNAME(Object x) {
+        if (x == RNull.instance) {
+            return x;
+        }
         guaranteeInstanceOf(x, RSymbol.class);
         return CharSXPWrapper.create(((RSymbol) x).getName());
     }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/RFFIUtils.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/RFFIUtils.java
index e3adbfa00e239f67d21784e95657417e2b438713..b7a447516e4f01e10ebea2f7f0271e49cbdd53a5 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/RFFIUtils.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/RFFIUtils.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
@@ -22,22 +22,25 @@
  */
 package com.oracle.truffle.r.ffi.impl.common;
 
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.nio.file.Path;
 import java.util.List;
 
 import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.r.runtime.FastROptions;
+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.Utils;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RObject;
 import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.ffi.RFFIContext;
+import com.oracle.truffle.r.runtime.ffi.RFFILog;
 
 /**
  * Mostly support for tracing R FFI up/down calls. Currently tracing of the arguments to calls is
@@ -49,58 +52,22 @@ import com.oracle.truffle.r.runtime.ffi.RFFIContext;
  * that launches RStudio.) and sets the cwd to "/", which is not writeable.
  */
 public class RFFIUtils {
-    /**
-     * Set this to {@code true} when it is not possible to set {@link FastROptions}.
-     */
-    private static boolean alwaysTrace;
-    /**
-     * Is set by initialization and caches whether we are tracing.
-     */
-    @CompilationFinal public static boolean traceEnabled;
-
-    public static boolean traceInitialized;
-
-    /**
-     * Always trace to a file because stdout is problematic for embedded mode.
-     */
-    private static final String TRACEFILE = "fastr_trace_nativecalls.log";
-    private static FileOutputStream traceStream;
-
-    /**
-     * Handles the initialization of the RFFI downcalls/upcall tracing implementation.
-     */
-    public static synchronized void initializeTracing() {
-        if (!traceInitialized) {
-            traceInitialized = true;
-            traceEnabled = alwaysTrace || FastROptions.TraceNativeCalls.getBooleanValue();
-            if (traceEnabled) {
-                if (traceStream == null) {
-                    initTraceStream();
-                }
-            }
-        }
-    }
 
-    private static void initTraceStream() {
-        Path tracePath = Utils.getLogPath(TRACEFILE);
-        try {
-            traceStream = new FileOutputStream(tracePath.toString());
-        } catch (IOException ex) {
-            System.err.println(ex.getMessage());
-            System.exit(1);
-        }
-    }
+    private static Node isPointerNode;
+    private static Node asPointerNode;
 
     private enum CallMode {
-        UP("U"),
-        UP_RETURN("UR"),
-        DOWN("D"),
-        DOWN_RETURN("DR");
+        UP("U", true),
+        UP_RETURN("UR", false),
+        DOWN("D", false),
+        DOWN_RETURN("DR", true);
 
         private final String printName;
+        private final boolean logNativeMirror;
 
-        CallMode(String printName) {
+        CallMode(String printName, boolean logNativeMirror) {
             this.printName = printName;
+            this.logNativeMirror = logNativeMirror;
         }
     }
 
@@ -125,11 +92,11 @@ public class RFFIUtils {
     }
 
     public static boolean traceEnabled() {
-        return traceEnabled;
+        return RFFILog.traceEnabled();
     }
 
     private static void traceCall(CallMode mode, String name, int depthValue, Object... args) {
-        if (traceEnabled) {
+        if (traceEnabled()) {
             StringBuilder sb = new StringBuilder();
             sb.append("CallRFFI[");
             sb.append(mode.printName);
@@ -138,21 +105,13 @@ public class RFFIUtils {
             sb.append(']');
             sb.append(name);
             sb.append('(');
-            printArgs(sb, args);
+            printArgs(mode, sb, args);
             sb.append(')');
-            sb.append(" [ctx:").append(System.identityHashCode(RContext.getInstance()));
-            sb.append(",thread:").append(Thread.currentThread().getId()).append(']');
-            try {
-                traceStream.write(sb.toString().getBytes());
-                traceStream.write('\n');
-                traceStream.flush();
-            } catch (IOException ex) {
-                // ignore
-            }
+            RFFILog.write(sb.toString());
         }
     }
 
-    private static void printArgs(StringBuilder sb, Object[] args) {
+    private static void printArgs(CallMode mode, StringBuilder sb, Object[] args) {
         boolean first = true;
         for (Object arg : args) {
             if (first) {
@@ -160,14 +119,38 @@ public class RFFIUtils {
             } else {
                 sb.append(", ");
             }
-            sb.append(arg == null ? "" : arg.getClass().getSimpleName());
-            if (arg instanceof RSymbol) {
-                RSymbol symbol = (RSymbol) arg;
-                sb.append("(\"" + symbol.getName() + "\")");
+            if (arg == null) {
+                sb.append("null");
+                continue;
+            }
+            sb.append(arg.getClass().getSimpleName()).append('(').append(arg.hashCode());
+            if (arg instanceof TruffleObject && ForeignAccess.sendIsPointer(getIsPointerNode(), (TruffleObject) arg)) {
+                try {
+                    sb.append(";ptr:").append(String.valueOf(ForeignAccess.sendAsPointer(getAsPointerNode(), (TruffleObject) arg)));
+                } catch (UnsupportedMessageException e) {
+                    throw RInternalError.shouldNotReachHere();
+                }
+            } else if (arg instanceof RSymbol) {
+                sb.append(';').append("\"" + arg.toString() + "\"");
+            } else if (arg instanceof RAbstractVector) {
+                RAbstractVector vec = (RAbstractVector) arg;
+                if (vec.getLength() == 0) {
+                    sb.append(";empty");
+                } else {
+                    sb.append(";len:" + vec.getLength() + ";data:");
+                    for (int i = 0; i < Math.min(3, vec.getLength()); i++) {
+                        String str = ((RAbstractVector) arg).getDataAtAsObject(0).toString();
+                        str = str.length() > 30 ? str.substring(0, 27) + "..." : str;
+                        sb.append(',').append(str);
+                    }
+                }
             }
-            if (!(arg instanceof RTypedValue)) {
-                sb.append("(" + arg + ")");
+            // Note: it makes sense to include native mirrors only once they have been create
+            // already
+            if (mode.logNativeMirror && arg instanceof RObject) {
+                sb.append(";" + ((RObject) arg).getNativeMirror());
             }
+            sb.append(')');
         }
     }
 
@@ -179,6 +162,10 @@ public class RFFIUtils {
 
     static RuntimeException unimplemented(String message) {
         CompilerDirectives.transferToInterpreter();
+        if (traceEnabled()) {
+            RFFILog.printf("Error: unimplemented %s", message);
+            RFFILog.printStackTrace();
+        }
         throw RInternalError.unimplemented(message);
     }
 
@@ -196,15 +183,44 @@ public class RFFIUtils {
     public static <T> T guaranteeInstanceOf(Object x, Class<T> clazz) {
         if (x == null) {
             CompilerDirectives.transferToInterpreter();
+            if (traceEnabled()) {
+                RFFILog.printf("Error: unexpected type: null instead of " + clazz.getSimpleName());
+                RFFILog.printStackTrace();
+            }
             unimplemented("unexpected type: null instead of " + clazz.getSimpleName());
         } else if (!clazz.isInstance(x)) {
             CompilerDirectives.transferToInterpreter();
+            if (traceEnabled()) {
+                RFFILog.printf("Error: unexpected type: %s is %s instead of %s", x, x.getClass().getSimpleName(), clazz.getSimpleName());
+                RFFILog.printStackTrace();
+            }
             unimplemented("unexpected type: " + x + " is " + x.getClass().getSimpleName() + " instead of " + clazz.getSimpleName());
         }
         return clazz.cast(x);
     }
 
+    public static void logException(Throwable ex) {
+        if (traceEnabled()) {
+            RFFILog.printf("Error: %s, Message: %s", ex.getClass().getSimpleName(), ex.getMessage());
+            RFFILog.printStackTrace();
+        }
+    }
+
     private static RFFIContext getContext() {
         return RContext.getInstance().getRFFI();
     }
+
+    private static Node getIsPointerNode() {
+        if (isPointerNode == null) {
+            isPointerNode = Message.IS_POINTER.createNode();
+        }
+        return isPointerNode;
+    }
+
+    private static Node getAsPointerNode() {
+        if (asPointerNode == null) {
+            asPointerNode = Message.AS_POINTER.createNode();
+        }
+        return asPointerNode;
+    }
 }
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 27448accd62d39405390e1353a3fe5ea079a1d5f..0ee3d5ff4c0e359055f2cf25f3a87d09b82f046e 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
@@ -53,12 +53,13 @@ import com.oracle.truffle.r.runtime.ffi.CallRFFI;
 import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
 import com.oracle.truffle.r.runtime.ffi.NativeCallInfo;
 import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
+import com.oracle.truffle.r.runtime.ffi.RFFILog;
 import com.oracle.truffle.r.runtime.ffi.RFFIVariables;
 
 final class TruffleLLVM_Call implements CallRFFI {
 
     TruffleLLVM_Call() {
-        RFFIUtils.initializeTracing();
+        RFFILog.initializeTracing();
     }
 
     static final class ContextStateImpl implements RContext.ContextState {
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Context.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Context.java
index b83771cec9b0c6885632d2bcc28f76b31f7ccfa7..b002c4884753b040aa1f819f1f955610cafbc587 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Context.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Context.java
@@ -61,6 +61,7 @@ import com.oracle.truffle.r.runtime.ffi.NativeFunction;
 import com.oracle.truffle.r.runtime.ffi.PCRERFFI;
 import com.oracle.truffle.r.runtime.ffi.REmbedRFFI;
 import com.oracle.truffle.r.runtime.ffi.RFFIContext;
+import com.oracle.truffle.r.runtime.ffi.RFFILog;
 import com.oracle.truffle.r.runtime.ffi.RFFIVariables;
 import com.oracle.truffle.r.runtime.ffi.StatsRFFI;
 import com.oracle.truffle.r.runtime.ffi.ToolsRFFI;
@@ -286,7 +287,7 @@ final class TruffleNFI_Context extends RFFIContext {
 
     @Override
     public ContextState initialize(RContext context) {
-        RFFIUtils.initializeTracing();
+        RFFILog.initializeTracing();
         initializeLock();
         if (traceEnabled()) {
             traceDownCall("initialize");
@@ -368,13 +369,13 @@ final class TruffleNFI_Context extends RFFIContext {
             UnsafeAdapter.UNSAFE.freeMemory(ptr);
         }
         transientAllocations.clear();
+        RuntimeException lastUpCallEx = getLastUpCallException();
+        setLastUpCallException(null);
         if (hasAccessLock) {
             releaseLock();
         }
-        RuntimeException lastUpCallEx = getLastUpCallException();
         if (lastUpCallEx != null) {
             CompilerDirectives.transferToInterpreter();
-            setLastUpCallException(null);
             throw lastUpCallEx;
         }
     }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/CoerceNodes.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/CoerceNodes.java
index bc51d6d45c3eb4590ec0f85ec40df30d74dd49af..b3007b211c50f7552ebd8bfab8cf3bd583b09458 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/CoerceNodes.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/CoerceNodes.java
@@ -51,6 +51,7 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RShareable;
 import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
@@ -75,7 +76,7 @@ public final class CoerceNodes {
             for (int i = 0; i < v.getLength(); i++) {
                 Object element = v.getDataAtAsObject(i);
                 adjustSharing(v, element);
-                RPairList cur = RDataFactory.createPairList(element, RNull.instance, names != null ? names.getDataAt(i) : RNull.instance, gnurType);
+                RPairList cur = RDataFactory.createPairList(element, RNull.instance, names != null ? RDataFactory.createSymbol(names.getDataAt(i)) : RNull.instance, gnurType);
 
                 if (prev == null) {
                     assert head == null;
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/DuplicateNodes.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/DuplicateNodes.java
index 4eab0d8673373a401ed93d7e7091d7ae122d7e62..ff0dbb981c6475531d933cf9613037766f642b0b 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/DuplicateNodes.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/DuplicateNodes.java
@@ -23,14 +23,21 @@
 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.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.ffi.impl.nodes.DuplicateNodesFactory.DuplicateNodeGen;
+import com.oracle.truffle.r.ffi.impl.nodes.DuplicateNodesFactory.RfAnyDuplicated3NodeGen;
+import com.oracle.truffle.r.ffi.impl.nodes.DuplicateNodesFactory.RfAnyDuplicatedNodeGen;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RSequence;
 import com.oracle.truffle.r.runtime.data.RShareable;
 import com.oracle.truffle.r.runtime.data.RSymbol;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.nodes.DuplicationHelper;
 
 public final class DuplicateNodes {
 
@@ -58,6 +65,11 @@ public final class DuplicateNodes {
             return val;
         }
 
+        @Fallback
+        public Object doOther(Object x, Object y) {
+            throw unsupportedTypes("Rf_duplicate", x, y);
+        }
+
         protected static boolean isReusableForDuplicate(Object o) {
             return o == RNull.instance || o instanceof REnvironment || o instanceof RSymbol;
         }
@@ -67,4 +79,45 @@ public final class DuplicateNodes {
         }
     }
 
+    public abstract static class RfAnyDuplicated extends FFIUpCallNode.Arg2 {
+        @Specialization
+        public int doDuplicate(RAbstractVector vec, int fromLast,
+                        @Cached("createBinaryProfile()") ConditionProfile isEmptyProfile) {
+            if (isEmptyProfile.profile(vec.getLength() <= 1)) {
+                return 0;
+            } else {
+                return DuplicationHelper.analyze(vec, null, true, fromLast != 0).getIndex();
+            }
+        }
+
+        @Fallback
+        public Object doOthers(Object vec, Object fromLast) {
+            throw unsupportedTypes("Rf_any_duplicated", vec, fromLast);
+        }
+
+        public static RfAnyDuplicated create() {
+            return RfAnyDuplicatedNodeGen.create();
+        }
+    }
+
+    public abstract static class RfAnyDuplicated3 extends FFIUpCallNode.Arg3 {
+        @Specialization
+        public int doDuplicate(RAbstractVector vec, RAbstractVector incomparables, int fromLast,
+                        @Cached("createBinaryProfile()") ConditionProfile isEmptyProfile) {
+            if (isEmptyProfile.profile(vec.getLength() <= 1)) {
+                return 0;
+            } else {
+                return DuplicationHelper.analyze(vec, incomparables, true, fromLast != 0).getIndex();
+            }
+        }
+
+        @Fallback
+        public Object doOthers(Object vec, Object incomparables, Object fromLast) {
+            throw unsupportedTypes("Rf_any_duplicated3", vec, incomparables, fromLast);
+        }
+
+        public static RfAnyDuplicated3 create() {
+            return RfAnyDuplicated3NodeGen.create();
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/FFIUpCallNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/FFIUpCallNode.java
index 5df825b06b78e80c37dfb663f2f3b2c4c311a156..4a86d30d42e81a4811fdde6e7983a6328b67e30b 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/FFIUpCallNode.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/FFIUpCallNode.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
@@ -22,11 +22,26 @@
  */
 package com.oracle.truffle.r.ffi.impl.nodes;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.Utils;
 
 public abstract class FFIUpCallNode extends Node {
     protected abstract int numArgs();
 
+    @TruffleBoundary
+    protected final RError unsupportedTypes(String name, Object... args) {
+        assert args.length > 0;
+        StringBuilder sb = new StringBuilder(args.length * 15);
+        sb.append("wrong argument types provided to Rf_duplicated: ").append(Utils.getTypeName(args[0]));
+        for (int i = 1; i < args.length; i++) {
+            sb.append(',').append(Utils.getTypeName(args[i]));
+        }
+        throw RError.error(RError.NO_CALLER, Message.GENERIC, sb);
+    }
+
     public abstract static class Arg0 extends FFIUpCallNode {
         public abstract Object executeObject();
 
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 a576084b4f92e967c536c75f70d17c849d4f3745..c74c97380988dc47a87c715faa2f94fa57be56f2 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
@@ -34,9 +34,11 @@ 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.DuplicateNodes.RfAnyDuplicated;
+import com.oracle.truffle.r.ffi.impl.nodes.DuplicateNodes.RfAnyDuplicated3;
 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.GetClassDefNode;
 import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodes.CAARNode;
 import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodes.CAD4RNode;
 import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodes.CADDDRNode;
@@ -206,8 +208,12 @@ public interface StdUpCallsRFFI {
     @RFFIUpCallNode(DuplicateNodes.DuplicateNode.class)
     Object Rf_duplicate(Object x, int deep);
 
+    @RFFIUpCallNode(RfAnyDuplicated.class)
     long Rf_any_duplicated(Object x, int fromLast);
 
+    @RFFIUpCallNode(RfAnyDuplicated3.class)
+    long Rf_any_duplicated3(Object x, Object incomparables, int fromLast);
+
     Object PRINTNAME(Object x);
 
     @RFFIUpCallNode(TAG.class)
diff --git a/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/FFIProcessor.java b/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/FFIProcessor.java
index 9934ccd6fa5f9fc8635efa871925625a5a3ee37f..d6948785437e6e3db76afb80f900b81c31973ebd 100644
--- a/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/FFIProcessor.java
+++ b/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/FFIProcessor.java
@@ -300,7 +300,7 @@ public final class FFIProcessor extends AbstractProcessor {
         w.append("                public Object execute(VirtualFrame frame) {\n");
         w.append("                    List<Object> arguments = ForeignAccess.getArguments(frame);\n");
         w.append("                    assert arguments.size() == " + params.size() + " : \"wrong number of arguments passed to " + name + "\";\n");
-        w.append("                    if (RFFIUtils.traceEnabled) {\n");
+        w.append("                    if (RFFIUtils.traceEnabled()) {\n");
         w.append("                        RFFIUtils.traceUpCall(\"" + name + "\", arguments);\n");
         w.append("                    }\n");
         w.append("                    RFFIContext ctx = RContext.getInstance().getStateRFFI();\n");
@@ -328,8 +328,9 @@ public final class FFIProcessor extends AbstractProcessor {
         } else {
             w.append(";\n");
         }
-        w.append("                    } catch (Exception ex) {\n");
+        w.append("                    } catch (Throwable ex) {\n");
         w.append("                        CompilerDirectives.transferToInterpreter();\n");
+        w.append("                        RFFIUtils.logException(ex);\n");
         w.append("                        handleExceptionNode.execute(ex);\n");
         if (returnKind.isPrimitive()) {
             w.append("                        resultRObj = Integer.valueOf(-1);\n");
@@ -339,11 +340,17 @@ public final class FFIProcessor extends AbstractProcessor {
         w.append("                    }\n");
         w.append("                    ctx.afterUpcall(" + canRunGc + ");\n");
         if (returnKind == TypeKind.VOID) {
+            w.append("                    if (RFFIUtils.traceEnabled()) {\n");
+            w.append("                        RFFIUtils.traceUpCallReturn(\"" + name + "\", null);\n");
+            w.append("                    }\n");
             w.append("                    return 0; // void return type\n");
         } else {
             if (!returnKind.isPrimitive() && m.getAnnotationsByType(RFFICpointer.class).length == 0) {
                 w.append("                    ctx.registerReferenceUsedInNative(resultRObj); \n");
             }
+            w.append("                    if (RFFIUtils.traceEnabled()) {\n");
+            w.append("                        RFFIUtils.traceUpCallReturn(\"" + name + "\", resultRObj);\n");
+            w.append("                    }\n");
             w.append("                    return resultRObj;\n");
         }
         w.append("                }\n");
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 1a6bc2c49b7a21559098ea7126a3d1a70ec9c902..e60dcbfe7fe9af0207c983535a0907aca7533757 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
@@ -57,6 +57,7 @@ typedef SEXP (*call_Rf_duplicate)(SEXP x, int v);
 typedef SEXP (*call_Rf_shallow_duplicate)(SEXP x);
 typedef SEXP (*call_Rf_coerceVector)(SEXP x, SEXPTYPE mode);
 typedef R_xlen_t (*call_Rf_any_duplicated)(SEXP x, Rboolean from_last);
+typedef R_xlen_t (*call_Rf_any_duplicated3)(SEXP x, SEXP y, Rboolean from_last);
 typedef SEXP (*call_Rf_duplicated)(SEXP x, Rboolean y);
 typedef SEXP (*call_Rf_applyClosure)(SEXP x, SEXP y, SEXP z, SEXP a, SEXP b);
 typedef int (*call_Rf_copyMostAttrib)(SEXP x, SEXP y);
diff --git a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h
index 8c6c12994411ddc5c7c0fa7a6e43e5ce5c922238..1dc742abd6f75f1fc437844b34bf8872c4e2dd37 100644
--- a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h
+++ b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h
@@ -104,98 +104,99 @@
 #define Rf_allocMatrix_x 99
 #define Rf_allocVector_x 100
 #define Rf_any_duplicated_x 101
-#define Rf_asChar_x 102
-#define Rf_asCharacterFactor_x 103
-#define Rf_asInteger_x 104
-#define Rf_asLogical_x 105
-#define Rf_asReal_x 106
-#define Rf_classgets_x 107
-#define Rf_coerceVector_x 108
-#define Rf_cons_x 109
-#define Rf_copyListMatrix_x 110
-#define Rf_copyMatrix_x 111
-#define Rf_copyMostAttrib_x 112
-#define Rf_dchisq_x 113
-#define Rf_defineVar_x 114
-#define Rf_dnchisq_x 115
-#define Rf_dunif_x 116
-#define Rf_duplicate_x 117
-#define Rf_error_x 118
-#define Rf_errorcall_x 119
-#define Rf_eval_x 120
-#define Rf_findFun_x 121
-#define Rf_findVar_x 122
-#define Rf_findVarInFrame_x 123
-#define Rf_findVarInFrame3_x 124
-#define Rf_getAttrib_x 125
-#define Rf_gsetVar_x 126
-#define Rf_inherits_x 127
-#define Rf_install_x 128
-#define Rf_installChar_x 129
-#define Rf_isNull_x 130
-#define Rf_isString_x 131
-#define Rf_lengthgets_x 132
-#define Rf_match_x 133
-#define Rf_mkCharLenCE_x 134
-#define Rf_namesgets_x 135
-#define Rf_ncols_x 136
-#define Rf_nrows_x 137
-#define Rf_pchisq_x 138
-#define Rf_pnchisq_x 139
-#define Rf_protect_x 140
-#define Rf_punif_x 141
-#define Rf_qchisq_x 142
-#define Rf_qnchisq_x 143
-#define Rf_qunif_x 144
-#define Rf_rchisq_x 145
-#define Rf_rnchisq_x 146
-#define Rf_runif_x 147
-#define Rf_setAttrib_x 148
-#define Rf_str2type_x 149
-#define Rf_unprotect_x 150
-#define Rf_unprotect_ptr_x 151
-#define Rf_warning_x 152
-#define Rf_warningcall_x 153
-#define Rprintf_x 154
-#define SETCAD4R_x 155
-#define SETCADDDR_x 156
-#define SETCADDR_x 157
-#define SETCADR_x 158
-#define SETCAR_x 159
-#define SETCDR_x 160
-#define SET_BODY_x 161
-#define SET_CLOENV_x 162
-#define SET_FORMALS_x 163
-#define SET_NAMED_FASTR_x 164
-#define SET_RDEBUG_x 165
-#define SET_RSTEP_x 166
-#define SET_S4_OBJECT_x 167
-#define SET_STRING_ELT_x 168
-#define SET_SYMVALUE_x 169
-#define SET_TAG_x 170
-#define SET_TYPEOF_FASTR_x 171
-#define SET_VECTOR_ELT_x 172
-#define STRING_ELT_x 173
-#define SYMVALUE_x 174
-#define TAG_x 175
-#define TYPEOF_x 176
-#define UNSET_S4_OBJECT_x 177
-#define VECTOR_ELT_x 178
-#define forceSymbols_x 179
-#define getCCallable_x 180
-#define getConnectionClassString_x 181
-#define getEmbeddingDLLInfo_x 182
-#define getOpenModeString_x 183
-#define getSummaryDescription_x 184
-#define isSeekable_x 185
-#define octsize_x 186
-#define registerCCallable_x 187
-#define registerRoutines_x 188
-#define restoreHandlerStacks_x 189
-#define setDotSymbolValues_x 190
-#define unif_rand_x 191
-#define useDynamicSymbols_x 192
+#define Rf_any_duplicated3_x 102
+#define Rf_asChar_x 103
+#define Rf_asCharacterFactor_x 104
+#define Rf_asInteger_x 105
+#define Rf_asLogical_x 106
+#define Rf_asReal_x 107
+#define Rf_classgets_x 108
+#define Rf_coerceVector_x 109
+#define Rf_cons_x 110
+#define Rf_copyListMatrix_x 111
+#define Rf_copyMatrix_x 112
+#define Rf_copyMostAttrib_x 113
+#define Rf_dchisq_x 114
+#define Rf_defineVar_x 115
+#define Rf_dnchisq_x 116
+#define Rf_dunif_x 117
+#define Rf_duplicate_x 118
+#define Rf_error_x 119
+#define Rf_errorcall_x 120
+#define Rf_eval_x 121
+#define Rf_findFun_x 122
+#define Rf_findVar_x 123
+#define Rf_findVarInFrame_x 124
+#define Rf_findVarInFrame3_x 125
+#define Rf_getAttrib_x 126
+#define Rf_gsetVar_x 127
+#define Rf_inherits_x 128
+#define Rf_install_x 129
+#define Rf_installChar_x 130
+#define Rf_isNull_x 131
+#define Rf_isString_x 132
+#define Rf_lengthgets_x 133
+#define Rf_match_x 134
+#define Rf_mkCharLenCE_x 135
+#define Rf_namesgets_x 136
+#define Rf_ncols_x 137
+#define Rf_nrows_x 138
+#define Rf_pchisq_x 139
+#define Rf_pnchisq_x 140
+#define Rf_protect_x 141
+#define Rf_punif_x 142
+#define Rf_qchisq_x 143
+#define Rf_qnchisq_x 144
+#define Rf_qunif_x 145
+#define Rf_rchisq_x 146
+#define Rf_rnchisq_x 147
+#define Rf_runif_x 148
+#define Rf_setAttrib_x 149
+#define Rf_str2type_x 150
+#define Rf_unprotect_x 151
+#define Rf_unprotect_ptr_x 152
+#define Rf_warning_x 153
+#define Rf_warningcall_x 154
+#define Rprintf_x 155
+#define SETCAD4R_x 156
+#define SETCADDDR_x 157
+#define SETCADDR_x 158
+#define SETCADR_x 159
+#define SETCAR_x 160
+#define SETCDR_x 161
+#define SET_BODY_x 162
+#define SET_CLOENV_x 163
+#define SET_FORMALS_x 164
+#define SET_NAMED_FASTR_x 165
+#define SET_RDEBUG_x 166
+#define SET_RSTEP_x 167
+#define SET_S4_OBJECT_x 168
+#define SET_STRING_ELT_x 169
+#define SET_SYMVALUE_x 170
+#define SET_TAG_x 171
+#define SET_TYPEOF_FASTR_x 172
+#define SET_VECTOR_ELT_x 173
+#define STRING_ELT_x 174
+#define SYMVALUE_x 175
+#define TAG_x 176
+#define TYPEOF_x 177
+#define UNSET_S4_OBJECT_x 178
+#define VECTOR_ELT_x 179
+#define forceSymbols_x 180
+#define getCCallable_x 181
+#define getConnectionClassString_x 182
+#define getEmbeddingDLLInfo_x 183
+#define getOpenModeString_x 184
+#define getSummaryDescription_x 185
+#define isSeekable_x 186
+#define octsize_x 187
+#define registerCCallable_x 188
+#define registerRoutines_x 189
+#define restoreHandlerStacks_x 190
+#define setDotSymbolValues_x 191
+#define unif_rand_x 192
+#define useDynamicSymbols_x 193
 
-#define UPCALLS_TABLE_SIZE 193
+#define UPCALLS_TABLE_SIZE 194
 
 #endif // RFFI_UPCALLSINDEX_H
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h b/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h
index 82bf7b8f64b6c1c2a002a7b769f31f757865f43d..5edea4d43b092503fe7a9dfaf848b6c120a247ac 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h
@@ -68,6 +68,7 @@
 
 #define UNIMPLEMENTED unimplemented(__FUNCTION__)
 
+#define NO_FASTR_REDEFINE
 #include <rffiutils.h>
 
 // these two functions are here just to handle casting void* to void function pointers...
@@ -448,6 +449,13 @@ R_xlen_t Rf_any_duplicated(SEXP x, Rboolean from_last) {
     return result;
 }
 
+R_xlen_t Rf_any_duplicated3(SEXP x, SEXP incomp, Rboolean from_last) {
+    TRACE0();
+    R_xlen_t result = (R_xlen_t) ((call_Rf_any_duplicated3) callbacks[Rf_any_duplicated3_x])(x, incomp, from_last);
+    checkExitCall();
+    return result;
+}
+
 SEXP Rf_duplicated(SEXP x, Rboolean y) {
     TRACE0();
     unimplemented("Rf_duplicated");
@@ -1245,7 +1253,7 @@ void DUPLICATE_ATTRIB(SEXP to, SEXP from) {
 R_len_t R_BadLongVector(SEXP x, const char *y, int z) {
     TRACE0();
     unimplemented("R_BadLongVector");
-    return (R_len_t) 0;
+    // "no return" function
 }
 
 int IS_S4_OBJECT(SEXP x) {
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_llvm/Rinternals.c b/com.oracle.truffle.r.native/fficall/src/truffle_llvm/Rinternals.c
index 4b3d916edd833c9728fb25cc0f26c8ca8b575202..f6dcf567ef2f622bf0878352af1478402c523c3e 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_llvm/Rinternals.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_llvm/Rinternals.c
@@ -21,6 +21,7 @@
  * questions.
  */
 
+#define NO_FASTR_REDEFINE
 #include <Rinterface.h>
 #include <rffiutils.h>
 #include <Rinternals_common.h>
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rinternals.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rinternals.c
index 39b2d0b9ab6b6ca0cba775cd6826c9cc08494fd5..cf8ea6aa96ee13995af6de6c2c38acf878dc80cd 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rinternals.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rinternals.c
@@ -20,6 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+#define NO_FASTR_REDEFINE
 #include <Rinterface.h>
 #include <rffiutils.h>
 #include <Rinternals_common.h>
diff --git a/com.oracle.truffle.r.native/version.source b/com.oracle.truffle.r.native/version.source
index fb1e7bc86996a80d4a16529b990adda1d3434c92..e1617e842ad9a038ec2d8332c6084300a43cb09d 100644
--- a/com.oracle.truffle.r.native/version.source
+++ b/com.oracle.truffle.r.native/version.source
@@ -1 +1 @@
-54
+57
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
index 17a34fa9a8e7f6e74783757d6f91afa58d25a9f7..601f97464f58dc91e5b9ab586645b47b7795b1ac 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
@@ -72,7 +72,6 @@ import com.oracle.truffle.r.nodes.builtin.base.infix.BreakBuiltinNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.infix.ForBuiltin;
 import com.oracle.truffle.r.nodes.builtin.base.infix.ForBuiltinNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.infix.FunctionBuiltin;
-import com.oracle.truffle.r.nodes.builtin.base.infix.FunctionBuiltinNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.infix.IfBuiltin;
 import com.oracle.truffle.r.nodes.builtin.base.infix.IfBuiltinNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.infix.NextBuiltin;
@@ -798,7 +797,7 @@ public class BasePackage extends RBuiltinPackage {
         add(BraceBuiltin.class, BraceBuiltinNodeGen::create);
         add(BreakBuiltin.class, BreakBuiltinNodeGen::create);
         add(ForBuiltin.class, ForBuiltinNodeGen::create);
-        add(FunctionBuiltin.class, FunctionBuiltinNodeGen::create);
+        add(FunctionBuiltin.class, FunctionBuiltin::create);
         add(IfBuiltin.class, IfBuiltinNodeGen::create);
         add(NextBuiltin.class, NextBuiltinNodeGen::create);
         add(ParenBuiltin.class, ParenBuiltin::new, ParenBuiltin::special);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.java
index da1db2993a9274581f31f7907d66ba41b21d9680..c60c75338c8c594cd5a1a4aab0abf79b5fba1ed9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.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
@@ -33,6 +33,8 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.RASTUtils;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.nodes.builtin.base.infix.FunctionBuiltin;
+import com.oracle.truffle.r.nodes.function.FunctionExpressionNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -79,32 +81,15 @@ public abstract class Call extends RBuiltinNode.Arg2 {
     @TruffleBoundary
     public static RLanguage makeCall(TruffleRLanguage language, RSyntaxNode target, Object[] arguments, ArgumentsSignature signature) {
         assert arguments.length == signature.getLength();
-        if (target instanceof RSyntaxLookup && "function".equals(((RSyntaxLookup) target).getIdentifier())) {
-            return makeFunction(language, arguments);
+        if (target instanceof RSyntaxLookup && "function".equals(((RSyntaxLookup) target).getIdentifier()) && arguments.length == 2) {
+            // this optimization is not strictly necessary, `function` builtin is functional too.
+            FunctionExpressionNode function = FunctionBuiltin.createFunctionExpressionNode(language, arguments[0], arguments[1]);
+            return RDataFactory.createLanguage(Closure.createLanguageClosure(function.asRNode()));
         } else {
             return makeCall0(target, arguments, signature);
         }
     }
 
-    private static RLanguage makeFunction(TruffleRLanguage language, Object[] arguments) {
-        CompilerAsserts.neverPartOfCompilation();
-        Object body = arguments.length <= 1 ? RNull.instance : arguments[1];
-        Object argList = arguments.length == 0 ? RNull.instance : arguments[0];
-        ArrayList<RCodeBuilder.Argument<RSyntaxNode>> finalArgs = new ArrayList<>();
-        while (argList != RNull.instance) {
-            if (!(argList instanceof RPairList)) {
-                throw RError.error(RError.SHOW_CALLER, Message.BAD_FUNCTION_EXPR);
-            }
-            RPairList pl = (RPairList) argList;
-            String name = ((RSymbol) pl.getTag()).getName();
-            RSyntaxNode value = RASTUtils.createNodeForValue(pl.car()).asRSyntaxNode();
-            finalArgs.add(RCodeBuilder.argument(RSyntaxNode.LAZY_DEPARSE, name, value));
-            argList = pl.cdr();
-        }
-        RSyntaxNode function = RContext.getASTBuilder().function(language, RSyntaxNode.LAZY_DEPARSE, finalArgs, RASTUtils.createNodeForValue(body).asRSyntaxNode(), null);
-        return RDataFactory.createLanguage(Closure.createLanguageClosure(function.asRNode()));
-    }
-
     @TruffleBoundary
     private static RLanguage makeCall0(RSyntaxNode target, Object[] arguments, ArgumentsSignature signature) {
         RSyntaxNode[] args = new RSyntaxNode[arguments.length];
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/FunctionBuiltin.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/FunctionBuiltin.java
index 3909ffbb92edc496f1e07f724252dcc77cd3df50..4f885fac2fe13fa5909fa370a48596f4509b096d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/FunctionBuiltin.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/FunctionBuiltin.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
@@ -22,23 +22,78 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base.infix;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
+import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.READS_FRAME;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
+import java.util.ArrayList;
+import java.util.List;
+
+import com.oracle.truffle.api.CompilerAsserts;
+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.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.frame.MaterializedFrame;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.r.nodes.RASTUtils;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.nodes.function.FunctionExpressionNode;
+import com.oracle.truffle.r.nodes.profile.TruffleBoundaryNode;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.TruffleRLanguage;
+import com.oracle.truffle.r.runtime.data.Closure;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RExpression;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RPairList;
+import com.oracle.truffle.r.runtime.data.RPromise;
+import com.oracle.truffle.r.runtime.data.RSymbol;
+import com.oracle.truffle.r.runtime.nodes.RCodeBuilder;
+import com.oracle.truffle.r.runtime.nodes.RCodeBuilder.Argument;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
-@RBuiltin(name = "function", kind = PRIMITIVE, parameterNames = {"x"}, behavior = READS_FRAME)
-public abstract class FunctionBuiltin extends RBuiltinNode.Arg1 {
+@RBuiltin(name = "function", kind = PRIMITIVE, nonEvalArgs = 1, parameterNames = {"args", "body"}, behavior = COMPLEX)
+public final class FunctionBuiltin extends RBuiltinNode.Arg2 {
 
     static {
         Casts.noCasts(FunctionBuiltin.class);
     }
 
-    @Specialization
-    protected Object doIt(@SuppressWarnings("unused") Object x) {
-        throw RInternalError.unimplemented();
+    @Child private CreateAndExecuteFunctionExpr createFunNode;
+
+    @Override
+    public Object execute(VirtualFrame frame, Object args, Object body) {
+        if (createFunNode == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            createFunNode = insert(new CreateAndExecuteFunctionExpr());
+        }
+        return createFunNode.execute(frame.materialize(), getRLanguage(), args, body);
+    }
+
+    public static FunctionBuiltin create() {
+        return new FunctionBuiltin();
+    }
+
+    protected static final class CreateAndExecuteFunctionExpr extends TruffleBoundaryNode {
+        @Child private FunctionExpressionNode funExprNode;
+
+        @TruffleBoundary
+        public Object execute(MaterializedFrame frame, TruffleRLanguage language, Object args, Object body) {
+            funExprNode = insert(createFunctionExpressionNode(getRLanguage(), args, body));
+            return funExprNode.execute(frame);
+        }
+    }
+
+    public static FunctionExpressionNode createFunctionExpressionNode(TruffleRLanguage language, Object args, Object body) {
+        List<Argument<RSyntaxNode>> finalArgs = RContext.getASTBuilder().getFunctionExprArgs(args);
+        return (FunctionExpressionNode) RContext.getASTBuilder().function(language, RSyntaxNode.LAZY_DEPARSE, finalArgs, RASTUtils.createNodeForValue(body).asRSyntaxNode(), null);
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java
index f970469231a641cd2190c2595ec57870aded683d..b682b1268a7c728e81af732e330ffea1e96c43bc 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java
@@ -22,8 +22,10 @@
  */
 package com.oracle.truffle.r.nodes;
 
+import java.util.ArrayList;
 import java.util.List;
 
+import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.RootCallTarget;
 import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.frame.FrameDescriptor;
@@ -53,12 +55,17 @@ import com.oracle.truffle.r.nodes.function.signature.MissingNode;
 import com.oracle.truffle.r.nodes.function.signature.QuoteNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.FastROptions;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.builtins.FastPathFactory;
 import com.oracle.truffle.r.runtime.context.TruffleRLanguage;
 import com.oracle.truffle.r.runtime.data.REmpty;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RShareable;
+import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.nodes.EvaluatedArgumentsVisitor;
 import com.oracle.truffle.r.runtime.nodes.RCodeBuilder;
@@ -190,6 +197,27 @@ public final class RASTBuilder implements RCodeBuilder<RSyntaxNode> {
         return FunctionExpressionNode.create(source, callTarget);
     }
 
+    @Override
+    public ArrayList<Argument<RSyntaxNode>> getFunctionExprArgs(Object args) {
+        CompilerAsserts.neverPartOfCompilation();
+        if (!(args instanceof RPairList || args == RNull.instance)) {
+            throw RError.error(RError.SHOW_CALLER, Message.INVALID_FORMAL_ARG_LIST, "function");
+        }
+        ArrayList<Argument<RSyntaxNode>> finalArgs = new ArrayList<>();
+        Object argList = args;
+        while (argList != RNull.instance) {
+            if (!(argList instanceof RPairList)) {
+                throw RError.error(RError.SHOW_CALLER, Message.INVALID_FORMAL_ARG_LIST, "function");
+            }
+            RPairList pl = (RPairList) argList;
+            String name = ((RSymbol) pl.getTag()).getName();
+            RSyntaxNode value = RASTUtils.createNodeForValue(pl.car()).asRSyntaxNode();
+            finalArgs.add(RCodeBuilder.argument(RSyntaxNode.LAZY_DEPARSE, name, value));
+            argList = pl.cdr();
+        }
+        return finalArgs;
+    }
+
     @Override
     public RootCallTarget rootFunction(TruffleRLanguage language, SourceSection source, List<Argument<RSyntaxNode>> params, RSyntaxNode body, String name) {
         // Parse argument list
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 7bef648d8b4e38b0ad54d4f1de55b92c1c9b929b..0b5398bfaacc456437a3fac92200f5b5920f1502 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
@@ -28,6 +28,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.List;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.interop.TruffleObject;
@@ -35,6 +36,7 @@ import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.SourceSection;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RAttributesLayout;
@@ -67,6 +69,8 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
 import com.oracle.truffle.r.runtime.interop.TruffleObjectConverter;
+import com.oracle.truffle.r.runtime.nodes.RCodeBuilder;
+import com.oracle.truffle.r.runtime.nodes.RCodeBuilder.Argument;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
@@ -521,6 +525,9 @@ public class RDeparse {
                 RSyntaxElement[] args = call.getSyntaxArguments();
                 if (lhs instanceof RSyntaxLookup) {
                     String symbol = ((RSyntaxLookup) lhs).getIdentifier();
+                    if ("function".equals(symbol)) {
+                        return visitFunctionFunction(args);
+                    }
                     RDeparse.Func func = RDeparse.getFunc(symbol);
                     if (func != null) {
                         PPInfo info = func.info;
@@ -675,10 +682,34 @@ public class RDeparse {
 
             @Override
             protected Void visit(RSyntaxFunction function) {
+                return visitFunctionExpr(function.getSyntaxSignature(), function.getSyntaxArgumentDefaults(), function.getSyntaxBody());
+            }
+
+            private Void visitFunctionExpr(ArgumentsSignature signature, RSyntaxElement[] argsDefaults, RSyntaxElement body) {
                 append("function(");
-                appendArgs(function.getSyntaxSignature(), function.getSyntaxArgumentDefaults(), 0, true);
+                appendArgs(signature, argsDefaults, 0, true);
                 append(") ");
-                appendFunctionBody(function.getSyntaxBody());
+                appendFunctionBody(body);
+                return null;
+            }
+
+            private Void visitFunctionFunction(RSyntaxElement[] args) {
+                if (args.length > 0 && !(args[0] instanceof RSyntaxConstant)) {
+                    throw RError.error(RError.SHOW_CALLER2, Message.BAD_FUNCTION_EXPR);
+                }
+                Object funArgsValue = args.length > 0 ? ((RSyntaxConstant) args[0]).getValue() : RNull.instance;
+                List<Argument<RSyntaxNode>> syntaxArgs = RContext.getASTBuilder().getFunctionExprArgs(funArgsValue);
+                String[] names = new String[syntaxArgs.size()];
+                RSyntaxNode[] values = new RSyntaxNode[syntaxArgs.size()];
+                for (int i = 0; i < syntaxArgs.size(); i++) {
+                    names[i] = syntaxArgs.get(i).name;
+                    values[i] = syntaxArgs.get(i).value;
+                }
+                Object body = args.length <= 1 ? RNull.instance : args[1];
+                if (!(body instanceof RSyntaxElement)) {
+                    body = RContext.getASTBuilder().constant(RSyntaxNode.SOURCE_UNAVAILABLE, body);
+                }
+                visitFunctionExpr(ArgumentsSignature.get(names), values, (RSyntaxElement) body);
                 return null;
             }
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
index a0282f634ed69c6694626fa30b24124e1f69c376..9c04e55fe45ece31a5d914e6c135a75f40f65b4d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java
@@ -944,6 +944,7 @@ public final class RError extends RuntimeException implements TruffleException {
         VERSION_N_NOT_SUPPORTED("version %d not supported"),
         ATOMIC_VECTOR_ARGUMENTS_ONLY("atomic vector arguments only"),
         MUST_BE_COMPLEX_MATRIX("'%s' must be a complex matrix"),
+        INVALID_FORMAL_ARG_LIST("invalid formal argument list for \"%s\""),
         SINGULAR_BACKSOLVE("singular matrix in 'backsolve'. First zero in diagonal [%d]");
 
         public final String message;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java
index 9f542e9f7a5d049ba41de0dc0aee624b31949749..aad7079a8101d62d73865029366576cf63a7a6ac 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java
@@ -37,6 +37,7 @@ import java.util.function.Function;
 
 import com.oracle.truffle.api.CallTarget;
 import com.oracle.truffle.api.CompilerAsserts;
+import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.TruffleRuntime;
@@ -57,6 +58,7 @@ import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor.MultiSlotData;
 import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
@@ -678,6 +680,21 @@ public final class Utils {
         return String.format(format, objects);
     }
 
+    /**
+     * Makes the best effort to create end user understandable String representation of the type of
+     * the parameter. When the parameter is null, returns "null".
+     */
+    public static String getTypeName(Object value) {
+        // Typically part of error reporting. The whole error reporting should be behind TB.
+        CompilerAsserts.neverPartOfCompilation();
+        if (value == null) {
+            return "null";
+        } else if (value instanceof RTypedValue) {
+            return ((RTypedValue) value).getRType().getName();
+        }
+        return value.getClass().getSimpleName();
+    }
+
     private static boolean isWriteableDirectory(String path) {
         File f = new File(path);
         return f.exists() && f.isDirectory() && f.canWrite();
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 09b82c05c43a5a1e6f9dbf57cceae1b0c579f59b..7bddf458f755527ef10cc2b606b752dd732bdae9 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
@@ -42,6 +42,7 @@ import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.ffi.RFFILog;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 import sun.misc.Unsafe;
@@ -125,7 +126,7 @@ public final class NativeDataAccess {
         private Object nativeWrapper;
 
         NativeMirror() {
-            this.id = counter.incrementAndGet();
+            this.id = counter.addAndGet(2);
         }
 
         /**
@@ -179,9 +180,16 @@ public final class NativeDataAccess {
                 assert (dataAddress = 0xbadbad) != 0;
             }
         }
+
+        @Override
+        public String toString() {
+            return "mirror:" + dataAddress;
+        }
     }
 
-    private static final AtomicLong counter = new AtomicLong(0xdef000000000000L);
+    // The counter is initialized to invalid address and incremented by 2 to always get invalid
+    // address value
+    private static final AtomicLong counter = new AtomicLong(0xdef000000000001L);
     private static final ConcurrentHashMap<Long, WeakReference<RObject>> nativeMirrors = new ConcurrentHashMap<>();
     private static final ConcurrentHashMap<Long, RuntimeException> nativeMirrorInfo = new ConcurrentHashMap<>();
 
@@ -235,6 +243,9 @@ public final class NativeDataAccess {
         if (TRACE_MIRROR_ALLOCATION_SITES) {
             registerAllocationSite(arg, newMirror);
         }
+        if (RFFILog.traceEnabled()) {
+            RFFILog.printf("NativeMirror:" + newMirror.id + "->" + obj.getClass().getSimpleName() + ',' + obj.hashCode());
+        }
         return newMirror;
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RArgsValuesAndNames.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RArgsValuesAndNames.java
index fee0ee0e9f4f3d1ec84ad3b192ca03f0bdf94f8d..f0182160856b72173b12e5dd533ec35f7ad2f186 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RArgsValuesAndNames.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RArgsValuesAndNames.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
@@ -108,7 +108,7 @@ public final class RArgsValuesAndNames extends RObject implements RTypedValue {
         assert signature.getLength() == getLength();
         for (int i = 0; i < getLength(); i++) {
             String name = signature.getName(i);
-            RPairList cur = RDataFactory.createPairList(getArgument(i), RNull.instance, name != null ? name : RNull.instance, SEXPTYPE.DOTSXP);
+            RPairList cur = RDataFactory.createPairList(getArgument(i), RNull.instance, name != null ? RDataFactory.createSymbol(name) : RNull.instance, SEXPTYPE.DOTSXP);
 
             if (head == null) {
                 head = cur;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExternalPtr.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExternalPtr.java
index fa03686af947f9cc3137ef97fbcb97ac4f14b686..5112b663132a02c31723cd5da68c103149ac51bf 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExternalPtr.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExternalPtr.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
@@ -56,6 +56,7 @@ public final class RExternalPtr extends RAttributeStorage implements RTypedValue
     }
 
     public SymbolHandle getAddr() {
+        // TODO: can be null? Callers do dereference the return value.
         return handle;
     }
 
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 8ba6f70a6a9a78a99fd0fcf5609becef434cf1af..b729095f5df82ea0face701e2c98ccf540b0eb45 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
@@ -45,7 +45,13 @@ import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
  * {@code null} is never allowed as a value for the tag, car or cdr, only the type.
  */
 public final class RPairList extends RSharingAttributeStorage implements RAbstractContainer, Iterable<RPairList> {
+    /**
+     * Data of the current pair list cell.
+     */
     private Object car = RNull.instance;
+    /**
+     * Link to the next {@link RPairList} cell or {@link RNull} if last.
+     */
     private Object cdr = RNull.instance;
     /**
      * Externally, i.e., when serialized, this is either a SYMSXP ({@link RSymbol}) or an
@@ -336,9 +342,7 @@ public final class RPairList extends RSharingAttributeStorage implements RAbstra
         int i = 0;
         while (true) {
             data[i] = Utils.toString(pl.tag);
-            if (pl.tag == RRuntime.STRING_NA) {
-                complete = false;
-            }
+            complete &= data[i] != RRuntime.STRING_NA;
             if (isNull(pl.cdr)) {
                 break;
             }
@@ -353,7 +357,7 @@ public final class RPairList extends RSharingAttributeStorage implements RAbstra
         Object p = this;
         for (int i = 0; i < newNames.getLength() && !isNull(p); i++) {
             RPairList pList = (RPairList) p;
-            pList.tag = newNames.getDataAt(i);
+            pList.tag = RDataFactory.createSymbol(newNames.getDataAt(i));
             p = pList.cdr;
         }
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFILog.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFILog.java
new file mode 100644
index 0000000000000000000000000000000000000000..5f736dec33c52d126a9bf8c02000b22fc0846d4d
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFILog.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2018, 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.ffi;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.file.Path;
+
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.r.runtime.FastROptions;
+import com.oracle.truffle.r.runtime.Utils;
+import com.oracle.truffle.r.runtime.context.RContext;
+
+public class RFFILog {
+    /**
+     * Set this to {@code true} when it is not possible to set {@link FastROptions}.
+     */
+    private static boolean alwaysTrace;
+    /**
+     * Is set by initialization and caches whether we are tracing.
+     */
+    @CompilationFinal public static boolean traceEnabled;
+
+    public static boolean traceInitialized;
+
+    /**
+     * Always trace to a file because stdout is problematic for embedded mode.
+     */
+    private static final String TRACEFILE = "fastr_trace_nativecalls.log";
+    private static PrintWriter traceStream;
+
+    /**
+     * Handles the initialization of the RFFI downcalls/upcall tracing implementation.
+     */
+    public static synchronized void initializeTracing() {
+        if (!traceInitialized) {
+            traceInitialized = true;
+            traceEnabled = alwaysTrace || FastROptions.TraceNativeCalls.getBooleanValue();
+            if (traceEnabled) {
+                if (traceStream == null) {
+                    initTraceStream();
+                }
+            }
+        }
+    }
+
+    public static boolean traceEnabled() {
+        return traceEnabled;
+    }
+
+    public static synchronized void write(String value) {
+        assert traceEnabled : "check traceEnabled() before calling RFFILog.write";
+        traceStream.write(value);
+        traceStream.append(" [ctx:").append("" + System.identityHashCode(RContext.getInstance()));
+        traceStream.append(",thread:").append("" + Thread.currentThread().getId()).append(']');
+        traceStream.write('\n');
+        traceStream.flush();
+    }
+
+    public static synchronized void printf(String fmt, Object... args) {
+        assert traceEnabled : "check traceEnabled() before calling RFFILog.printf";
+        traceStream.printf(fmt, args);
+        traceStream.write('\n');
+        traceStream.flush();
+    }
+
+    public static synchronized void printStackTrace() {
+        assert traceEnabled : "check traceEnabled() before calling RFFILog.printStackTrace";
+        new RuntimeException().printStackTrace(traceStream);
+    }
+
+    private static void initTraceStream() {
+        Path tracePath = Utils.getLogPath(TRACEFILE);
+        try {
+            traceStream = new PrintWriter(tracePath.toString());
+        } catch (IOException ex) {
+            System.err.println(ex.getMessage());
+            System.exit(1);
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.java
index 1071ca6c130f8dd37f1e075776b94f0b84a391ef..9d4415f7ab1c90c91c4132c59618c156184b9ade 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.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
@@ -32,6 +32,7 @@ import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.context.TruffleRLanguage;
+import com.oracle.truffle.r.runtime.data.RNull;
 
 /**
  * Implementers of this interface can be used to generate a representation of an R closure.
@@ -120,6 +121,13 @@ public interface RCodeBuilder<T> {
      */
     RootCallTarget rootFunction(TruffleRLanguage language, SourceSection source, List<Argument<T>> arguments, T body, String name);
 
+    /**
+     * Given a {@link com.oracle.truffle.r.runtime.data.RPairList} or {@link RNull}, this method
+     * creates a corresponding list of named arguments with default values if any, like if passed to
+     * the `function` expression.
+     */
+    List<Argument<RSyntaxNode>> getFunctionExprArgs(Object args);
+
     void setContext(CodeBuilderContext context);
 
     CodeBuilderContext getContext();
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 1a21c8090a5a601bfb60f3d7df41906514cd2d50..440ac65414ad32b7126fb05f6e1781f0e148f82b 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
@@ -5917,10 +5917,6 @@ foo()
 #call('function')
 function() NULL
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_ascall.testAsCall#Output.IgnoreWhitespace#
-#call('function', 'a')
-Error: badly formed function expression
-
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_ascall.testAsCall#Output.IgnoreWhitespace#
 #call('function', pairlist(a=1))
 function(a = 1) NULL
@@ -5949,6 +5945,13 @@ pairlist(a = )()
 #e <- substitute(a$b(c)); as.call(lapply(e, function(x) x))
 a$b(c)
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ascall.testAsCall#Output.IgnoreWhitespace#
+#invisible(call('function', 'a'))
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ascall.testAsCall#Output.IgnoreWhitespace#
+#length(call('function', 'a'))
+[1] 2
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_ascall.testAsCall#
 #typeof(as.call(list(substitute(graphics::par))))
 [1] "language"
@@ -28261,6 +28264,21 @@ Error: atomic vector arguments only
 #argv <- structure(list(pv = 0.200965994008331, digits = 3), .Names = c('pv',     'digits'));do.call('format.pval', argv)
 [1] "0.201"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_function.testFunctionFunction#
+#do.call('function', list(as.pairlist(list(x=4)), expression(x + 1)[[1]]))
+function (x = 4)
+x + 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_function.testFunctionFunction#Output.IgnoreErrorContext#
+#eval(call('function', 1, expression(x + 1)[[1]]))
+Error in eval(call("function", 1, expression(x + 1)[[1]])) :
+  invalid formal argument list for "function"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_function.testFunctionFunction#
+#eval(call('function', as.pairlist(list(x=4)), expression(x + 1)[[1]]))
+function (x = 4)
+x + 1
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_g.testg1#Output.IgnoreErrorContext#
 #argv <- list(1);g(argv[[1]]);
 Error in g(argv[[1]]) : could not find function "g"
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascall.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascall.java
index 7b5523963748615dc4b7c21994975f8f3acf90f4..bc6fff85e3d6fb0157283ba3669227307ad25d7d 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascall.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascall.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -68,7 +68,9 @@ public class TestBuiltin_ascall extends TestBase {
         assertEval(Output.IgnoreWhitespace, "e <- expression(function(a) b); as.call(list(e[[1]][[1]]))");
         assertEval("e <- expression(function(a) b); as.call(list(e[[1]][[2]]))");
         assertEval("call('foo')");
-        assertEval(Output.IgnoreWhitespace, "call('function', 'a')");
+        // Note: call('function', 'a') should not cause the exception, it should be the printing
+        assertEval(Output.IgnoreWhitespace, "invisible(call('function', 'a'))");
+        assertEval(Output.IgnoreWhitespace, "length(call('function', 'a'))");
         assertEval(Output.IgnoreWhitespace, "call('function', pairlist(a=1))");
         assertEval(Output.IgnoreWhitespace, "call('function', pairlist(a=1), 3)");
         assertEval(Output.IgnoreWhitespace, "call('function', pairlist(a=1), 5,3)");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_function.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_function.java
new file mode 100644
index 0000000000000000000000000000000000000000..eac9c3629d63f0921183400c3ad3b3ba025206dc
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_function.java
@@ -0,0 +1,37 @@
+/*
+ * 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
+ * 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.test.builtins;
+
+import org.junit.Test;
+
+import com.oracle.truffle.r.test.TestBase;
+
+// Checkstyle: stop line length check
+public class TestBuiltin_function extends TestBase {
+    @Test
+    public void testFunctionFunction() {
+        assertEval(Output.IgnoreErrorContext, "eval(call('function', 1, expression(x + 1)[[1]]))");
+        assertEval("eval(call('function', as.pairlist(list(x=4)), expression(x + 1)[[1]]))");
+        assertEval("do.call('function', list(as.pairlist(list(x=4)), expression(x + 1)[[1]]))");
+    }
+}
diff --git a/mx.fastr/mx_fastr_edinclude.py b/mx.fastr/mx_fastr_edinclude.py
index 0032c54979c0af20778ea657a9375c0eb1fdea47..40d357e92ea0c54e58b544ea598780ae36d2c79a 100644
--- a/mx.fastr/mx_fastr_edinclude.py
+++ b/mx.fastr/mx_fastr_edinclude.py
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2017, 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
@@ -74,6 +74,14 @@ use_internals_end = '''#endif
 
 '''
 
+set_typeof_rewrite = '''#ifdef FASTR
+SEXP SET_TYPEOF_FASTR(SEXP x, int v);
+#ifndef NO_FASTR_REDEFINE
+#define SET_TYPEOF(X,Y) X=SET_TYPEOF_FASTR(X,Y)
+#endif
+#endif
+'''
+
 def ed_r_internals(gnu_dir):
     r_internals_h = join(gnu_dir, 'Rinternals.h')
     with open(r_internals_h) as f:
@@ -105,6 +113,9 @@ def ed_r_internals(gnu_dir):
                     rewrite_var(f, var, line)
                 else:
                     f.write(line)
+            elif 'SET_TYPEOF' in line and '(SEXP' in line:
+                f.write(line)
+                f.write(set_typeof_rewrite)
             else:
                 f.write(line)