diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/WriteTable.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/WriteTable.java
index 84ffe5fcc20ddb387cf6f44230934e55cd765836..2726c549b685d0cfe3e44577b6788188a0b1b555 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/WriteTable.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/WriteTable.java
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1995-2012, The R Core Team
  * Copyright (c) 2003, The R Foundation
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -55,8 +55,8 @@ public final class WriteTable extends RExternalBuiltinNode {
                 // if (i % 1000 == 999)
                 // R_CheckUserInterrupt();
                 if (!(rnames instanceof RNull)) {
-                    os.write(encodeElement2((RStringVector) rnames, i, quoteRn, qmethod, cdec).getBytes());
-                    os.write(csep.getBytes());
+                    tmp = new StringBuffer(encodeElement2((RStringVector) rnames, i, quoteRn, qmethod, cdec)).append(csep).toString();
+                    os.write(tmp.getBytes());
                 }
                 for (int j = 0; j < nc; j++) {
                     Object xjObj = x.getDataAtAsObject(j);
@@ -99,8 +99,7 @@ public final class WriteTable extends RExternalBuiltinNode {
                     // R_CheckUserInterrupt();
                 }
                 if (!(rnames instanceof RNull)) {
-                    os.write(encodeElement2((RStringVector) rnames, i, quoteRn, qmethod, cdec).getBytes());
-                    os.write(csep.getBytes());
+                    os.write(new StringBuffer(encodeElement2((RStringVector) rnames, i, quoteRn, qmethod, cdec)).append(csep).toString().getBytes());
                 }
                 for (int j = 0; j < nc; j++) {
                     if (j > 0) {
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 17b15adcfdc3f4d0c7389466d5daa79af385918e..5359998782965fb15bf383c631e237f268ecc742 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
@@ -386,6 +386,7 @@ public class BasePackage extends RBuiltinPackage {
         add(Matrix.class, MatrixNodeGen::create);
         add(Max.class, MaxNodeGen::create);
         add(Mean.class, MeanNodeGen::create);
+        add(Merge.class, MergeNodeGen::create);
         add(Min.class, MinNodeGen::create);
         add(Missing.class, MissingNodeGen::create);
         add(Mod.class, ModNodeGen::create);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Merge.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Merge.java
new file mode 100644
index 0000000000000000000000000000000000000000..9d355d693691b51999eafe1d64e8c5ad025f156d
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Merge.java
@@ -0,0 +1,207 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 1995, 1996  Robert Gentleman and Ross Ihaka
+ * Copyright (c) 1997-2014,  The R Core Team
+ * Copyright (c) 2016, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+
+package com.oracle.truffle.r.nodes.builtin.base;
+
+import static com.oracle.truffle.r.runtime.RBuiltinKind.*;
+
+import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.builtin.*;
+import com.oracle.truffle.r.runtime.*;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RIntVector;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
+
+@RBuiltin(name = "merge", kind = INTERNAL, parameterNames = {"xinds", "xinds", "all.x", "all.y"})
+public abstract class Merge extends RBuiltinNode {
+
+    @Override
+    protected void createCasts(CastBuilder casts) {
+        casts.firstLogical(2);
+        casts.firstLogical(3);
+    }
+
+    private static void isortWithIndex(int[] x, int[] indx, int n) {
+        int i;
+        int j;
+        int h;
+        int iv;
+        int v;
+
+        for (h = 1; h <= n / 9; h = 3 * h + 1) {
+        }
+        for (; h > 0; h /= 3) {
+            for (i = h; i < n; i++) {
+                v = x[i];
+                iv = indx[i];
+                j = i;
+                while (j >= h && x[j - h] > v) {
+                    x[j] = x[j - h];
+                    indx[j] = indx[j - h];
+                    j -= h;
+                }
+                x[j] = v;
+                indx[j] = iv;
+            }
+        }
+    }
+
+    @Specialization(guards = {"xIndsAbstract.getLength() > 0", "xIndsAbstract.getLength() > 0", "!isNA(allX)", "!isNA(allY)"})
+    RList merge(RAbstractIntVector xIndsAbstract, RAbstractIntVector yIndsAbstract, byte allX, byte allY) {
+        RIntVector xInds = xIndsAbstract.materialize();
+        RIntVector yInds = yIndsAbstract.materialize();
+
+        /* 0. sort the indices */
+        int nx = xInds.getLength();
+        int ny = yInds.getLength();
+        int[] ix = new int[nx];
+        int[] iy = new int[ny];
+        for (int i = 0; i < nx; i++) {
+            ix[i] = i + 1;
+        }
+        for (int i = 0; i < ny; i++) {
+            iy[i] = i + 1;
+        }
+        int[] xIndsData = xInds.getDataWithoutCopying();
+        int[] yIndsData = yInds.getDataWithoutCopying();
+        isortWithIndex(xIndsData, ix, nx);
+        isortWithIndex(yIndsData, iy, ny);
+
+        /* 1. determine result sizes */
+        int nxLone = 0;
+        int nyLone = 0;
+        int l;
+        for (l = 0; l < nx; l++) {
+            if (xIndsData[l] > 0) {
+                break;
+            }
+        }
+        nxLone = l;
+
+        for (l = 0; l < ny; l++) {
+            if (yIndsData[l] > 0) {
+                break;
+            }
+        }
+        nyLone = l;
+
+        int nnx;
+        int nny;
+        double dnans = 0;
+        int j = nyLone;
+        for (int i = nxLone; i < nx; i = nnx, j = nny) {
+            int tmp = xIndsData[i];
+            for (nnx = i; nnx < nx; nnx++) {
+                if (xIndsData[nnx] != tmp) {
+                    break;
+                }
+            }
+            // the next is not in theory necessary, since we have the common values only
+            for (; j < ny; j++) {
+                if (yIndsData[j] >= tmp) {
+                    break;
+                }
+            }
+            for (nny = j; nny < ny; nny++) {
+                if (yIndsData[nny] != tmp) {
+                    break;
+                }
+            }
+            dnans += ((double) (nnx - i)) * (nny - j);
+        }
+        if (dnans > RRuntime.INT_MAX_VALUE) {
+            throw RError.error(this, RError.Message.GENERIC, "number of rows in the result exceeds maximum vector length");
+        }
+        int nans = (int) dnans;
+
+        /* 2. allocate and store result components */
+
+        int[] ansXData = new int[nans];
+        int[] ansYData = new int[nans];
+
+        RList ans = RDataFactory.createList(new Object[4], RDataFactory.createStringVector(new String[]{"xi", "yi", "x.alone", "y.alone"}, RDataFactory.COMPLETE_VECTOR));
+        ans.updateDataAt(0, RDataFactory.createIntVector(ansXData, RDataFactory.COMPLETE_VECTOR), null);
+        ans.updateDataAt(1, RDataFactory.createIntVector(ansYData, RDataFactory.COMPLETE_VECTOR), null);
+
+        if (allX == RRuntime.LOGICAL_TRUE) {
+            int[] xLoneData = new int[nxLone];
+            ans.updateDataAt(2, RDataFactory.createIntVector(xLoneData, RDataFactory.COMPLETE_VECTOR), null);
+            for (int i = 0, ll = 0; i < nxLone; i++) {
+                xLoneData[ll++] = ix[i];
+            }
+        } else {
+            ans.updateDataAt(2, RNull.instance, null);
+        }
+
+        if (allY == RRuntime.LOGICAL_TRUE) {
+            int[] yLoneData = new int[nyLone];
+            ans.updateDataAt(3, RDataFactory.createIntVector(yLoneData, RDataFactory.COMPLETE_VECTOR), null);
+            for (int i = 0, ll = 0; i < nyLone; i++) {
+                yLoneData[ll++] = iy[i];
+            }
+        } else {
+            ans.updateDataAt(3, RNull.instance, null);
+        }
+
+        j = nyLone;
+        for (int i = nxLone, k = 0; i < nx; i = nnx, j = nny) {
+            int tmp = xIndsData[i];
+            for (nnx = i; nnx < nx; nnx++) {
+                if (xIndsData[nnx] != tmp) {
+                    break;
+                }
+            }
+            for (; j < ny; j++) {
+                if (yIndsData[j] >= tmp) {
+                    break;
+                }
+            }
+            for (nny = j; nny < ny; nny++) {
+                if (yIndsData[nny] != tmp) {
+                    break;
+                }
+            }
+            for (int i0 = i; i0 < nnx; i0++) {
+                for (int j0 = j; j0 < nny; j0++) {
+                    ansXData[k] = ix[i0];
+                    ansYData[k++] = iy[j0];
+                }
+            }
+        }
+
+        return ans;
+    }
+
+    @Fallback
+    Object merge(Object xInds, Object yInds, byte allX, byte allY) {
+        if (!(xInds instanceof Integer || (xInds instanceof RAbstractIntVector && ((RAbstractIntVector) xInds).getLength() > 0))) {
+            throw RError.error(this, RError.Message.INVALID_ARGUMENT, "xinds");
+        }
+        if (!(yInds instanceof Integer || (yInds instanceof RAbstractIntVector && ((RAbstractIntVector) yInds).getLength() > 0))) {
+            throw RError.error(this, RError.Message.INVALID_ARGUMENT, "yinds");
+        }
+        if (RRuntime.isNA(allX)) {
+            throw RError.error(this, RError.Message.INVALID_LOGICAL, "all.x");
+        } else {
+            assert RRuntime.isNA(allY);
+            throw RError.error(this, RError.Message.INVALID_LOGICAL, "all.y");
+        }
+    }
+
+    protected boolean isNA(byte v) {
+        return RRuntime.isNA(v);
+    }
+
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/R/dataframe_overrides.R b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/R/dataframe_overrides.R
new file mode 100644
index 0000000000000000000000000000000000000000..2d61513b5326ac326cbce80dd9e4cfdd02fad0f9
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/R/dataframe_overrides.R
@@ -0,0 +1,30 @@
+#  File src/library/base/R/dataframe.R
+#  Part of the R package, http://www.R-project.org
+#
+#  This program is free software; you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 2 of the License, or
+#  (at your option) any later version.
+#
+#  This program 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 for more details.
+#
+#  A copy of the GNU General Public License is available at
+#  http://www.r-project.org/Licenses/
+
+# Statlib code by John Chambers, Bell Labs, 1994
+# Changes Copyright (C) 1998-2014 The R Core Team
+
+Summary.data.frame <- function(..., na.rm=FALSE)
+{
+    args <- list(...)
+    args <- lapply(args, function(x) {
+        x <- as.matrix(x)
+        if(!is.numeric(x) && !is.complex(x))
+            stop("only defined on a data frame with all numeric variables")
+        x
+    })
+    do.call(.Generic, c(args, na.rm=na.rm))
+}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
index 0552aae1eddb1698a31caa2a4d944ed3fe644df2..9bba39c01141c6ca557b7a70575e8a30aa051409 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
@@ -28,6 +28,7 @@ import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNodeGen;
 import com.oracle.truffle.r.nodes.unary.CastDoubleNodeGen;
 import com.oracle.truffle.r.nodes.unary.CastIntegerNodeGen;
 import com.oracle.truffle.r.nodes.unary.CastLogicalNodeGen;
+import com.oracle.truffle.r.nodes.unary.CastLogicalScalarNodeGen;
 import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.nodes.unary.CastStringNodeGen;
 import com.oracle.truffle.r.nodes.unary.CastToAttributableNodeGen;
@@ -138,4 +139,8 @@ public final class CastBuilder {
     public CastBuilder firstBoolean(int index, String invalidValueName) {
         return insert(index, FirstBooleanNodeGen.create(invalidValueName));
     }
+
+    public CastBuilder firstLogical(int index) {
+        return insert(index, CastLogicalScalarNodeGen.create());
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RChannel.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RChannel.java
index eaa5032f66c79be6d05536d7fdc4c1ace15f6697..889acb913da6e584d9e8e2b2e5d6a4d5022fbe35 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RChannel.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RChannel.java
@@ -301,10 +301,6 @@ public class RChannel {
             msg = RSerialize.serialize(msg, RSerialize.XDR, RSerialize.DEFAULT_VERSION, null);
         }
         try {
-            int i = 0;
-            if (msg == null) {
-                i++;
-            }
             (id > 0 ? channel.masterToClient : channel.clientToMaster).put(msg);
         } catch (InterruptedException x) {
             throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, "error sending through the channel");
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
index e1943b9a83597322952fa4283865258665a25de1..8b7bdcb9eedb56de15f249194319d822fa93cd50 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java
@@ -175,7 +175,7 @@ public class TextConnections {
 
         @Override
         public OutputStream getOutputStream() throws IOException {
-            throw RInternalError.shouldNotReachHere();
+            return new ConnectionOutputStream();
         }
 
         @Override
@@ -197,13 +197,24 @@ public class TextConnections {
         private void writeStringInternal(String result) {
             int nlIndex;
             int px = 0;
+            boolean endOfLine = false;
             ArrayList<String> appendedLines = new ArrayList<>();
             while ((nlIndex = result.indexOf('\n', px)) >= 0) {
-                appendedLines.add(result.substring(px, nlIndex));
+                if (incompleteLine != null) {
+                    appendedLines.add(new StringBuffer(incompleteLine).append(result.substring(px, nlIndex)).toString());
+                    incompleteLine = null;
+                } else {
+                    appendedLines.add(result.substring(px, nlIndex));
+                }
                 nlIndex++;
                 px = nlIndex;
+                endOfLine = true;
             }
-            if (px < result.length()) {
+            if (incompleteLine != null && !endOfLine) {
+                // end of line not found - accumulate incomplete line
+                incompleteLine = new StringBuffer(incompleteLine).append(result).toString();
+            } else if (px < result.length()) {
+                // only reset incompleteLine if
                 incompleteLine = result.substring(px);
             }
             if (appendedLines.size() > 0) {
@@ -270,6 +281,33 @@ public class TextConnections {
             throw RError.nyi(null, "textConnectionValue");
         }
 
+        private class ConnectionOutputStream extends OutputStream {
+
+            @Override
+            public void close() {
+            }
+
+            @Override
+            public void flush() {
+            }
+
+            @Override
+            public void write(byte[] b) throws IOException {
+                writeStringInternal(new String(b));
+            }
+
+            @Override
+            public void write(byte[] b, int off, int len) {
+                throw RInternalError.unimplemented();
+            }
+
+            @Override
+            public void write(int b) {
+                throw RInternalError.unimplemented();
+            }
+
+        }
+
     }
 
     /**
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 92d281efc19dd0d04714b517db0de4918dd2ca62..b9120f640b5db14025dce7e3f3a809db1c5aba13 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
@@ -2157,6 +2157,10 @@ In any(1) : coercing argument of type 'double' to logical
 #{ any(logical(0)) }
 [1] FALSE
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_any.testAny
+#{ d<-data.frame(c(1L,2L), c(10L, 20L)); any(d) }
+[1] TRUE
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_any.testany1
 #argv <- list(structure(c(TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE), .Tsp = c(1, 101, 1), class = 'ts'));any(argv[[1]]);
 [1] TRUE
@@ -52294,6 +52298,11 @@ character(0)
 ##com.oracle.truffle.r.test.library.base.TestConnections.testWriteConnection
 #{ con <- textConnection("tcval", open="w"); writeLines("a\nb", con); tcval; close(con) }
 
+##com.oracle.truffle.r.test.library.base.TestConnections.testWriteConnection
+#{ d<-data.frame(c(1,2), c(10, 20)); buf<-character(); c<-textConnection("buf", open="w", local=T); write.table(d, c); buf }
+[1] "\"c.1..2.\" \"c.10..20.\"" "\"1\" 1 10"
+[3] "\"2\" 2 20"
+
 ##com.oracle.truffle.r.test.library.base.TestConnections.testWriteTextReadConnection
 #{ writeChar("x", textConnection("abc")) }
 Error in writeChar("x", textConnection("abc")) :
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_any.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_any.java
index f2d23109a8c1e718acad538db5050ffc16ea7dcd..fae415953bc273e4c2b97f578404f15e2400dcc2 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_any.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_any.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -122,5 +122,7 @@ public class TestBuiltin_any extends TestBase {
         assertEval(Ignored.Unknown, Output.ContainsWarning, "{ any(1) }");
         // FIXME coercion warning missing
         assertEval(Ignored.Unknown, Output.ContainsWarning, "{ any(0) }");
+
+        assertEval("{ d<-data.frame(c(1L,2L), c(10L, 20L)); any(d) }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_merge.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_merge.java
index db2a3fca6154e22ff9bbde9551f486bc78652a42..6a0b944e7480da437ce65aec33f246274e60d496 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_merge.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_merge.java
@@ -19,24 +19,23 @@ public class TestBuiltin_merge extends TestBase {
 
     @Test
     public void testmerge1() {
-        assertEval(Ignored.Unknown, "argv <- list(c(0L, 0L, 0L, 0L, 0L), 0L, FALSE, TRUE); .Internal(merge(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))");
+        assertEval("argv <- list(c(0L, 0L, 0L, 0L, 0L), 0L, FALSE, TRUE); .Internal(merge(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))");
     }
 
     @Test
     public void testmerge2() {
-        assertEval(Ignored.Unknown, "argv <- list(c(0L, 0L, 0L, 0L, 0L), 0L, TRUE, FALSE); .Internal(merge(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))");
+        assertEval("argv <- list(c(0L, 0L, 0L, 0L, 0L), 0L, TRUE, FALSE); .Internal(merge(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))");
     }
 
     @Test
     public void testmerge3() {
-        assertEval(Ignored.Unknown, "argv <- list(c(0L, 0L, 0L, 3L, 4L), c(0L, 0L, 0L, 3L, 4L), FALSE, FALSE); .Internal(merge(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))");
+        assertEval("argv <- list(c(0L, 0L, 0L, 3L, 4L), c(0L, 0L, 0L, 3L, 4L), FALSE, FALSE); .Internal(merge(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))");
     }
 
     @Test
     public void testmerge5() {
-        assertEval(Ignored.Unknown,
-                        "argv <- structure(list(x = structure(list(gender = structure(c(1L,     1L, 2L), .Label = c('F', 'M'), class = 'factor'), age = c(20,     30, 40), filename = structure(1:3, .Label = c('q1.csv', 'q2.csv',     'q3.csv'), class = 'factor')), .Names = c('gender', 'age',     'filename'), row.names = c(NA, -3L), class = 'data.frame'),     y = structure(list(effsize = c(3.5, 2, 1.7), constraint = c(0.40625,         0.5, 0.882), outdegree = c(4, 2, 2), indegree = c(4,         2, 3), efficiency = c(0.625, 0.5, 0.444444444444444),         hierarchy = c(0, 0, 0.333333333333333), centralization = c(0.833333333333333,             1, 0.333333333333333), gden = c(0.5, 0.666666666666667,             0.666666666666667), ego.gden = c(0.166666666666667,             0, 0.5), filename = structure(1:3, .Label = c('q1.csv',             'q2.csv', 'q3.csv'), class = 'factor')), .Names = c('effsize',         'constraint', 'outdegree', 'indegree', 'efficiency',         'hierarchy', 'centralization', 'gden', 'ego.gden', 'filename'),         row.names = c('q1.csv', 'q2.csv', 'q3.csv'), class = 'data.frame'),     by = 'filename'), .Names = c('x', 'y', 'by'));"
-                                        + "do.call('merge', argv)");
+        assertEval("argv <- structure(list(x = structure(list(gender = structure(c(1L,     1L, 2L), .Label = c('F', 'M'), class = 'factor'), age = c(20,     30, 40), filename = structure(1:3, .Label = c('q1.csv', 'q2.csv',     'q3.csv'), class = 'factor')), .Names = c('gender', 'age',     'filename'), row.names = c(NA, -3L), class = 'data.frame'),     y = structure(list(effsize = c(3.5, 2, 1.7), constraint = c(0.40625,         0.5, 0.882), outdegree = c(4, 2, 2), indegree = c(4,         2, 3), efficiency = c(0.625, 0.5, 0.444444444444444),         hierarchy = c(0, 0, 0.333333333333333), centralization = c(0.833333333333333,             1, 0.333333333333333), gden = c(0.5, 0.666666666666667,             0.666666666666667), ego.gden = c(0.166666666666667,             0, 0.5), filename = structure(1:3, .Label = c('q1.csv',             'q2.csv', 'q3.csv'), class = 'factor')), .Names = c('effsize',         'constraint', 'outdegree', 'indegree', 'efficiency',         'hierarchy', 'centralization', 'gden', 'ego.gden', 'filename'),         row.names = c('q1.csv', 'q2.csv', 'q3.csv'), class = 'data.frame'),     by = 'filename'), .Names = c('x', 'y', 'by'));"
+                        + "do.call('merge', argv)");
     }
 
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
index b6060b1c3686c26cd223e442b5bc9f7dc08de51d..5f3f244e1f937c368a9f059e4acabb920467666e 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -123,5 +123,7 @@ public class TestConnections extends TestBase {
         assertEval("{ con <- textConnection(\"tcval\", open=\"w\"); writeLines(\"a\", con); writeLines(c(\"a\", \"b\"), con, sep=\".\"); writeLines(\"\", con); tcval; close(con) }");
         assertEval("{ con <- textConnection(\"tcval\", open=\"w\"); writeLines(\"a\\nb\", con); tcval; close(con) }");
         assertEval(Ignored.Unimplemented, "c <- textConnection('out', 'w'); cat('testtext', file=c); isIncomplete(c); cat('testtext2\\n', file=c); isIncomplete(c); close(c); out");
+
+        assertEval("{ d<-data.frame(c(1,2), c(10, 20)); buf<-character(); c<-textConnection(\"buf\", open=\"w\", local=T); write.table(d, c); buf }");
     }
 }
diff --git a/mx.fastr/copyrights/gnu_r_gentleman_ihaka2.copyright.star.regex b/mx.fastr/copyrights/gnu_r_gentleman_ihaka2.copyright.star.regex
index 550c1688ca9bc53f73ccd5db40e9783020473474..b9e6ad6dfc19ef20fa816c012583acf977580ad2 100644
--- a/mx.fastr/copyrights/gnu_r_gentleman_ihaka2.copyright.star.regex
+++ b/mx.fastr/copyrights/gnu_r_gentleman_ihaka2.copyright.star.regex
@@ -1 +1 @@
-/\*\n \* This material is distributed under the GNU General Public License\n \* Version 2. You may review the terms of this license at\n \* http://www.gnu.org/licenses/gpl-2.0.html\n \*\n \* Copyright \(c\) 1995, 1996  Robert Gentleman and Ross Ihaka\n \* Copyright \(c\) 1997-2013,  The R Core Team\n \* Copyright \(c\) (?:(20[0-9][0-9]), )?(20[0-9][0-9]), Oracle and/or its affiliates\n \*\n \* All rights reserved.\n \*/\n.*
\ No newline at end of file
+/\*\n \* This material is distributed under the GNU General Public License\n \* Version 2. You may review the terms of this license at\n \* http://www.gnu.org/licenses/gpl-2.0.html\n \*\n \* Copyright \(c\) 1995, 1996  Robert Gentleman and Ross Ihaka\n \* Copyright \(c\) (?:[1-2][09][0-9][0-9]-)?[1-2][09][0-9][0-9],  The R Core Team\n \* Copyright \(c\) (?:(20[0-9][0-9]), )?(20[0-9][0-9]), Oracle and/or its affiliates\n \*\n \* All rights reserved.\n \*/\n.*
\ No newline at end of file
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index 56e6ce88a2267273a6764b3935e59fd817c6697d..aadbee6b72989c14985c82195ba287fc58c6273e 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -142,6 +142,7 @@ com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/I
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java,gnu_r.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java,purdue.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java,gnu_r_gentleman_ihaka.copyright
+com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Merge.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java,purdue.copyright
diff --git a/mx.fastr/mx_fastr.py b/mx.fastr/mx_fastr.py
index 10e6195f4105a90a7f7ece4c3af579e241220b5f..04f6961dfccdbb6a40157ba33f34702a89013677 100644
--- a/mx.fastr/mx_fastr.py
+++ b/mx.fastr/mx_fastr.py
@@ -565,7 +565,7 @@ def load_optional_suite(name, rev):
         mx.build_suite(opt_suite)
     return opt_suite
 
-_r_apptests_rev = '804b75871abe803f46af6b2a075cc3f6acfdd6e9'
+_r_apptests_rev = '2f363c204f713520ea1d881af71bac8962a82c72'
 _r_benchmarks_rev = '0b4f36819086323aebce7a2d7bc62949ff90950b'
 
 def mx_post_parse_cmd_line(opts):