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 e1c3ca08e3b0899498abbe29882a93dc486d7462..b200768c1127edf4101bdbf8d53dd8eed8a7b69b 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
@@ -361,6 +361,7 @@ public class BasePackage extends RBuiltinPackage {
         add(DimNames.class, DimNamesNodeGen::create);
         add(DoCall.class, DoCallNodeGen::create);
         add(DPut.class, DPutNodeGen::create);
+        add(Dump.class, DumpNodeGen::create);
         add(Drop.class, DropNodeGen::create);
         add(DuplicatedFunctions.AnyDuplicated.class, DuplicatedFunctionsFactory.AnyDuplicatedNodeGen::create);
         add(DuplicatedFunctions.Duplicated.class, DuplicatedFunctionsFactory.DuplicatedNodeGen::create);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Dump.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Dump.java
new file mode 100644
index 0000000000000000000000000000000000000000..22ef993e33fb83761e59cb3d0bce3e00349cff74
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Dump.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.nodes.builtin.base;
+
+import static com.oracle.truffle.r.runtime.RError.Message.INVALID_ARGUMENT;
+import static com.oracle.truffle.r.runtime.RVisibility.OFF;
+import static com.oracle.truffle.r.runtime.builtins.RBehavior.IO;
+import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
+import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
+import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.nodes.function.PromiseHelperNode;
+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.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.conn.RConnection;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RPromise;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
+
+@RBuiltin(name = "dump", visibility = OFF, kind = INTERNAL, parameterNames = {"list", "file", "envir", "opts", "evaluate"}, behavior = IO)
+public abstract class Dump extends RBuiltinNode.Arg5 {
+
+    @Child protected Helper helper;
+
+    static {
+        Casts casts = new Casts(Dump.class);
+        casts.arg("list").mustNotBeMissing().mustBe(Predef.stringValue()).asStringVector();
+        casts.arg("file").defaultError(Message.INVALID_CONNECTION).mustNotBeNull().asIntegerVector().findFirst();
+        casts.arg("envir").mustNotBeMissing().mustBe(REnvironment.class, INVALID_ARGUMENT, "envir");
+        casts.arg("opts").mustNotBeMissing().asIntegerVector().findFirst();
+        casts.arg("evaluate").mustNotBeMissing().asLogicalVector().findFirst().map(Predef.toBoolean());
+    }
+
+    @Specialization
+    protected Object dump(VirtualFrame frame, RAbstractStringVector x, int file, REnvironment envir, int opts, boolean evaluate) {
+        if (helper == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            helper = insert(new Helper());
+        }
+        int retrieved = 0;
+        String[] retrievedNames = new String[x.getLength()];
+        Object[] objects = new Object[x.getLength()];
+        for (int i = 0; i < x.getLength(); i++) {
+            String name = x.getDataAt(i);
+            objects[i] = helper.getAndCheck(frame, name, envir, evaluate);
+            if (objects[i] != null) {
+                retrievedNames[retrieved++] = name;
+            }
+        }
+        writeToConnection(deparse(x, objects, prepareOpts(opts, evaluate)), file);
+        return RDataFactory.createStringVector(Arrays.copyOfRange(retrievedNames, 0, retrieved), RDataFactory.COMPLETE_VECTOR);
+    }
+
+    @TruffleBoundary
+    private static String deparse(RAbstractStringVector x, Object[] objects, int opts) {
+        assert x.getLength() == objects.length;
+        StringBuilder code = new StringBuilder();
+        for (int i = 0; i < objects.length; i++) {
+            if (objects[i] != null) {
+                if (i != 0) {
+                    code.append(System.lineSeparator());
+                }
+                code.append(x.getDataAt(i)).append(" <-").append(System.lineSeparator()).append(RDeparse.deparse(objects[i], RDeparse.DEFAULT_CUTOFF, true, opts, -1));
+            }
+        }
+        return code.toString();
+    }
+
+    @TruffleBoundary
+    private void writeToConnection(String code, int file) {
+        try (RConnection openConn = RConnection.fromIndex(file).forceOpen("wt")) {
+            openConn.writeString(code, true);
+        } catch (IOException ex) {
+            throw error(RError.Message.GENERIC, ex.getMessage());
+        }
+    }
+
+    private static int prepareOpts(int opts, boolean evaluate) {
+        return evaluate ? opts : opts | RDeparse.DELAYPROMISES;
+    }
+
+    private static final class Helper extends RBaseNode {
+
+        @Child private PromiseHelperNode promiseHelper;
+
+        @CompilationFinal private boolean firstExecution = true;
+
+        protected void unknownObject(String x) {
+            warning(RError.Message.UNKNOWN_OBJECT, x);
+        }
+
+        protected Object checkPromise(VirtualFrame frame, Object r, String identifier) {
+            if (r instanceof RPromise) {
+                if (firstExecution) {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    firstExecution = false;
+                    return ReadVariableNode.evalPromiseSlowPathWithName(identifier, frame, (RPromise) r);
+                }
+                if (promiseHelper == null) {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    promiseHelper = insert(new PromiseHelperNode());
+                }
+                return promiseHelper.evaluate(frame, (RPromise) r);
+            } else {
+                return r;
+            }
+        }
+
+        protected Object getAndCheck(VirtualFrame frame, String x, REnvironment env, boolean evaluatePromise) {
+            Object obj;
+            if (evaluatePromise) {
+                obj = checkPromise(frame, env.get(x), x);
+            } else {
+                obj = env.get(x);
+            }
+            if (obj != null) {
+                return obj;
+            } else {
+                unknownObject(x);
+                return null;
+            }
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GetCallerFrameNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GetCallerFrameNode.java
index bf283b26035874d27723ac6863c20439a148c5bd..fde5609e43395c48c0144a55ba92c565903a6f87 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GetCallerFrameNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GetCallerFrameNode.java
@@ -62,7 +62,7 @@ public final class GetCallerFrameNode extends RBaseNode {
                 return slowPathFrame;
             }
         }
-        assert callerFrameObject == null;
+        assert callerFrameObject instanceof CallerFrameClosure || callerFrameObject == null;
 
         // S3 method can be dispatched from top-level where there is no caller frame
         // Since RArguments does not allow to create arguments with a 'null' caller frame, this
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConvertBooleanNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConvertBooleanNode.java
index 9fc48e238af3b92c8c436b8ac2f1ea8df9ddc596..53cf0b30375ebbfec7da318cd378c4f9e85e53d2 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConvertBooleanNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConvertBooleanNode.java
@@ -24,6 +24,7 @@ package com.oracle.truffle.r.nodes.unary;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.NodeChild;
 import com.oracle.truffle.api.dsl.Specialization;
@@ -183,6 +184,11 @@ public abstract class ConvertBooleanNode extends RNode {
         throw error(RError.Message.ARGUMENT_NOT_INTERPRETABLE_LOGICAL);
     }
 
+    @Fallback
+    protected byte doObject(Object o) {
+        throw error(RError.Message.ARGUMENT_NOT_INTERPRETABLE_LOGICAL);
+    }
+
     public static ConvertBooleanNode create(RSyntaxNode node) {
         if (node instanceof ConvertBooleanNode) {
             return (ConvertBooleanNode) node;
diff --git a/com.oracle.truffle.r.pkgs/refcmp/DESCRIPTION b/com.oracle.truffle.r.pkgs/refcmp/DESCRIPTION
new file mode 100644
index 0000000000000000000000000000000000000000..db08b312ea63a20cd42da20fdf2e94fd446e1d61
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/refcmp/DESCRIPTION
@@ -0,0 +1,12 @@
+Package: refcmp
+Type: Package
+Title: Compare snapshotted variables to a reference run
+Version: 1.0
+Date: 2017-09-07
+Author: Florian Angerer
+Maintainer: Florian Angerer <florian.angerer@oracle.com>
+Copyright: Oracle
+Description: Compare values at defined snapshot to a reference run.
+License: GPL-2
+Depends: 
+RoxygenNote: 6.0.1
diff --git a/com.oracle.truffle.r.pkgs/refcmp/NAMESPACE b/com.oracle.truffle.r.pkgs/refcmp/NAMESPACE
new file mode 100644
index 0000000000000000000000000000000000000000..77c432a5901fda5ccbe5df9d60a6bbb96485adf4
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/refcmp/NAMESPACE
@@ -0,0 +1,6 @@
+# Generated by roxygen2: do not edit by hand
+
+export(snapshot)
+export(snapshot.init)
+export(snapshot.named)
+export(snapshot.show)
diff --git a/com.oracle.truffle.r.pkgs/refcmp/R/refcmp.R b/com.oracle.truffle.r.pkgs/refcmp/R/refcmp.R
new file mode 100644
index 0000000000000000000000000000000000000000..1bea83401725d277bd48791c309be4f9c19b4c69
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/refcmp/R/refcmp.R
@@ -0,0 +1,25 @@
+#' The refcmp packages is supposed to compare intermediate values to a dedicated reference run.
+#'
+#' @name refcmp
+#' @examples
+#' # Loading and setting up
+#' 
+#' library(refcmp)
+#' snapshot.init()
+#' 
+#' # Taking a snapshot of variables or comparing the values to the reference run
+#' a <- 1
+#' b <- 2
+#' snapshot(a, b)
+#' 
+#' # Taking a snapshot of expressions or comparing the values
+#' # We need to name them
+#' snapshot.named(c = 2 +3, d = a + b)
+#' 
+#' # Show the contents of the latest snapshot
+#' snapshot.show()
+#' 
+#' # Show the contents of a snapshot using the ID (a sequence number)
+#' snapshot.show(0)
+#'
+NULL
diff --git a/com.oracle.truffle.r.pkgs/refcmp/R/snapshot.R b/com.oracle.truffle.r.pkgs/refcmp/R/snapshot.R
new file mode 100644
index 0000000000000000000000000000000000000000..11673c4d50489f5e5b2ea6702c87871c22268bc0
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/refcmp/R/snapshot.R
@@ -0,0 +1,200 @@
+##
+ # Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ #
+ # This code is free software; you can redistribute it and/or modify it
+ # under the terms of the GNU General Public License version 2 only, as
+ # published by the Free Software Foundation.
+ #
+ # This code is distributed in the hope that it will be useful, but WITHOUT
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ # FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ # version 2 for more details (a copy is included in the LICENSE file that
+ # accompanied this code).
+ #
+ # You should have received a copy of the GNU General Public License version
+ # 2 along with this work; if not, write to the Free Software Foundation,
+ # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ #
+ # Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ # or visit www.oracle.com if you need additional information or have any
+ # questions.
+##
+
+refcmpEnv <- new.env(parent = emptyenv())
+refcmpEnv$snapshot_dir <- 'snapshots'
+refcmpEnv$snapshot_id <- 0L
+refcmpEnv$equals <- all.equal
+
+snapshot.isFastR <- function() {
+    length(grep('FastR', R.Version()$version.string)) != 0
+}
+
+#' Initialize package
+#'
+#' @param dir The directory where to store snapshot to (default: 'snapshots')
+#' @param is_reference_run A function returning TRUE if snapshots should be taken and FALSE if values should be compared (default: snapshot dir does not exist)
+#' @param equalityFunction The function to use for comparing actual values to snapshotted values (default: 'all.equal')
+#' @examples
+#' # Only comparing using snapshots in directory "my/snapshot/dir" and using function 'identical' to compare values.
+#' snapshot.init(dir = "my/snapshot/dir", referenceRunPredicate = function() FALSE, equalityFunction = identical)
+#' 
+#' # This should do the job in most cases
+#' snapshot.init()
+#' @export
+snapshot.init <- function (dir, is_reference_run, equalityFunction) {
+    if (!missing(dir)) {
+        refcmpEnv$snaphost_dir <- dir
+    }
+    if (!missing(is_reference_run)) {
+        refcmpEnv$is_reference_run <- is_reference_run
+    } else {
+        refcmpEnv$is_reference_run <- !file.exists(refcmpEnv$snapshot_dir)
+    }
+    if (!missing(equalityFunction)) {
+        refcmpEnv$equals <- equalityFunction
+    }
+    refcmpEnv$snapshot_id <- 0L
+}
+
+#' Take a snapshot of some variable's values or compare the values to a previously taken snapshot.
+#' 
+#' This function has two modes, (1) record, and (2) check.
+#' Depending on the result of function 'refcmpEnv$is_reference_run', the mode is (1) if TRUE is returned or (2) otherwise.
+#' 
+#' When in the first mode 'record', function 'snapshot' serializes the values of the specified variables into a file together with the names of the variables. It also increases the ID of the snapshot automatically.
+#' 
+#' When in the second mode 'check', function 'snapshot' deserializes values of a previously taken snapshot and compares the values of the provided variables to the deserialized values by matching names.
+#'
+#' @examples
+#' x <- 10
+#' y <- 20
+#' z <- function() print("hello")
+#' 
+#' snapshot(x, y, z)
+#' @export
+snapshot <- function(...) {
+    # the actual parameter expessions
+    actParExprs <- as.list(match.call()[-1])
+    valueList <- actParsToList(actParExprs, parent.frame())
+    try({
+        snapshot.id(refcmpEnv$snapshot_id, valueList)
+        refcmpEnv$snapshot_id <- refcmpEnv$snapshot_id + 1
+    })
+}
+
+#' Take a snapshot of provided values and name the values as specified in the arguments.
+#' 
+#' This function has two modes, (1) record, and (2) check.
+#' Depending on the result of function 'refcmpEnv$is_reference_run', the mode is (1) if TRUE is returned or (2) otherwise.
+#' 
+#' When in the first mode 'record', function 'snapshot.named' serializes the values of the specified variables into a file together with the names of the variables. It also increases the ID of the snapshot automatically.
+#' 
+#' When in the second mode 'check', function 'snapshot.named' deserializes values of a previously taken snapshot and compares the values of the provided variables to the deserialized values by matching names.
+#' 
+#' I contrast to function 'snapshot', this function does not try to automatically determine the name of a value.
+#' It uses the names as provided in the arguments.
+#'
+#' @examples
+#' snapshot.named(a = 10 + 20, b = 30, c = function() print("hello"))
+#' @export
+snapshot.named <- function (...) {
+    args <- list(...)
+    valueList <- args[names(args) != ""] 
+    try({
+        snapshot.id(refcmpEnv$snapshot_id, valueList)
+        refcmpEnv$snapshot_id <- refcmpEnv$snapshot_id + 1 
+    })  
+}
+
+snapshot.id <- function(id, valueList) {
+    if(refcmpEnv$is_reference_run) {
+        snapshot.record(id, valueList)
+    } else {
+        snapshot.check(id, valueList)
+    }
+}
+
+snapshot.record <- function(id, valueList) {
+    dumpDir <- file.path(refcmpEnv$snapshot_dir)
+    if(!dir.exists(dumpDir)) {
+        dir.create(dumpDir)
+    }
+    fcon <- file(file.path(refcmpEnv$snapshot_dir, paste0("snapshot", id, ".obj")))
+    saveRDS(valueList, file=fcon)
+    close(fcon)
+}
+
+snapshot.check <- function(id, valueList) {
+    fcon <- file(file.path(refcmpEnv$snapshot_dir, paste0("snapshot", id, ".obj")))
+    restoredVars <- readRDS(file=fcon)
+    close(fcon)
+
+    if(length(restoredVars) < length(valueList)) {
+        stop(paste("recorded snapshot has", length(restoredVars), "recorded variables but expected", length(valueList)))
+    }
+
+    var_names <- names(valueList)
+    restored_names <- names(restoredVars)
+    for(i in seq_along(var_names)) {
+        if(var_names[[i]] %in% restored_names) {
+            actualVal <- valueList[[var_names[[i]]]]
+            expectedVal <- restoredVars[[var_names[[i]]]]
+            if(!refcmpEnv$equals(expectedVal, actualVal)) {
+                stop(paste0("Value of variable '", var_names[[i]], "' differs. Expected ", expectedVal, " but was ", actualVal))
+            }
+        } else {
+            stop(paste0("Missing variable '", var_names[[i]], "' in recorded variables"))
+        }
+    }
+}
+
+#' Shows the contents of a snapshot.
+#' 
+#' @param id The ID of the snapshot to show (default: latest)
+#' 
+#' @examples
+#' a <- 1
+#' snapshot(a)
+#' snapshot.show()
+#' 
+#' a <- 2
+#' snapshot(a)
+#' 
+#' a <- 3
+#' snapshot(a)
+#' 
+#' a <- 4
+#' snapshot(a)
+#' snapshot.show(0)
+#' snapshot.show(1)
+#' snapshot.show(2)
+#' snapshot.show(3)
+#' @export
+snapshot.show <- function(id = refcmpEnv$snapshot_id) {
+    snapshot_filename <- file.path(refcmpEnv$snapshot_dir, paste0("snapshot", id, ".obj"))
+    if(!file.exists(snapshot_filename)) {
+        stop(paste0("Snapshot with ID=", id, " does not exist"))
+    }
+    fcon <- file(snapshot_filename)
+    restoredVars <- readRDS(file=fcon)
+    close(fcon)
+
+    return (restoredVars)
+}
+
+actParsToList <- function(pars, env) { 
+    l <- list() 
+    for(i in seq_along(pars)) { 
+        strrep <- as.character(pars[[i]])
+        if (is.symbol(pars[[i]])) {
+            value <- eval(pars[[i]], envir=env)
+            l[[strrep]] <- value
+        } else {
+            warning(paste0("Skipping '", strrep, "' because only symbols are allowed"))
+        }
+    }
+    l
+}
+
+
diff --git a/com.oracle.truffle.r.pkgs/refcmp/man/refcmp.Rd b/com.oracle.truffle.r.pkgs/refcmp/man/refcmp.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..98677ce0b2f04ff25fd34b005684a7bdc90461e5
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/refcmp/man/refcmp.Rd
@@ -0,0 +1,30 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/refcmp.R
+\name{refcmp}
+\alias{refcmp}
+\title{The refcmp packages is supposed to compare intermediate values to a dedicated reference run.}
+\description{
+The refcmp packages is supposed to compare intermediate values to a dedicated reference run.
+}
+\examples{
+# Loading and setting up
+
+library(refcmp)
+snapshot.init()
+
+# Taking a snapshot of variables or comparing the values to the reference run
+a <- 1
+b <- 2
+snapshot(a, b)
+
+# Taking a snapshot of expressions or comparing the values
+# We need to name them
+snapshot.named(c = 2 +3, d = a + b)
+
+# Show the contents of the latest snapshot
+snapshot.show()
+
+# Show the contents of a snapshot using the ID (a sequence number)
+snapshot.show(0)
+
+}
diff --git a/com.oracle.truffle.r.pkgs/refcmp/man/snapshot.Rd b/com.oracle.truffle.r.pkgs/refcmp/man/snapshot.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..792bed41912e361590b4590d457735317e3a5f44
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/refcmp/man/snapshot.Rd
@@ -0,0 +1,24 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/snapshot.R
+\name{snapshot}
+\alias{snapshot}
+\title{Take a snapshot of some variable's values or compare the values to a previously taken snapshot.}
+\usage{
+snapshot(...)
+}
+\description{
+This function has two modes, (1) record, and (2) check.
+Depending on the result of function 'refcmpEnv$is_reference_run', the mode is (1) if TRUE is returned or (2) otherwise.
+}
+\details{
+When in the first mode 'record', function 'snapshot' serializes the values of the specified variables into a file together with the names of the variables. It also increases the ID of the snapshot automatically.
+
+When in the second mode 'check', function 'snapshot' deserializes values of a previously taken snapshot and compares the values of the provided variables to the deserialized values by matching names.
+}
+\examples{
+x <- 10
+y <- 20
+z <- function() print("hello")
+
+snapshot(x, y, z)
+}
diff --git a/com.oracle.truffle.r.pkgs/refcmp/man/snapshot.init.Rd b/com.oracle.truffle.r.pkgs/refcmp/man/snapshot.init.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..012f384caf43f652146f55ff2568401591c2601f
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/refcmp/man/snapshot.init.Rd
@@ -0,0 +1,25 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/snapshot.R
+\name{snapshot.init}
+\alias{snapshot.init}
+\title{Initialize package}
+\usage{
+snapshot.init(dir, is_reference_run, equalityFunction)
+}
+\arguments{
+\item{dir}{The directory where to store snapshot to (default: 'snapshots')}
+
+\item{is_reference_run}{A function returning TRUE if snapshots should be taken and FALSE if values should be compared (default: snapshot dir does not exist)}
+
+\item{equalityFunction}{The function to use for comparing actual values to snapshotted values (default: 'all.equal')}
+}
+\description{
+Initialize package
+}
+\examples{
+# Only comparing using snapshots in directory "my/snapshot/dir" and using function 'identical' to compare values.
+snapshot.init(dir = "my/snapshot/dir", referenceRunPredicate = function() FALSE, equalityFunction = identical)
+
+# This should do the job in most cases
+snapshot.init()
+}
diff --git a/com.oracle.truffle.r.pkgs/refcmp/man/snapshot.named.Rd b/com.oracle.truffle.r.pkgs/refcmp/man/snapshot.named.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..1a076ec6915b17ab039728a26395a1d2ffbafeb2
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/refcmp/man/snapshot.named.Rd
@@ -0,0 +1,23 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/snapshot.R
+\name{snapshot.named}
+\alias{snapshot.named}
+\title{Take a snapshot of provided values and name the values as specified in the arguments.}
+\usage{
+snapshot.named(...)
+}
+\description{
+This function has two modes, (1) record, and (2) check.
+Depending on the result of function 'refcmpEnv$is_reference_run', the mode is (1) if TRUE is returned or (2) otherwise.
+}
+\details{
+When in the first mode 'record', function 'snapshot.named' serializes the values of the specified variables into a file together with the names of the variables. It also increases the ID of the snapshot automatically.
+
+When in the second mode 'check', function 'snapshot.named' deserializes values of a previously taken snapshot and compares the values of the provided variables to the deserialized values by matching names.
+
+I contrast to function 'snapshot', this function does not try to automatically determine the name of a value.
+It uses the names as provided in the arguments.
+}
+\examples{
+snapshot.named(a = 10 + 20, b = 30, c = function() print("hello"))
+}
diff --git a/com.oracle.truffle.r.pkgs/refcmp/man/snapshot.show.Rd b/com.oracle.truffle.r.pkgs/refcmp/man/snapshot.show.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..d2170d4e23269777f151b33870dd145a36d416c9
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/refcmp/man/snapshot.show.Rd
@@ -0,0 +1,32 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/snapshot.R
+\name{snapshot.show}
+\alias{snapshot.show}
+\title{Shows the contents of a snapshot.}
+\usage{
+snapshot.show(id = refcmpEnv$snapshot_id)
+}
+\arguments{
+\item{id}{The ID of the snapshot to show (default: latest)}
+}
+\description{
+Shows the contents of a snapshot.
+}
+\examples{
+a <- 1
+snapshot(a)
+snapshot.show()
+
+a <- 2
+snapshot(a)
+
+a <- 3
+snapshot(a)
+
+a <- 4
+snapshot(a)
+snapshot.show(0)
+snapshot.show(1)
+snapshot.show(2)
+snapshot.show(3)
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java
index ecd287b87b5bdf9a1c120d634bc935e074af3c8c..6dedde1535352ed78b38f7aa66e496d2e6ccf3ad 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java
@@ -222,6 +222,9 @@ public final class ArgumentsSignature implements Iterable<String> {
             return false;
         }
         ArgumentsSignature other = (ArgumentsSignature) obj;
+        if (length != other.length) {
+            return false;
+        }
         if (!Arrays.equals(names, other.names)) {
             return false;
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
index 79911c2ea1a89f89c83829060c0a7021336f1895..fec907242f0fc9d30cb9e084d97b8384a3fa941e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
@@ -363,8 +363,8 @@ abstract class DelegateRConnection implements RConnection, ByteChannel {
                 channel.position(offset);
                 break;
             case END:
-                throw RInternalError.unimplemented();
-
+                channel.position(channel.size());
+                break;
         }
         return position;
     }
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 23aeeb5945798641fbd90e60e94ccec19d95c57e..867ad706c8c086e9fe0427b76e16002d08686958 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
@@ -22909,6 +22909,48 @@ End = 1
 Frequency = 1
 [1] FALSE
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_dump.testDumpData#Output.IgnoreWhitespace#
+#{ x <- 10; .Internal(dump("x", stdout(), environment(), .deparseOpts("all"), TRUE))}
+x <-
+10
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_dump.testDumpData#Output.IgnoreWhitespace#
+#{ x <- 1:10; .Internal(dump("x", stdout(), environment(), .deparseOpts("all"), TRUE))}
+x <-
+1:10
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_dump.testDumpData#Output.IgnoreWhitespace#
+#{ x <- c(10,20,25); .Internal(dump("x", stdout(), environment(), .deparseOpts("all"), TRUE))}
+x <-
+c(10, 20, 25)
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_dump.testDumpData#Output.IgnoreWhitespace#
+#{ x <- list(a=10,b=20); .Internal(dump("x", stdout(), environment(), .deparseOpts("all"), TRUE))}
+x <-
+structure(list(a = 10, b = 20), .Names = c("a", "b"))
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_dump.testDumpFunctions#Output.IgnoreWhitespace#
+#{ foo <- function() cat("Hello"); bar <- function() cat("World"); .Internal(dump(c("foo", "bar"), stdout(), environment(), .deparseOpts("all"), TRUE))}
+foo <-
+function() cat("Hello")
+bar <-
+function() cat("World")
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_dump.testDumpFunctions#Output.IgnoreWhitespace#
+#{ fun <- function() print("Hello, World!"); .Internal(dump("fun", stdout(), environment(), .deparseOpts("all"), TRUE))}
+fun <-
+function() print("Hello, World!")
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_dump.testDumpLanguage#Output.IgnoreWhitespace#
+#{ x <- 2 + 3; .Internal(dump("x", stdout(), environment(), .deparseOpts("all"), FALSE))}
+x <-
+5
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_dump.testDumpLanguage#Output.IgnoreWhitespace#
+#{ x <- quote(2 + 3); .Internal(dump("x", stdout(), environment(), .deparseOpts("all"), FALSE))}
+x <-
+quote(2 + 3)
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_duplicated.testDuplicated#
 #{ duplicated(NULL, 0); }
 logical(0)
@@ -86106,6 +86148,10 @@ NULL
 ##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testIfWithoutElseIgnore#
 #if(FALSE) 1
 
+##com.oracle.truffle.r.test.library.base.TestSimpleIfEvaluator.testInvalidCondition#
+#{ f <- function() TRUE; if (f) 'unexpected' }
+Error in if (f) "unexpected" : argument is not interpretable as logical
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleLists.testAvoidingCopying#
 #a<-list(); a$x <- c(1,2,3); ident <- function(q)q; invisible(tracemem(a$x)); a$x[[1]] <- ident(a$x[[2]]); a$x
 [1] 2 2 3
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dump.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dump.java
new file mode 100644
index 0000000000000000000000000000000000000000..8d81d425416539cf084cee2f1a745b44f607b994
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dump.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.test.builtins;
+
+import org.junit.Test;
+
+import com.oracle.truffle.r.test.TestBase;
+
+// Checkstyle: stop line length check
+public class TestBuiltin_dump extends TestBase {
+
+    private static final String TEMPLATE = "{ %s; .Internal(dump(%s, stdout(), environment(), .deparseOpts(\"all\"), %s))}";
+
+    @Test
+    public void testDumpFunctions() {
+        assertEval(Output.IgnoreWhitespace, String.format(TEMPLATE, "fun <- function() print(\"Hello, World!\")", "\"fun\"", "TRUE"));
+        assertEval(Output.IgnoreWhitespace, String.format(TEMPLATE, "foo <- function() cat(\"Hello\"); bar <- function() cat(\"World\")", "c(\"foo\", \"bar\")", "TRUE"));
+    }
+
+    @Test
+    public void testDumpData() {
+        assertEval(Output.IgnoreWhitespace, String.format(TEMPLATE, "x <- 10", "\"x\"", "TRUE"));
+        assertEval(Output.IgnoreWhitespace, String.format(TEMPLATE, "x <- list(a=10,b=20)", "\"x\"", "TRUE"));
+        assertEval(Output.IgnoreWhitespace, String.format(TEMPLATE, "x <- c(10,20,25)", "\"x\"", "TRUE"));
+        assertEval(Output.IgnoreWhitespace, String.format(TEMPLATE, "x <- 1:10", "\"x\"", "TRUE"));
+    }
+
+    @Test
+    public void testDumpLanguage() {
+        assertEval(Output.IgnoreWhitespace, String.format(TEMPLATE, "x <- 2 + 3", "\"x\"", "FALSE"));
+        assertEval(Output.IgnoreWhitespace, String.format(TEMPLATE, "x <- quote(2 + 3)", "\"x\"", "FALSE"));
+    }
+
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleIfEvaluator.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleIfEvaluator.java
index 60dc992cb1c4a89329dfdfd6dad428c00a7ad884..eaf9e7103d64916684fa218e2187505296bc38b0 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleIfEvaluator.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleIfEvaluator.java
@@ -100,4 +100,9 @@ public class TestSimpleIfEvaluator extends TestBase {
         assertEval("{ if (TRUE) invisible(23) }");
         assertEval("{ if (FALSE) 23 else invisible(23) }");
     }
+
+    @Test
+    public void testInvalidCondition() {
+        assertEval("{ f <- function() TRUE; if (f) 'unexpected' }");
+    }
 }