diff --git a/ci.hocon b/ci.hocon
index 9e85b47df51380e4d3737037c9d54df84d1f5a1d..5c04f82cf99d06dc864f4b1ae2ae87a4c3721224 100644
--- a/ci.hocon
+++ b/ci.hocon
@@ -7,6 +7,7 @@
 java7 : {name : oraclejdk, version : "7",    platformspecific: true}
 # java 8 must be a jvmci enabled variant
 java8 : {name : labsjdk, version : "8-jvmci-latest", platformspecific: true}
+java9 : {name : labsjdk, version : "9-ea+168", platformspecific: true}
 
 java8Downloads : {
   downloads : {
@@ -17,6 +18,16 @@ java8Downloads : {
   }
 }
 
+java9Downloads : {
+  downloads : {
+    EXTRA_JAVA_HOMES : { pathlist :[
+      ${java7}
+      ${java8}
+    ]}
+    JAVA_HOME : ${java9}
+  }
+}
+
 logfiles : [
     "fastr_errors.log"
     "results.json"
@@ -123,6 +134,12 @@ gateTestManagedLinux: ${common} {
   ]
 }
 
+gateTestJava9Linux : ${java9Downloads} ${gateTestCommon} {
+  downloads : {
+    JAVA_HOME : ${java9Downloads.downloads.JAVA_HOME}
+    EXTRA_JAVA_HOMES : ${java9Downloads.downloads.EXTRA_JAVA_HOMES}
+  }
+}
 
 # This performs a number of "style" checks on the code to ensure it confirms to the project standards.
 
@@ -171,4 +188,5 @@ builds = [
   ${rbcheck}                  {capabilities : [linux, amd64],  targets : [gate], name: "gate-rbcheck-linux-amd64"}
   ${internalPkgtest}          {capabilities : [linux, amd64],  targets : [gate], name: "gate-internal-pkgtest-linux-amd64"}
   ${gateTestManagedLinux}     {capabilities : [linux, amd64, fast],  targets : [gate], name: "gate-test-managed-linux-amd64"}
+  ${gateTestJava9Linux}       {capabilities : [linux, amd64, fast],  targets : [gate], name: "gate-test-java9-linux-amd64"}
 ]
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java
index a1027bfdc9013d56578f9aab0f743c2c6e10bd77..49bbcb8c54d4552a613aba0b86ca1a448fe35f6e 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java
@@ -390,7 +390,7 @@ final class REngine implements Engine, Engine.Timings {
                     }
                     lastValue = calls[i].call(new Object[]{executionFrame != null ? executionFrame : newContext.stateREnvironment.getGlobalFrame()});
                 }
-                return lastValue;
+                return RRuntime.r2Java(lastValue);
             } catch (ReturnException ex) {
                 return ex.getResult();
             } catch (DebugExitException | JumpToTopLevelException | ExitException | ThreadDeath e) {
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 ed08560e6b131206d1d416026031cdf0a9c24215..7c242944350bfebdceda6e44619e119485e7d8c3 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
@@ -438,7 +438,7 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
         // This checks for the specific structure of replacements
         RLanguage replacement = ReplacementDispatchNode.getRLanguage(rl);
         RLanguage elem = replacement == null ? rl : replacement;
-        String string = RDeparse.deparse(elem, RDeparse.DEFAULT_Cutoff, true, RDeparse.KEEPINTEGER, -1);
+        String string = RDeparse.deparse(elem, RDeparse.DEFAULT_CUTOFF, true, RDeparse.KEEPINTEGER, -1);
         return string.split("\n")[0];
     }
 
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java
index ee9a96bf866b4d36ef569b37630685bcfd81a6af..7a858d921322dde03302073b288e8218cebf7a06 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java
@@ -148,7 +148,7 @@ public final class TruffleRLanguage extends TruffleLanguage<RContext> implements
             return (String) unwrapped;
         }
         if (unwrapped instanceof RTypedValue) {
-            return RDeparse.deparse(unwrapped);
+            return RDeparse.deparse(unwrapped, RDeparse.MAX_CUTOFF, true, RDeparse.KEEPINTEGER, -1, 1024 * 1024);
         }
         return RRuntime.toString(unwrapped);
     }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/REmptyMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/REmptyMR.java
new file mode 100644
index 0000000000000000000000000000000000000000..99277bbbcfbee60a210c5d0eacf8c530faa4dae0
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/REmptyMR.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop;
+
+import com.oracle.truffle.api.interop.CanResolve;
+import com.oracle.truffle.api.interop.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.engine.TruffleRLanguage;
+import com.oracle.truffle.r.runtime.data.REmpty;
+
+@MessageResolution(receiverType = REmpty.class, language = TruffleRLanguage.class)
+public class REmptyMR {
+
+    @Resolve(message = "IS_BOXED")
+    public abstract static class REmptyIsBoxedNode extends Node {
+        protected Object access(@SuppressWarnings("unused") REmpty receiver) {
+            return false;
+        }
+    }
+
+    @Resolve(message = "HAS_SIZE")
+    public abstract static class REmptyHasSizeNode extends Node {
+        protected Object access(@SuppressWarnings("unused") REmpty receiver) {
+            return false;
+        }
+    }
+
+    @Resolve(message = "IS_NULL")
+    public abstract static class REmptyIsNullNode extends Node {
+        protected Object access(@SuppressWarnings("unused") REmpty receiver) {
+            return false;
+        }
+    }
+
+    @CanResolve
+    public abstract static class REmptyCheck extends Node {
+
+        protected static boolean test(TruffleObject receiver) {
+            return receiver instanceof REmpty;
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
index 9082fefc169f2c968b3d4eb6e6b27411e2ed162c..fa203c367ab06940717e8f66f02b92fb8910150b 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RForeignAccessFactoryImpl.java
@@ -29,22 +29,24 @@ import com.oracle.truffle.api.interop.MessageResolution;
 import com.oracle.truffle.r.engine.TruffleRLanguage;
 import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_Base;
 import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_PCRE;
-import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_UpCallsRFFIImpl;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.conn.RConnection;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.context.RForeignAccessFactory;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RDouble;
+import com.oracle.truffle.r.runtime.data.REmpty;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RInteger;
+import com.oracle.truffle.r.runtime.data.RInteropScalar;
 import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
-import com.oracle.truffle.r.runtime.data.RS4Object;
 import com.oracle.truffle.r.runtime.data.RPromise;
+import com.oracle.truffle.r.runtime.data.RS4Object;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.RTruffleObject;
 import com.oracle.truffle.r.runtime.data.RUnboundValue;
@@ -125,6 +127,12 @@ public final class RForeignAccessFactoryImpl implements RForeignAccessFactory {
             return RLanguageMRForeign.ACCESS;
         } else if (obj instanceof ActiveBinding) {
             return ActiveBindingMRForeign.ACCESS;
+        } else if (obj instanceof RInteropScalar) {
+            return RInteropScalarMRForeign.ACCESS;
+        } else if (obj instanceof RMissing) {
+            return RMissingMRForeign.ACCESS;
+        } else if (obj instanceof REmpty) {
+            return REmptyMRForeign.ACCESS;
 
         } else {
             if (obj instanceof RAbstractVector) {
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RInteropScalarMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RInteropScalarMR.java
new file mode 100644
index 0000000000000000000000000000000000000000..d904aa2171893fb5433e80805af01b2c8eff4291
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RInteropScalarMR.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop;
+
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.interop.CanResolve;
+import com.oracle.truffle.api.interop.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.profiles.ValueProfile;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.data.RInteropScalar;
+
+@MessageResolution(receiverType = RInteropScalar.class)
+public class RInteropScalarMR {
+
+    @Resolve(message = "IS_BOXED")
+    public abstract static class RInteropScalarIsBoxedNode extends Node {
+        protected Object access(@SuppressWarnings("unused") RInteropScalar receiver) {
+            return true;
+        }
+    }
+
+    @Resolve(message = "UNBOX")
+    public abstract static class RInteropScalarUnboxNode extends Node {
+        private final ValueProfile classProfile = ValueProfile.createClassProfile();
+
+        protected Object access(RInteropScalar receiver) {
+            RInteropScalar t = classProfile.profile(receiver);
+            if (t instanceof RInteropScalar.RInteropByte) {
+                return ((RInteropScalar.RInteropByte) t).getValue();
+            } else if (t instanceof RInteropScalar.RInteropChar) {
+                return ((RInteropScalar.RInteropChar) t).getValue();
+            } else if (t instanceof RInteropScalar.RInteropFloat) {
+                return ((RInteropScalar.RInteropFloat) t).getValue();
+            } else if (t instanceof RInteropScalar.RInteropLong) {
+                return ((RInteropScalar.RInteropLong) t).getValue();
+            } else if (t instanceof RInteropScalar.RInteropShort) {
+                return ((RInteropScalar.RInteropShort) t).getValue();
+            }
+            throw RInternalError.unimplemented("missing RInteropScalar : " + receiver.getClass().getName());
+        }
+    }
+
+    @Resolve(message = "HAS_SIZE")
+    public abstract static class RInteropScalarHasSizeNode extends Node {
+        protected Object access(@SuppressWarnings("unused") RInteropScalar receiver) {
+            return false;
+        }
+    }
+
+    @Resolve(message = "IS_NULL")
+    public abstract static class RInteropScalarIsNullNode extends Node {
+        protected Object access(@SuppressWarnings("unused") RInteropScalar receiver) {
+            return false;
+        }
+    }
+
+    @CanResolve
+    public abstract static class RInteropScalarCheck extends Node {
+        protected static boolean test(TruffleObject receiver) {
+            return receiver instanceof RInteropScalar;
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RMissingMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RMissingMR.java
new file mode 100644
index 0000000000000000000000000000000000000000..656843ed0c421fa4281d00467a90ca850a28203d
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RMissingMR.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.engine.interop;
+
+import com.oracle.truffle.api.interop.CanResolve;
+import com.oracle.truffle.api.interop.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.engine.TruffleRLanguage;
+import com.oracle.truffle.r.runtime.data.RMissing;
+
+@MessageResolution(receiverType = RMissing.class, language = TruffleRLanguage.class)
+public class RMissingMR {
+
+    @Resolve(message = "IS_BOXED")
+    public abstract static class RMissingIsBoxedNode extends Node {
+        protected Object access(@SuppressWarnings("unused") RMissing receiver) {
+            return false;
+        }
+    }
+
+    @Resolve(message = "HAS_SIZE")
+    public abstract static class RMissingHasSizeNode extends Node {
+        protected Object access(@SuppressWarnings("unused") RMissing receiver) {
+            return false;
+        }
+    }
+
+    @Resolve(message = "IS_NULL")
+    public abstract static class RMissingIsNullNode extends Node {
+        protected Object access(@SuppressWarnings("unused") RMissing receiver) {
+            return false;
+        }
+    }
+
+    @CanResolve
+    public abstract static class RMissingCheck extends Node {
+
+        protected static boolean test(TruffleObject receiver) {
+            return receiver instanceof RMissing;
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/EmbeddedConsoleHandler.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/EmbeddedConsoleHandler.java
index cc668a856e86c2abd0db1876c3b47278f2739e20..c47155062d8634fd1b9d7b965304af8a6ccc7779 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/EmbeddedConsoleHandler.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/EmbeddedConsoleHandler.java
@@ -38,7 +38,7 @@ import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
  * have be lazy about that.
  *
  */
-public class EmbeddedConsoleHandler implements ConsoleHandler {
+public class EmbeddedConsoleHandler extends ConsoleHandler {
 
     private final RStartParams startParams;
     /**
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleCompleter.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleCompleter.java
index 2c18397bf7f432a3a4d80572fef3d634c022cdb6..eaeeb329ea451ca404e91fe0c99f69592298e2e8 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleCompleter.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleCompleter.java
@@ -22,20 +22,23 @@
  */
 package com.oracle.truffle.r.engine.shell;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.r.nodes.function.PromiseHelperNode;
 import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.context.ConsoleHandler;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RList;
 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 java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
+
 import jline.console.completer.Completer;
 
 public class JLineConsoleCompleter implements Completer {
@@ -64,50 +67,54 @@ public class JLineConsoleCompleter implements Completer {
         return cursor;
     }
 
-    private static int completeImpl(String buffer, int cursor, List<CharSequence> candidates) {
+    @SuppressWarnings("try")
+    private int completeImpl(String buffer, int cursor, List<CharSequence> candidates) {
         if (buffer.isEmpty()) {
             return cursor;
         }
 
-        REnvironment utils = REnvironment.getRegisteredNamespace("utils");
-        Object o = utils.get(".completeToken");
-        if (o instanceof RPromise) {
-            o = PromiseHelperNode.evaluateSlowPath(null, (RPromise) o);
-        }
-        RFunction completeToken;
-        if (o instanceof RFunction) {
-            completeToken = (RFunction) o;
-        } else {
-            return cursor;
-        }
+        try (RCloseable c = RContext.withinContext(console.getContext())) {
 
-        o = utils.get(".CompletionEnv");
-        if (!(o instanceof RPromise)) {
-            return cursor;
-        }
-        REnvironment env = (REnvironment) PromiseHelperNode.evaluateSlowPath(null, (RPromise) o);
-        int start = getStart(buffer, env, cursor);
-        env.safePut("start", start);
-        env.safePut("end", cursor);
-        env.safePut("linebuffer", buffer);
-        env.safePut("token", buffer.substring(start, cursor));
-
-        MaterializedFrame callingFrame = REnvironment.globalEnv().getFrame();
-        RContext.getEngine().evalFunction(completeToken, callingFrame, RCaller.createInvalid(callingFrame), null, new Object[]{});
-
-        o = env.get("comps");
-        if (!(o instanceof RAbstractStringVector)) {
-            return cursor;
-        }
+            REnvironment utils = REnvironment.getRegisteredNamespace("utils");
+            Object o = utils.get(".completeToken");
+            if (o instanceof RPromise) {
+                o = PromiseHelperNode.evaluateSlowPath(null, (RPromise) o);
+            }
+            RFunction completeToken;
+            if (o instanceof RFunction) {
+                completeToken = (RFunction) o;
+            } else {
+                return cursor;
+            }
+
+            o = utils.get(".CompletionEnv");
+            if (!(o instanceof RPromise)) {
+                return cursor;
+            }
+            REnvironment env = (REnvironment) PromiseHelperNode.evaluateSlowPath(null, (RPromise) o);
+            int start = getStart(buffer, env, cursor);
+            env.safePut("start", start);
+            env.safePut("end", cursor);
+            env.safePut("linebuffer", buffer);
+            env.safePut("token", buffer.substring(start, cursor));
+
+            MaterializedFrame callingFrame = REnvironment.globalEnv().getFrame();
+            RContext.getEngine().evalFunction(completeToken, callingFrame, RCaller.createInvalid(callingFrame), null, new Object[]{});
+
+            o = env.get("comps");
+            if (!(o instanceof RAbstractStringVector)) {
+                return cursor;
+            }
 
-        RAbstractStringVector comps = (RAbstractStringVector) o;
-        List<String> ret = new ArrayList<>(comps.getLength());
-        for (int i = 0; i < comps.getLength(); i++) {
-            ret.add(comps.getDataAt(i));
+            RAbstractStringVector comps = (RAbstractStringVector) o;
+            List<String> ret = new ArrayList<>(comps.getLength());
+            for (int i = 0; i < comps.getLength(); i++) {
+                ret.add(comps.getDataAt(i));
+            }
+            Collections.sort(ret, String.CASE_INSENSITIVE_ORDER);
+            candidates.addAll(ret);
+            return start;
         }
-        Collections.sort(ret, String.CASE_INSENSITIVE_ORDER);
-        candidates.addAll(ret);
-        return start;
     }
 
     private static int getStart(String buffer, REnvironment env, int cursor) {
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleHandler.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleHandler.java
index 18ced0d667c767e10df4217d3bdd630da2cbb77e..6353be6e9a9fc9199ef8dea6a3744c386a8f8908 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleHandler.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleHandler.java
@@ -39,7 +39,7 @@ import jline.console.UserInterruptException;
 import jline.console.history.FileHistory;
 import jline.console.history.History;
 
-class JLineConsoleHandler implements ConsoleHandler {
+class JLineConsoleHandler extends ConsoleHandler {
     private final ConsoleReader console;
     private final boolean isInteractive;
     private final PrintWriter printWriter;
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java
index 9f159f813512fb6ae93d57a02795069172011266..0f98a4dbcbd93f27024760beeb60afca1f0b1afe 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java
@@ -54,11 +54,13 @@ import com.oracle.truffle.r.runtime.Utils.DebugExitException;
 import com.oracle.truffle.r.runtime.context.ConsoleHandler;
 import com.oracle.truffle.r.runtime.context.ContextInfo;
 import com.oracle.truffle.r.runtime.context.DefaultConsoleHandler;
+import com.oracle.truffle.r.runtime.context.Engine;
 import com.oracle.truffle.r.runtime.context.Engine.IncompleteSourceException;
 import com.oracle.truffle.r.runtime.context.Engine.ParseException;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.context.RContext.ContextKind;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
+import com.oracle.truffle.r.runtime.data.RStringVector;
 
 import jline.console.UserInterruptException;
 
@@ -190,6 +192,7 @@ public class RCommand {
 
     private static final Source GET_ECHO = RSource.fromTextInternal("invisible(getOption('echo'))", RSource.Internal.GET_ECHO);
     private static final Source QUIT_EOF = RSource.fromTextInternal("quit(\"default\", 0L, TRUE)", RSource.Internal.QUIT_EOF);
+    private static final Source GET_CONTINUE_PROMPT = RSource.fromTextInternal("invisible(getOption('continue'))", RSource.Internal.GET_CONTINUE_PROMPT);
 
     /**
      * The read-eval-print loop, which can take input from a console, command line expression or a
@@ -221,10 +224,10 @@ public class RCommand {
                         continue;
                     }
 
-                    String continuePrompt = getContinuePrompt();
+                    String continuePrompt = getContinuePrompt(vm);
                     StringBuffer sb = new StringBuffer(input);
                     Source source = RSource.fromTextInternal(sb.toString(), RSource.Internal.SHELL_INPUT);
-                    boolean hasExecutor = RContext.getInstance().hasExecutor();
+                    boolean hasExecutor = hasExectuor(vm);
                     while (true) {
                         lastStatus = 0;
                         try {
@@ -308,7 +311,9 @@ public class RCommand {
     private static boolean doEcho(PolyglotEngine vm) {
         PolyglotEngine.Value echoValue = vm.eval(GET_ECHO);
         Object echo = echoValue.get();
-        if (echo instanceof TruffleObject) {
+        if (echo instanceof Boolean) {
+            return (boolean) echo;
+        } else if (echo instanceof TruffleObject) {
             RLogicalVector echoVec = echoValue.as(RLogicalVector.class);
             return RRuntime.fromLogical(echoVec.getDataAt(0));
         } else if (echo instanceof Byte) {
@@ -318,7 +323,21 @@ public class RCommand {
         }
     }
 
-    private static String getContinuePrompt() {
-        return RRuntime.asString(RRuntime.asAbstractVector(RContext.getInstance().stateROptions.getValue("continue")));
+    private static String getContinuePrompt(PolyglotEngine vm) {
+        PolyglotEngine.Value echoValue = vm.eval(GET_CONTINUE_PROMPT);
+        Object echo = echoValue.get();
+        if (echo instanceof String) {
+            return (String) echo;
+        } else if (echo instanceof TruffleObject) {
+            RStringVector promptVec = echoValue.as(RStringVector.class);
+            return promptVec.getDataAt(0);
+        } else {
+            throw RInternalError.shouldNotReachHere();
+        }
     }
+
+    private static boolean hasExectuor(PolyglotEngine vm) {
+        return vm.eval(Engine.GET_CONTEXT).as(RContext.class).hasExecutor();
+    }
+
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/StringConsoleHandler.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/StringConsoleHandler.java
index 51af0bead26b43b0fa393bd666900a01a7a1fcc2..271b69345df92e9297e4d81391d5fece14eff410 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/StringConsoleHandler.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/StringConsoleHandler.java
@@ -28,13 +28,15 @@ import java.util.List;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.context.ConsoleHandler;
+import com.oracle.truffle.r.runtime.context.RContext;
 
-class StringConsoleHandler implements ConsoleHandler {
+class StringConsoleHandler extends ConsoleHandler {
     private final PrintStream output;
     private final List<String> lines;
     private final String inputDescription;
     private String prompt;
     private int currentLine;
+    private RContext ctx;
 
     StringConsoleHandler(List<String> lines, OutputStream output, String inputDescription) {
         this.lines = lines;
@@ -103,4 +105,14 @@ class StringConsoleHandler implements ConsoleHandler {
     public String getInputDescription() {
         return inputDescription;
     }
+
+    @Override
+    public void setContext(RContext ctx) {
+        this.ctx = ctx;
+    }
+
+    @Override
+    public RContext getContext() {
+        return ctx;
+    }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
index 1f297581c409dd3eb1c7e4bf0c1f3cf691fefcd5..016b8d9e98c8d7a83c1ede405b736cd431eb03d5 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/FastRGridExternalLookup.java
@@ -25,6 +25,8 @@ package com.oracle.truffle.r.library.fastrGrid;
 import com.oracle.truffle.r.library.fastrGrid.DisplayList.LGetDisplayListElement;
 import com.oracle.truffle.r.library.fastrGrid.DisplayList.LInitDisplayList;
 import com.oracle.truffle.r.library.fastrGrid.DisplayList.LSetDisplayListOn;
+import com.oracle.truffle.r.library.fastrGrid.PaletteExternals.CPalette;
+import com.oracle.truffle.r.library.fastrGrid.PaletteExternals.CPalette2;
 import com.oracle.truffle.r.library.fastrGrid.grDevices.DevCairo;
 import com.oracle.truffle.r.library.fastrGrid.grDevices.DevCurr;
 import com.oracle.truffle.r.library.fastrGrid.grDevices.DevHoldFlush;
@@ -75,6 +77,10 @@ public final class FastRGridExternalLookup {
                 return SavePlot.create();
             case "X11":
                 return new InitWindowedDevice();
+            case "palette":
+                return CPalette.create();
+            case "palette2":
+                return CPalette2.create();
             default:
                 return null;
         }
@@ -94,6 +100,8 @@ public final class FastRGridExternalLookup {
                 return LValidUnit.create();
             case "L_pretty":
                 return LPretty.create();
+            case "L_stringMetric":
+                return LStringMetric.create();
 
             // Viewport management
             case "L_upviewport":
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
index f826ccd696f2f509374b4b9c2b072fa9ab75957c..48e5ca2d58fcd3da897908e0acc74003041ee96d 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java
@@ -18,6 +18,7 @@ import static com.oracle.truffle.r.library.fastrGrid.GridUtils.getDataAtMod;
 import java.util.Arrays;
 import java.util.function.Function;
 
+import com.oracle.truffle.r.library.fastrGrid.GridState.GridPalette;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContextDefaults;
 import com.oracle.truffle.r.library.fastrGrid.device.GridColor;
@@ -25,6 +26,7 @@ import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 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.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -264,7 +266,22 @@ public final class GPar {
         }
 
         private GridColor getGridColor(int listIndex) {
-            GridColor color = GridColorUtils.gridColorFromString(GridUtils.asString(data[listIndex], index));
+            Object value = data[listIndex];
+            GridColor color = getPaletteColor(value);
+            if (color != null) {
+                return color;
+            }
+
+            String strValue = null;
+            if (value instanceof String) {
+                strValue = (String) value;
+            } else if (value instanceof RAbstractStringVector && ((RAbstractStringVector) value).getLength() > 0) {
+                strValue = ((RAbstractStringVector) value).getDataAt(index % ((RAbstractStringVector) value).getLength());
+            } else {
+                return GridColor.TRANSPARENT;
+            }
+
+            color = GridColorUtils.gridColorFromString(strValue);
             double alpha = asDouble(data[GP_ALPHA], index);
             if (alpha != 1.) {
                 int newAlpha = Math.min(255, (int) (alpha * ((color.getAlpha() / 255.0) * 255)));
@@ -274,6 +291,44 @@ public final class GPar {
             }
         }
 
+        private GridColor getPaletteColor(Object colorIdIn) {
+            Object colorId = colorIdIn;
+            if (colorId instanceof RAbstractVector) {
+                RAbstractVector vec = (RAbstractVector) colorId;
+                colorId = vec.getDataAtAsObject(index % vec.getLength());
+            }
+            int paletteIdx = RRuntime.INT_NA;
+            if (colorId instanceof Integer) {
+                paletteIdx = (int) colorId;
+            } else if (colorId instanceof Double && !RRuntime.isNA((Double) colorId)) {
+                paletteIdx = (int) (double) colorId;
+            } else if (colorId instanceof String && !RRuntime.isNA((String) colorId)) {
+                paletteIdx = paletteIdxFromString((String) colorId);
+            } else if (colorId instanceof Byte && !RRuntime.isNA((byte) colorId)) {
+                paletteIdx = (int) (byte) colorId;
+            }
+            if (RRuntime.isNA(paletteIdx)) {
+                return null;
+            }
+            if (paletteIdx < 0) {
+                throw RError.error(RError.NO_CALLER, Message.GENERIC, Utils.stringFormat("numerical color values must be >= 0, found %d", paletteIdx));
+            }
+            if (paletteIdx == 0) {
+                return GridColor.TRANSPARENT;
+            }
+            GridPalette palette = GridContext.getContext().getGridState().getPalette();
+            GridColor result = palette.colors[(paletteIdx - 1) % palette.colors.length];
+            return result; // one based index
+        }
+
+        private int paletteIdxFromString(String colorId) {
+            try {
+                return Integer.parseInt(colorId, 10);
+            } catch (NumberFormatException ex) {
+                return RRuntime.INT_NA;
+            }
+        }
+
         private static final byte[] DASHED_LINE = new byte[]{4, 4};
         private static final byte[] DOTTED_LINE = new byte[]{1, 3};
         private static final byte[] DOTDASH_LINE = new byte[]{1, 3, 4, 3};
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridColorUtils.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridColorUtils.java
index 939a90546e5b2cfcb1ef3155d6c352519e64fe16..1ec25bf728686609acfa0232c2515f4f09818363 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridColorUtils.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridColorUtils.java
@@ -14,15 +14,36 @@ package com.oracle.truffle.r.library.fastrGrid;
 import java.util.HashMap;
 import java.util.Locale;
 
+import com.oracle.truffle.r.library.fastrGrid.GridState.GridPalette;
 import com.oracle.truffle.r.library.fastrGrid.device.GridColor;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 
 public final class GridColorUtils {
+
+    private static GridPalette defaultPalette;
+
     private GridColorUtils() {
         // only static members
     }
 
+    public static GridPalette getDefaultPalette() {
+        if (defaultPalette == null) {
+            // Note: default palette copied from GNU R
+            defaultPalette = new GridPalette(new String[]{
+                            "black",
+                            "red",
+                            "green3",
+                            "blue",
+                            "cyan",
+                            "magenta",
+                            "yellow",
+                            "grey"
+            });
+        }
+        return defaultPalette;
+    }
+
     /**
      * Converts the representation of color used within R, e.g. as value for
      * {@code gpar(col='value')}, to our internal representation that grid device should understand.
@@ -34,6 +55,11 @@ public final class GridColorUtils {
             return parseHex(value);
         }
 
+        if (value.equals("NA")) {
+            // special case value, we want to check only for "NA", not "na".
+            return GridColor.TRANSPARENT;
+        }
+
         Object result = findByName(value);
         if (result == null) {
             throw RError.error(RError.NO_CALLER, Message.GENERIC, "Invalid color '" + value + "'.");
@@ -84,7 +110,6 @@ public final class GridColorUtils {
 
         static {
             NAMES.put("transparent", GridColor.TRANSPARENT);
-            NAMES.put("NA", GridColor.TRANSPARENT);
             NAMES.put("white", "#FFFFFF");
             NAMES.put("aliceblue", "#F0F8FF");
             NAMES.put("antiquewhite", "#FAEBD7");
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
index 63585c18374f5b8e04e6325d8730b9afa1619a1b..20027f98003ddadbf07e640aa24cea53f7afe6b0 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java
@@ -13,6 +13,7 @@ package com.oracle.truffle.r.library.fastrGrid;
 
 import java.util.function.Supplier;
 
+import com.oracle.truffle.r.library.fastrGrid.device.GridColor;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -21,6 +22,7 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
 public final class GridState {
     private REnvironment gridEnv;
     private GridDeviceState devState;
+    private GridPalette palette;
 
     /**
      * Current grob being drawn (for determining the list of grobs to search when evaluating a
@@ -87,6 +89,14 @@ public final class GridState {
         devState.displayListIndex = newValue;
     }
 
+    public GridPalette getPalette() {
+        return palette == null ? GridColorUtils.getDefaultPalette() : palette;
+    }
+
+    public void setPalette(GridPalette palette) {
+        this.palette = palette;
+    }
+
     public void init(REnvironment gridEnv) {
         this.gridEnv = gridEnv;
         this.currentGrob = RNull.instance;
@@ -153,6 +163,28 @@ public final class GridState {
         return devState.scale;
     }
 
+    public static final class GridPalette {
+        public final GridColor[] colors;
+        public final String[] colorNames;
+
+        public GridPalette(String[] colorNames) {
+            this.colorNames = colorNames;
+            colors = new GridColor[colorNames.length];
+            for (int i = 0; i < colorNames.length; i++) {
+                colors[i] = GridColorUtils.gridColorFromString(colorNames[i]);
+            }
+        }
+
+        public GridPalette(int[] colors) {
+            this.colors = new GridColor[colors.length];
+            colorNames = new String[colors.length];
+            for (int i = 0; i < colors.length; i++) {
+                this.colors[i] = GridColor.fromRawValue(colors[i]);
+                colorNames[i] = GridColorUtils.gridColorToRString(this.colors[i]);
+            }
+        }
+    }
+
     static final class GridDeviceState {
         private boolean isDeviceInitialized = false;
         private RList gpar;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
index 284a98450523ea60c5e2c57de3a91fd81070ab25..e88b9cf5a61311e6d7e7e7d1a013a1a2ff686476 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java
@@ -15,6 +15,8 @@ import static com.oracle.truffle.r.runtime.nmath.RMath.fmax2;
 import static com.oracle.truffle.r.runtime.nmath.RMath.fmin2;
 
 import com.oracle.truffle.api.nodes.ExplodeLoop;
+import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.data.RAttributable;
@@ -40,6 +42,16 @@ final class GridUtils {
         return coord - size * justification;
     }
 
+    static double getStringWidth(DrawingContext drawingContext, GridDevice dev, String str) {
+        String[] lines;
+        double result = 0;
+        lines = str.split("\n");
+        for (String line : lines) {
+            result = Math.max(result, dev.getStringWidth(drawingContext, line));
+        }
+        return result;
+    }
+
     /**
      * Returns the amount of justification required. I.e. transforms the justification from value
      * between 0 and 1 to the value within size.
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LStringMetric.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LStringMetric.java
new file mode 100644
index 0000000000000000000000000000000000000000..c4fb977c581e268f818ed9542aa4c051b360b06c
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LStringMetric.java
@@ -0,0 +1,76 @@
+/*
+ * 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.library.fastrGrid;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
+
+import java.util.Arrays;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+
+/**
+ * Returns a list with string's width, ascent and descent all in inches.
+ */
+public abstract class LStringMetric extends RExternalBuiltinNode.Arg1 {
+    static {
+        Casts casts = new Casts(LStringMetric.class);
+        casts.arg(0).mustBe(stringValue()).asStringVector();
+    }
+
+    public static LStringMetric create() {
+        return LStringMetricNodeGen.create();
+    }
+
+    @Specialization
+    @TruffleBoundary
+    public Object execute(RAbstractStringVector text) {
+        int len = text.getLength();
+
+        // Needs to be determined if ascent/descent are actually used by anyone without knowing the
+        // actual string height
+        double[] ascent = new double[len];
+        double[] descent = new double[len];
+        Arrays.fill(ascent, 0.);
+        Arrays.fill(descent, 0.);
+
+        GridContext ctx = GridContext.getContext();
+        GridDevice dev = ctx.getCurrentDevice();
+        GPar gpar = GPar.create(ctx.getGridState().getGpar());
+        double[] width = new double[len];
+        for (int i = 0; i < text.getLength(); i++) {
+            width[i] = GridUtils.getStringWidth(gpar.getDrawingContext(i), dev, text.getDataAt(i));
+        }
+
+        return RDataFactory.createList(new Object[]{asVec(ascent), asVec(descent), asVec(width)});
+    }
+
+    private static RAbstractDoubleVector asVec(double[] data) {
+        return RDataFactory.createDoubleVector(data, RDataFactory.COMPLETE_VECTOR);
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/PaletteExternals.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/PaletteExternals.java
new file mode 100644
index 0000000000000000000000000000000000000000..67646f37e38032e5de2d49ee72515a1d44ed6aa1
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/PaletteExternals.java
@@ -0,0 +1,121 @@
+/*
+ * 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) 1997-2014, The R Core Team
+ * Copyright (c) 2003, The R Foundation
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.library.fastrGrid.GridState.GridPalette;
+import com.oracle.truffle.r.library.fastrGrid.PaletteExternalsFactory.CPalette2NodeGen;
+import com.oracle.truffle.r.library.fastrGrid.PaletteExternalsFactory.CPaletteNodeGen;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RIntVector;
+import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+
+public final class PaletteExternals {
+    private PaletteExternals() {
+        // only static members
+    }
+
+    /**
+     * Implements external {@code C_palette} used in palette R function.
+     */
+    public abstract static class CPalette extends RExternalBuiltinNode.Arg1 {
+
+        static {
+            Casts casts = new Casts(CPalette.class);
+            casts.arg(0).mustBe(stringValue());
+        }
+
+        public static CPalette create() {
+            return CPaletteNodeGen.create();
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public RStringVector updatePalette(RAbstractStringVector palette) {
+            GridState state = GridContext.getContext().getGridState();
+            GridPalette newPalette = null;
+            if (palette.getLength() == 1) {
+                if (palette.getDataAt(0).toLowerCase().equals("default")) {
+                    newPalette = GridColorUtils.getDefaultPalette();
+                } else {
+                    throw error(Message.GENERIC, "unknown palette (need >= 2 colors)");
+                }
+            } else if (palette.getLength() > 1) {
+                newPalette = new GridPalette(palette.materialize().getDataCopy());
+            }
+
+            String[] original = state.getPalette().colorNames;
+            if (newPalette != null) {
+                // the contract is that if the argument's length is zero, we only return the palette
+                // and
+                // do not set anything.
+                state.setPalette(newPalette);
+            }
+            // don't know the completeness, assume the worst rather than finding out
+            RStringVector result = RDataFactory.createStringVector(original, RDataFactory.INCOMPLETE_VECTOR);
+            result.makeSharedPermanent();
+            return result;
+        }
+    }
+
+    /**
+     * Implements external {@code C_palette2} used only internally in grDevices, the parameter are
+     * colors encoded in integer already.
+     */
+    public abstract static class CPalette2 extends RExternalBuiltinNode.Arg1 {
+        static {
+            Casts casts = new Casts(CPalette2.class);
+            casts.arg(0).mustBe(abstractVectorValue());
+        }
+
+        public static CPalette2 create() {
+            return CPalette2NodeGen.create();
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public RIntVector updatePalette(RAbstractVector palette) {
+            GridState state = GridContext.getContext().getGridState();
+            int[] newPalette = null;
+            if (palette.getLength() > 0) {
+                RAbstractIntVector data = GridUtils.asIntVector(palette);
+                newPalette = data.materialize().getDataCopy();
+            }
+            RIntVector result = getResult(state);
+            if (newPalette != null) {
+                state.setPalette(new GridPalette(newPalette));
+            }
+            return result;
+        }
+
+        private static RIntVector getResult(GridState state) {
+            GridPalette palette = state.getPalette();
+            int[] result = new int[palette.colors.length];
+            boolean complete = true;
+            for (int i = 0; i < result.length; i++) {
+                result[i] = palette.colors[i].getRawValue();
+                complete &= !RRuntime.isNA(result[i]);
+            }
+            return RDataFactory.createIntVector(result, complete);
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
index 1d6405efaf78e1942d91018099ea19e6c5df9c42..23a7f92db67eb6c30eff8b842730e90b8bbf7ab7 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java
@@ -213,11 +213,7 @@ public final class Unit {
             case STRINGWIDTH:
             case MYSTRINGWIDTH:
                 str = RRuntime.asString(data.getDataAt(0));
-                lines = str.split("\n");
-                for (String line1 : lines) {
-                    result = Math.max(result, ctx.device.getStringWidth(ctx.gpar.getDrawingContext(index), line1));
-                }
-                return value * result;
+                return value * GridUtils.getStringWidth(ctx.gpar.getDrawingContext(index), ctx.device, str);
             case STRINGHEIGHT:
             case MYSTRINGHEIGHT:
                 str = RRuntime.asString(data.getDataAt(0));
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridColor.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridColor.java
index 28abf944f1eae6088260398ccf7c9103c7118733..ec11023ea1248c6471f9a92947c56543c8f91882 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridColor.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridColor.java
@@ -33,6 +33,10 @@ public final class GridColor {
 
     private final int value;
 
+    private GridColor(int value) {
+        this.value = value;
+    }
+
     public GridColor(int red, int green, int blue, int alpha) {
         value = ((alpha & 0xFF) << 24) |
                         ((red & 0xFF) << 16) |
@@ -40,6 +44,10 @@ public final class GridColor {
                         (blue & 0xFF);
     }
 
+    public static GridColor fromRawValue(int value) {
+        return new GridColor(value);
+    }
+
     public int getRed() {
         return (value >> 16) & 0xFF;
     }
@@ -56,6 +64,10 @@ public final class GridColor {
         return (value >> 24) & 0xff;
     }
 
+    public int getRawValue() {
+        return value;
+    }
+
     @Override
     public boolean equals(Object obj) {
         return obj instanceof GridColor && value == ((GridColor) obj).value;
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Rdynload_fastr.c b/com.oracle.truffle.r.native/fficall/src/jni/Rdynload_fastr.c
index ebf731f63f9664d3921bba9ba643b1af4c6206d0..88a5b6e9b3ba8e93b958ce16d0e495bf87d60b1d 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Rdynload_fastr.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Rdynload_fastr.c
@@ -22,6 +22,7 @@ static jclass RegisteredNativeSymbolClass;
 
 static jmethodID registerRoutinesID;
 static jmethodID registerCCallableID;
+static jmethodID getCCallableID;
 static jmethodID useDynamicSymbolsID;
 static jmethodID forceSymbolsID;
 static jmethodID setDotSymbolValuesID;
@@ -36,6 +37,7 @@ void init_dynload(JNIEnv *env) {
 
     registerRoutinesID = checkGetMethodID(env, JNI_PkgInitClass, "registerRoutines", "(Lcom/oracle/truffle/r/runtime/ffi/DLL$DLLInfo;IIJ)V", 1);
     registerCCallableID = checkGetMethodID(env, JNI_PkgInitClass, "registerCCallable", "(Ljava/lang/String;Ljava/lang/String;J)V", 1);
+    getCCallableID = checkGetMethodID(env, JNI_PkgInitClass, "getCCallable", "(Ljava/lang/String;Ljava/lang/String;)J", 1);
     useDynamicSymbolsID = checkGetMethodID(env, JNI_PkgInitClass, "useDynamicSymbols", "(Lcom/oracle/truffle/r/runtime/ffi/DLL$DLLInfo;I)I", 1);
     forceSymbolsID = checkGetMethodID(env, JNI_PkgInitClass, "forceSymbols", "(Lcom/oracle/truffle/r/runtime/ffi/DLL$DLLInfo;I)I", 1);
     setDotSymbolValuesID = checkGetMethodID(env, JNI_PkgInitClass, "setDotSymbolValues", "(Ljava/lang/String;JI)Lcom/oracle/truffle/r/runtime/ffi/DLL$DotSymbol;", 1);
@@ -139,8 +141,10 @@ Rboolean R_forceSymbols(DllInfo *dllInfo, Rboolean value) {
 }
 
 DL_FUNC R_GetCCallable(const char *package, const char *name) {
-	unimplemented("R_GetCCallable");
-	return NULL;
+    JNIEnv *thisenv = getEnv();
+    jstring packageString = (*thisenv)->NewStringUTF(thisenv, package);
+    jstring nameString = (*thisenv)->NewStringUTF(thisenv, name);
+    return (DL_FUNC) (*thisenv)->CallStaticObjectMethod(thisenv, JNI_PkgInitClass, getCCallableID, packageString, nameString);
 }
 
 DL_FUNC R_FindSymbol(char const *name, char const *pkg,
diff --git a/com.oracle.truffle.r.native/version.source b/com.oracle.truffle.r.native/version.source
index 2bd5a0a98a36cc08ada88b804d3be047e6aa5b8a..409940768f2a684935a7d15a29f96e82c487f439 100644
--- a/com.oracle.truffle.r.native/version.source
+++ b/com.oracle.truffle.r.native/version.source
@@ -1 +1 @@
-22
+23
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java
index f76be777345451de573b7888e29b873a5e3065d9..ece1e6e7b936fc80923e638d3442b69f5492dd5d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java
@@ -74,7 +74,7 @@ public abstract class AsCharacter extends RBuiltinNode.Arg2 {
             } else if (elem instanceof RStringVector && ((RStringVector) elem).getLength() == 1) {
                 data[i] = ((RStringVector) elem).getDataAt(0);
             } else {
-                data[i] = RDeparse.deparse(elem, RDeparse.MAX_Cutoff, true, RDeparse.SIMPLEDEPARSE, -1);
+                data[i] = RDeparse.deparse(elem, RDeparse.MAX_CUTOFF, true, RDeparse.SIMPLEDEPARSE, -1);
             }
             if (RRuntime.isNA(data[i])) {
                 complete = RDataFactory.INCOMPLETE_VECTOR;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attr.java
index e746de2a76368f54daa0461ad94e6659a1f0cfd7..fab198672dd600476fc59d33672bfe909ac5b20b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attr.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attr.java
@@ -32,6 +32,7 @@ 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.interop.TruffleObject;
 import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.GetAttributeNode;
@@ -48,6 +49,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RAttributesLayout;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
@@ -136,6 +138,8 @@ public abstract class Attr extends RBuiltinNode.Arg3 {
     protected Object attr(Object object, Object name, Object exact) {
         if (object instanceof RAttributable) {
             return attrRA((RAttributable) object, intern.execute((String) name), (boolean) exact);
+        } else if (RRuntime.isForeignObject(object)) {
+            throw RError.error(this, Message.OBJ_CANNOT_BE_ATTRIBUTED);
         } else {
             throw RError.nyi(this, "object cannot be attributed");
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attributes.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attributes.java
index c2e894809ced2e2442a1f0f9cb861a4604d390d7..5f3aee4e78d586e8754665ea9e0e3f6a480975a3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attributes.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attributes.java
@@ -84,7 +84,7 @@ public abstract class Attributes extends RBuiltinNode.Arg1 {
             } else {
                 return createResult((RAttributable) object, false);
             }
-        } else if (object == RNull.instance) {
+        } else if (object == RNull.instance || RRuntime.isForeignObject(object)) {
             return RNull.instance;
         } else {
             throw RError.nyi(this, "object cannot be attributed");
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 c30232bc10d3b97eb4bb95c78daf7a29c4dfcc8e..2bf4e37ed7d34b898ab99c5a2c8da89f5987f94c 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
@@ -102,6 +102,8 @@ import com.oracle.truffle.r.nodes.builtin.fastr.FastRRefCountInfo;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRRefCountInfoNodeGen;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRSlotAssign;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRSlotAssignNodeGen;
+import com.oracle.truffle.r.nodes.builtin.fastr.FastRSourceInfo;
+import com.oracle.truffle.r.nodes.builtin.fastr.FastRSourceInfoNodeGen;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRStackTrace;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRStackTraceNodeGen;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRStats.FastRProfAttr;
@@ -391,6 +393,7 @@ public class BasePackage extends RBuiltinPackage {
         add(FastRInterop.ToShort.class, FastRInteropFactory.ToShortNodeGen::create);
         add(FastRRefCountInfo.class, FastRRefCountInfoNodeGen::create);
         add(FastRPkgSource.class, FastRPkgSourceNodeGen::create);
+        add(FastRSourceInfo.class, FastRSourceInfoNodeGen::create);
         add(FastRStackTrace.class, FastRStackTraceNodeGen::create);
         add(FastRProfAttr.class, FastRStatsFactory.FastRProfAttrNodeGen::create);
         add(FastRProfTypecounts.class, FastRStatsFactory.FastRProfTypecountsNodeGen::create);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DPut.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DPut.java
index d0361a493fd9fba3da09709a9e967e9334354574..13f43b742006fdade1fcc006389fc993d931ed34 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DPut.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DPut.java
@@ -52,7 +52,7 @@ public abstract class DPut extends RBuiltinNode.Arg3 {
     @Specialization
     @TruffleBoundary
     protected Object dput(Object x, int file, int opts) {
-        String string = RDeparse.deparse(x, RDeparse.DEFAULT_Cutoff, true, opts, -1);
+        String string = RDeparse.deparse(x, RDeparse.DEFAULT_CUTOFF, true, opts, -1);
         try (RConnection openConn = RConnection.fromIndex(file).forceOpen("wt")) {
             openConn.writeString(string, true);
         } catch (IOException ex) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Deparse.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Deparse.java
index fdd7a26615bc8c8b22a40276dca4f24dcdb20cc5..a258e75f8ed951e14f99225759e4f55a1e34de67 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Deparse.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Deparse.java
@@ -42,9 +42,9 @@ public abstract class Deparse extends RBuiltinNode.Arg5 {
     @TruffleBoundary
     protected RStringVector deparse(Object expr, int widthCutoffArg, boolean backtick, int control, int nlines) {
         int widthCutoff = widthCutoffArg;
-        if (widthCutoff == RRuntime.INT_NA || widthCutoff < RDeparse.MIN_Cutoff || widthCutoff > RDeparse.MAX_Cutoff) {
+        if (widthCutoff == RRuntime.INT_NA || widthCutoff < RDeparse.MIN_CUTOFF || widthCutoff > RDeparse.MAX_CUTOFF) {
             warning(RError.Message.DEPARSE_INVALID_CUTOFF);
-            widthCutoff = RDeparse.DEFAULT_Cutoff;
+            widthCutoff = RDeparse.DEFAULT_CUTOFF;
         }
 
         String[] data = RDeparse.deparse(expr, widthCutoff, backtick, control, nlines).split("\n");
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java
index a05fba7d0a78b52737beb2200532f51fb97e55e3..ef414d42b61e114ba26cc3a4c5960b2a0bf0aa56 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java
@@ -66,9 +66,11 @@ import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RS4Object;
+import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
@@ -316,6 +318,8 @@ public class GetFunctions {
 
         @Specialization
         protected RList mget(VirtualFrame frame, RAbstractStringVector xv, REnvironment envir, RAbstractStringVector mode, RList ifNotFound, boolean inherits,
+                        @Cached("createBinaryProfile()") ConditionProfile argsAndValuesProfile,
+                        @Cached("createBinaryProfile()") ConditionProfile missingProfile,
                         @Cached("createBinaryProfile()") ConditionProfile inheritsProfile) {
             State state = checkArgs(xv, mode, ifNotFound);
             for (int i = 0; i < state.svLength; i++) {
@@ -330,7 +334,7 @@ public class GetFunctions {
                         while (env != REnvironment.emptyEnv()) {
                             env = env.getParent();
                             if (env != REnvironment.emptyEnv()) {
-                                r = helper.checkPromise(frame, env.get(x), x);
+                                r = handleMissingAndVarargs(helper.checkPromise(frame, env.get(x), x), argsAndValuesProfile, missingProfile);
                                 if (r != null && RRuntime.checkType(r, modeType)) {
                                     break;
                                 }
@@ -343,7 +347,7 @@ public class GetFunctions {
                         state.data[i] = r;
                     }
                 } else {
-                    Object r = helper.checkPromise(frame, envir.get(x), x);
+                    Object r = handleMissingAndVarargs(helper.checkPromise(frame, envir.get(x), x), argsAndValuesProfile, missingProfile);
                     if (r != null && RRuntime.checkType(r, modeType)) {
                         state.data[i] = r;
                     } else {
@@ -356,9 +360,11 @@ public class GetFunctions {
 
         @Specialization
         protected RList mget(VirtualFrame frame, RAbstractStringVector xv, RS4Object s4Envir, RAbstractStringVector mode, RList ifNotFound, boolean inherits,
+                        @Cached("createBinaryProfile()") ConditionProfile argsAndValuesProfile,
+                        @Cached("createBinaryProfile()") ConditionProfile missingProfile,
                         @Cached("createBinaryProfile()") ConditionProfile inheritsProfile,
                         @Cached("new()") S4ToEnvNode s4ToEnv) {
-            return mget(frame, xv, (REnvironment) s4ToEnv.execute(s4Envir), mode, ifNotFound, inherits, inheritsProfile);
+            return mget(frame, xv, (REnvironment) s4ToEnv.execute(s4Envir), mode, ifNotFound, inherits, argsAndValuesProfile, missingProfile, inheritsProfile);
         }
 
         private void doIfNotFound(VirtualFrame frame, State state, int i, String x, RList ifNotFound) {
@@ -380,5 +386,20 @@ public class GetFunctions {
             return callCache.execute(frame, ifnFunc, RCaller.create(frame, RCallerHelper.createFromArguments(ifnFunc, args)), callerFrame, new Object[]{x}, formals.getSignature(),
                             ifnFunc.getEnclosingFrame(), null);
         }
+
+        private static Object handleMissingAndVarargs(Object value, ConditionProfile argsAndValuesProfile, ConditionProfile missingProfile) {
+            if (argsAndValuesProfile.profile(value instanceof RArgsValuesAndNames)) {
+                if (((RArgsValuesAndNames) value).getLength() == 0) {
+                    return RSymbol.MISSING;
+                } else {
+                    // GNUR also puts raw promises in the list
+                    return RDataFactory.createList(((RArgsValuesAndNames) value).getArguments());
+                }
+            }
+            if (missingProfile.profile(value == RMissing.instance)) {
+                return RSymbol.MISSING;
+            }
+            return value;
+        }
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Split.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Split.java
index 8a5446c3d6af500002450e0b5686860bd2c4f872..f309975878a3af3f16c66c8e2a099601b24bb498 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Split.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Split.java
@@ -35,9 +35,11 @@ import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RRawVector;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
@@ -47,6 +49,9 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
  *
  * TODO Can we find a way to efficiently write the specializations as generics? The code is
  * identical except for the argument type.
+ *
+ * TODO: GNU R preserves the corresponding values of names attribute. There are (ignored) tests for
+ * this in TestBuiltin_split.
  */
 @RBuiltin(name = "split", kind = INTERNAL, parameterNames = {"x", "f"}, behavior = PURE)
 public abstract class Split extends RBuiltinNode.Arg2 {
@@ -62,9 +67,37 @@ public abstract class Split extends RBuiltinNode.Arg2 {
         Casts.noCasts(Split.class);
     }
 
-    public static class SplitTemplate {
-        @SuppressWarnings("unused") private int[] collectResultsSize;
-        @SuppressWarnings("unused") private int nLevels;
+    @Specialization
+    protected RList split(RAbstractListVector x, RAbstractIntVector f) {
+        int[] factor = f.materialize().getDataWithoutCopying();
+        RStringVector names = getLevelNode.execute(f);
+        final int nLevels = getNLevels(names);
+
+        // initialise result arrays
+        Object[][] collectResults = new Object[nLevels][];
+        int[] collectResultSize = new int[nLevels];
+        for (int i = 0; i < collectResults.length; i++) {
+            collectResults[i] = new Object[INITIAL_SIZE];
+        }
+
+        // perform split
+        for (int i = 0, fi = 0; i < x.getLength(); ++i, fi = Utils.incMod(fi, factor.length)) {
+            int resultIndex = factor[fi] - 1; // a factor is a 1-based int vector
+            Object[] collect = collectResults[resultIndex];
+            if (collect.length == collectResultSize[resultIndex]) {
+                collectResults[resultIndex] = Arrays.copyOf(collect, collect.length * SCALE_FACTOR);
+                collect = collectResults[resultIndex];
+            }
+            collect[collectResultSize[resultIndex]++] = x.getDataAt(i);
+        }
+
+        // assemble result vectors and level names
+        Object[] results = new Object[nLevels];
+        for (int i = 0; i < nLevels; i++) {
+            results[i] = RDataFactory.createList(Arrays.copyOfRange(collectResults[i], 0, collectResultSize[i]));
+        }
+
+        return RDataFactory.createList(results, names);
     }
 
     @Specialization
@@ -199,6 +232,39 @@ public abstract class Split extends RBuiltinNode.Arg2 {
         return RDataFactory.createList(results, names);
     }
 
+    @Specialization
+    protected RList split(RRawVector x, RAbstractIntVector f) {
+        int[] factor = f.materialize().getDataWithoutCopying();
+        RStringVector names = getLevelNode.execute(f);
+        final int nLevels = getNLevels(names);
+
+        // initialise result arrays
+        byte[][] collectResults = new byte[nLevels][];
+        int[] collectResultSize = new int[nLevels];
+        for (int i = 0; i < collectResults.length; i++) {
+            collectResults[i] = new byte[INITIAL_SIZE];
+        }
+
+        // perform split
+        for (int i = 0, fi = 0; i < x.getLength(); ++i, fi = Utils.incMod(fi, factor.length)) {
+            int resultIndex = factor[fi] - 1; // a factor is a 1-based int vector
+            byte[] collect = collectResults[resultIndex];
+            if (collect.length == collectResultSize[resultIndex]) {
+                collectResults[resultIndex] = Arrays.copyOf(collect, collect.length * SCALE_FACTOR);
+                collect = collectResults[resultIndex];
+            }
+            collect[collectResultSize[resultIndex]++] = x.getDataAt(i).getValue();
+        }
+
+        // assemble result vectors and level names
+        Object[] results = new Object[nLevels];
+        for (int i = 0; i < nLevels; i++) {
+            results[i] = RDataFactory.createRawVector(Arrays.copyOfRange(collectResults[i], 0, collectResultSize[i]));
+        }
+
+        return RDataFactory.createList(results, names);
+    }
+
     private static int getNLevels(RStringVector levels) {
         return levels != null ? levels.getLength() : 0;
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
index 1b8e654595860dd72bb9c1a41276a552536ace64..50fce23643fd2166344fa2b9128ea88834da9480 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
@@ -32,6 +32,7 @@ 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.interop.TruffleObject;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.nodes.attributes.RemoveAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SetAttributeNode;
@@ -47,6 +48,7 @@ import com.oracle.truffle.r.nodes.unary.CastToVectorNode;
 import com.oracle.truffle.r.nodes.unary.CastToVectorNodeGen;
 import com.oracle.truffle.r.nodes.unary.GetNonSharedNode;
 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.RBuiltin;
@@ -243,6 +245,8 @@ public abstract class UpdateAttr extends RBuiltinNode.Arg3 {
                 attributable.setAttr(internedName, value);
             }
             return object;
+        } else if (RRuntime.isForeignObject(obj)) {
+            throw RError.error(this, Message.OBJ_CANNOT_BE_ATTRIBUTED);
         } else {
             throw RError.nyi(this, "object cannot be attributed");
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LanguagePrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LanguagePrinter.java
index 82ddd8f26ff0f5bda65d6705a7185f065090e358..bc050bed9d46661b295b32889e4b192304e8daa8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LanguagePrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LanguagePrinter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,6 +39,6 @@ final class LanguagePrinter extends AbstractValuePrinter<RLanguage> {
     @Override
     @TruffleBoundary
     protected void printValue(RLanguage language, PrintContext printCtx) throws IOException {
-        printCtx.output().print(RDeparse.deparse(language, RDeparse.DEFAULT_Cutoff, true, RDeparse.KEEPINTEGER, -1));
+        printCtx.output().print(RDeparse.deparse(language, RDeparse.DEFAULT_CUTOFF, true, RDeparse.KEEPINTEGER, -1));
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/SymbolPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/SymbolPrinter.java
index 19451dfcbf5e7dc936254d14ef4d57b7af44566e..0bf416f5573f48cfaec6cfc6e328d1531e4f90a1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/SymbolPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/SymbolPrinter.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,6 +39,6 @@ final class SymbolPrinter extends AbstractValuePrinter<RSymbol> {
     @Override
     @TruffleBoundary
     protected void printValue(RSymbol value, PrintContext printCtx) throws IOException {
-        printCtx.output().print(RDeparse.deparse(value, RDeparse.DEFAULT_Cutoff, true, RDeparse.SIMPLEDEPARSE, -1));
+        printCtx.output().print(RDeparse.deparse(value, RDeparse.DEFAULT_CUTOFF, true, RDeparse.SIMPLEDEPARSE, -1));
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java
index 6beeea072ece55a1284ae5c7f54a4f8d4131a51b..662a227111f22dc328e300f21616f61edfd10dae 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinterNode.java
@@ -101,7 +101,6 @@ public final class ValuePrinterNode extends RBaseNode {
         @Child private Node unboxNode = com.oracle.truffle.api.interop.Message.UNBOX.createNode();
         @Child private Node keysNode = com.oracle.truffle.api.interop.Message.KEYS.createNode();
         @Child private SetFixedAttributeNode namesAttrSetter = SetFixedAttributeNode.createNames();
-        @Child private SetFixedAttributeNode isTruffleObjAttrSetter = SetFixedAttributeNode.create("is.truffle.object");
 
         @TruffleBoundary
         public Object convert(TruffleObject obj) {
@@ -303,7 +302,6 @@ public final class ValuePrinterNode extends RBaseNode {
                             super(length);
                             DynamicObject attrs = RAttributesLayout.createNames(names);
                             initAttributes(attrs);
-                            isTruffleObjAttrSetter.execute(attrs, RRuntime.LOGICAL_TRUE);
                         }
 
                         @Override
@@ -377,32 +375,47 @@ public final class ValuePrinterNode extends RBaseNode {
     }
 
     private Object convertTruffleObject(Object o) {
-        if (o instanceof TruffleObject && !(o instanceof RTypedValue)) {
+        if (RRuntime.isForeignObject(o)) {
             if (convertTruffleObject == null) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
                 convertTruffleObject = insert(new ConvertTruffleObjectNode());
             }
             return convertTruffleObject.convert((TruffleObject) o);
         }
-        return o;
+        return null;
     }
 
     public String execute(Object o, Object digits, boolean quote, Object naPrint, Object printGap, boolean right, Object max, boolean useSource, boolean noOpt) {
         try {
-            prettyPrint(convertTruffleObject(o), new PrintParameters(digits, quote, naPrint, printGap, right, max, useSource, noOpt), RWriter::new);
+            PrintParameters printParams = new PrintParameters(digits, quote, naPrint, printGap, right, max, useSource, noOpt);
+
+            PrintContext printCtx = PrintContext.enter(this, printParams, RWriter::new);
+            try {
+                prettyPrint(o, printCtx);
+                Object foreignObjectWrapper = convertTruffleObject(o);
+                if (foreignObjectWrapper != null) {
+                    prettyPrint(foreignObjectWrapper, printCtx);
+                }
+            } finally {
+                PrintContext.leave();
+            }
             return null;
         } catch (IOException ex) {
             throw RError.ioError(this, ex);
         }
     }
 
+    @TruffleBoundary
+    private static void prettyPrint(Object o, PrintContext printCtx) throws IOException {
+        ValuePrinters.INSTANCE.print(o, printCtx);
+        ValuePrinters.printNewLine(printCtx);
+    }
+
     private abstract static class TruffleObjectWrapper extends RAttributeStorage implements RAbstractVector {
 
         private final int length;
 
         TruffleObjectWrapper(int length) {
-            initAttributes().define("is.truffle.object", RRuntime.LOGICAL_TRUE);
-
             this.length = length;
         }
 
@@ -548,22 +561,6 @@ public final class ValuePrinterNode extends RBaseNode {
         }
     }
 
-    private String prettyPrint(Object o, PrintParameters printParams, WriterFactory wf) throws IOException {
-        PrintContext printCtx = PrintContext.enter(this, printParams, wf);
-        try {
-            prettyPrint(o, printCtx);
-            return null;
-        } finally {
-            PrintContext.leave();
-        }
-    }
-
-    @TruffleBoundary
-    private static void prettyPrint(Object o, PrintContext printCtx) throws IOException {
-        ValuePrinters.INSTANCE.print(o, printCtx);
-        ValuePrinters.printNewLine(printCtx);
-    }
-
     @SuppressWarnings("deprecation")
     public static String prettyPrint(final Object value) {
         return (String) Truffle.getRuntime().createCallTarget(new RootNode(TruffleLanguage.class, null, null) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java
index c59f4dbc43c325a0046106d0e04140d1123b77f4..3594b6ceaaeb548248103ca47531d29805e995b6 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java
@@ -98,7 +98,7 @@ public class FastRContext {
     private static void handleSharedContexts(ContextKind contextKind) {
         if (contextKind == ContextKind.SHARE_ALL) {
             RContext current = RContext.getInstance();
-            if (EvalThread.threads.size() == 0 && (current.isInitial() || current.getKind() == ContextKind.SHARE_PARENT_RW)) {
+            if (EvalThread.threadCnt.get() == 0 && (current.isInitial() || current.getKind() == ContextKind.SHARE_PARENT_RW)) {
                 ContextInfo.resetMultiSlotIndexGenerator();
             } else {
                 throw RError.error(RError.NO_CALLER, RError.Message.GENERIC, "Shared contexts can be created only if no other child contexts exist");
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSourceInfo.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSourceInfo.java
new file mode 100644
index 0000000000000000000000000000000000000000..ed3430a7b325f4ad1d1f6abd39ecc8fb61e57102
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRSourceInfo.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.nodes.builtin.fastr;
+
+import static com.oracle.truffle.r.runtime.RVisibility.ON;
+import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
+
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.source.SourceSection;
+import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.runtime.builtins.RBehavior;
+import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.data.RNull;
+
+/**
+ * Allows to show the actual location of the source section of a provided function.
+ */
+@RBuiltin(name = ".fastr.srcinfo", visibility = ON, kind = PRIMITIVE, parameterNames = "fun", behavior = RBehavior.IO)
+public abstract class FastRSourceInfo extends RBuiltinNode.Arg1 {
+
+    static {
+        Casts.noCasts(FastRSourceInfo.class);
+    }
+
+    @Specialization
+    public Object srcInfo(@SuppressWarnings("unused") RNull fun) {
+        return RNull.instance;
+    }
+
+    @Specialization
+    public Object srcInfo(RFunction fun) {
+        SourceSection ss = fun.getRootNode().getSourceSection();
+        if (ss != null) {
+            String path = ss.getSource().getPath();
+            if (path != null) {
+                return path + "#" + ss.getStartLine();
+            } else {
+                return ss.getSource().getName();
+            }
+        }
+        return RNull.instance;
+    }
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java
index 75684febae6ee8df37d7d1fd758169b6a918569f..b50be670aff64e6194a116cffdf175381e241629 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/DebugHandling.java
@@ -598,11 +598,14 @@ public class DebugHandling {
         public void onEnter(EventContext context, VirtualFrame frame) {
             if (!RContext.getInstance().stateInstrumentation.debugGloballyDisabled()) {
                 CompilerDirectives.transferToInterpreter();
-                FunctionDefinitionNode fdn = (FunctionDefinitionNode) context.getInstrumentedNode().getRootNode();
-                FunctionStatementsEventListener ensureSingleStep = ensureSingleStep(fdn);
+                RootNode rootNode = context.getInstrumentedNode().getRootNode();
+                if (rootNode instanceof FunctionDefinitionNode) {
+                    FunctionDefinitionNode fdn = (FunctionDefinitionNode) rootNode;
+                    FunctionStatementsEventListener ensureSingleStep = ensureSingleStep(fdn);
 
-                functionStatementsEventListener.clearStepInstrument();
-                ensureSingleStep.onEnter(context, frame);
+                    functionStatementsEventListener.clearStepInstrument();
+                    ensureSingleStep.onEnter(context, frame);
+                }
             }
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/parallel/R/forkcluster_overrides.R b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/parallel/R/forkcluster_overrides.R
index 2d3ebf6b49a58ea052b43953b3c3e1c47aaaad39..02940b6a2aa6d27bf3fc7b34d79558e58f26a8c3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/parallel/R/forkcluster_overrides.R
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/parallel/R/forkcluster_overrides.R
@@ -111,4 +111,10 @@ stopCluster.SHAREDcluster <- function(cl) {
     }
 }
 
+## manually register S3 generic methods
+registerS3method("closeNode", "SHAREDnode", closeNode.SHAREDnode) 
+registerS3method("sendData", "SHAREDnode", sendData.SHAREDnode) 
+registerS3method("recvData", "SHAREDnode", recvData.SHAREDnode) 
+registerS3method("recvOneData", "SHAREDcluster", recvOneData.SHAREDcluster) 
+registerS3method("stopCluster", "SHAREDcluster", stopCluster.SHAREDcluster) 
 }), asNamespace("parallel"))
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java
index 1f317668577066be9db826c1ae0ee1dce1e65fa2..0a8d63ec7ed252318654e764ef1e79573fbcfcf3 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java
@@ -150,7 +150,7 @@ public abstract class BinaryBooleanNode extends RBuiltinNode.Arg2 {
     }
 
     private static RString deparseSymbolOrLang(Object val) {
-        return RString.valueOf(RDeparse.deparse(val, RDeparse.MAX_Cutoff, false, RDeparse.KEEPINTEGER, -1));
+        return RString.valueOf(RDeparse.deparse(val, RDeparse.MAX_CUTOFF, false, RDeparse.KEEPINTEGER, -1));
     }
 
     protected BinaryBooleanNode createRecursive() {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java
index 92e4c8dfa0d50926b61d8bc4fb57cf5097917278..7c2fefce91fa49c3feb87db49592190fa9eebbde 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java
@@ -672,7 +672,7 @@ public class ArgumentMatcher {
         assert suppliedName != null && !suppliedName.isEmpty();
         for (int i = 0; i < formalsSignature.getLength(); i++) {
             String formalName = formalsSignature.getName(i);
-            if (formalName != null) {
+            if (!formalsSignature.isVarArg(i) && formalName != null) {
                 if (formalName.equals(suppliedName)) {
                     if (resultPermutation[i] != MatchPermutation.UNMATCHED) {
                         if (builtin != null && builtin.getKind() == RBuiltinKind.PRIMITIVE && hasVarArgs) {
diff --git a/com.oracle.truffle.r.pkgs/rJava/DESCRIPTION b/com.oracle.truffle.r.pkgs/rJava/DESCRIPTION
new file mode 100644
index 0000000000000000000000000000000000000000..22b6b722cc2bf4bf2c7ee8830d129ea8a50f8272
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/DESCRIPTION
@@ -0,0 +1,11 @@
+Package: rJava
+Type: Package
+Title: FastR rJava compatibility layer
+Version: 1.0
+Date: 2017-05-18
+Author: Tomas Stupka
+Maintainer: Tomas Stupka <tomas.stupka@oracle.com>
+Description: Provides rJava R interface backed by FastR interoperability builtins.
+License: GPL-2
+Suggests: testthat
+RoxygenNote: 6.0.1
diff --git a/com.oracle.truffle.r.pkgs/rJava/NAMESPACE b/com.oracle.truffle.r.pkgs/rJava/NAMESPACE
new file mode 100644
index 0000000000000000000000000000000000000000..20c27039014d4fc3a4125f92e4f5960410723234
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/NAMESPACE
@@ -0,0 +1,16 @@
+# Generated by roxygen2: do not edit by hand
+
+export(.jarray)
+export(.jbyte)
+export(.jcall)
+export(.jchar)
+export(.jcheck)
+export(.jevalArray)
+export(.jfield)
+export(.jfloat)
+export(.jinit)
+export(.jlong)
+export(.jnew)
+export(.jnull)
+export(.jshort)
+export(.jsimplify)
diff --git a/com.oracle.truffle.r.pkgs/rJava/R/rj.R b/com.oracle.truffle.r.pkgs/rJava/R/rj.R
new file mode 100644
index 0000000000000000000000000000000000000000..eb18a8713c1f47f2d7739a9fd41cf8bbbc28590d
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/R/rj.R
@@ -0,0 +1,119 @@
+##
+ # 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) 2006 Simon Urbanek <simon.urbanek@r-project.org>
+ # Copyright (c) 2017, Oracle and/or its affiliates
+ #
+ # All rights reserved.
+##
+
+#' @export
+.jnew <- function (class, ..., check = TRUE, silent = !check) 
+{
+    class <- gsub("/", ".", as.character(class))
+    co <- .fastr.java.class(class)
+    o <- .fastr.interop.new(co, ...)
+    invisible(o)
+}
+
+#' @export
+.jcall <- function (obj, returnSig = "V", method, ..., evalArray = TRUE, 
+    evalString = TRUE, check = TRUE, interface = "RcallMethod", 
+    simplify = FALSE, use.true.class = FALSE) 
+{
+    if(is.character(obj)) {
+        co <- .fastr.java.class(obj)
+        r <- co[method](...)
+    } else {
+        r <- obj[method](...)
+    }
+    r
+}
+
+#' @export
+.jfield <- function (obj, sig = NULL, name, true.class = is.null(sig), convert = TRUE) 
+{
+    if(is.character(obj)) {
+        co <- .fastr.java.class(obj)
+        r <- co[name]
+    } else {
+        r <- obj[name]
+    }
+    r    
+}
+
+#' @export
+.jarray <- function (x, contents.class = NULL, dispatch = FALSE) 
+{
+    .fastr.java.toArray(x, ,TRUE)
+}
+
+#' @export
+.jevalArray <- function (x, contents.class = NULL, dispatch = FALSE) 
+{
+    .fastr.java.fromArray(x)
+}
+
+#' @export
+.jbyte <- function (x) 
+{
+    x <- .fastr.interop.toByte(x)
+    invisible(x)
+}
+
+#' @export
+.jchar <- function (x) 
+{
+    x <- .fastr.interop.toChar(x)
+    invisible(x)
+}
+
+#' @export
+.jshort <- function (x) 
+{
+    x <- .fastr.interop.toShort(x)
+    invisible(x)
+}
+
+#' @export
+.jlong <- function (x) 
+{
+    x <- .fastr.interop.toLong(x)
+    invisible(x)
+}
+
+#' @export
+.jfloat <- function (x) 
+{    
+    x <- .fastr.interop.toFloat(x)
+    invisible(x)
+}
+
+#
+# noop stubs
+#
+
+#' @export
+.jinit <- function ()
+{    
+    # do nothing
+}
+
+#' @export
+.jsimplify <- function (x) 
+{    
+    x
+}
+
+#' @export
+.jcheck <- function(silent = FALSE) {
+    FALSE
+}
+
+#' @export
+.jnull <- function (class)
+{    
+    # do nothing
+}
diff --git a/com.oracle.truffle.r.pkgs/rJava/tests/testthat.R b/com.oracle.truffle.r.pkgs/rJava/tests/testthat.R
new file mode 100644
index 0000000000000000000000000000000000000000..46b38886ec61b333475eda982a77f68ac0bdd59a
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/tests/testthat.R
@@ -0,0 +1,5 @@
+library(testthat)
+library(rjava)
+
+test_check("rjava")
+typeName
\ No newline at end of file
diff --git a/com.oracle.truffle.r.pkgs/rJava/tests/testthat/testArrays.R b/com.oracle.truffle.r.pkgs/rJava/tests/testthat/testArrays.R
new file mode 100644
index 0000000000000000000000000000000000000000..d0581b43c8330e550bca70c78820096bfb5ad1ff
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/tests/testthat/testArrays.R
@@ -0,0 +1,102 @@
+# prerequisites:
+# - 'testthat' package has to be installed: install.packages("testthat")
+# - FastR`s rJava package has to be installed: bin/r CMD INSTALL com.oracle.truffle.r.pkgs/rjava
+# - mxbuild/dists/fastr-unit-tests.jar has to be on FastR classpath
+
+library(testthat)
+library(rJava)
+
+testName <- "test .jarray"
+test_that(testName, {
+    cat(paste0(testName, "\n"))
+	
+    a <- .jarray(c(1.1, 2.1, 3.1))
+    expect_true(.fastr.java.isArray(a))
+    expect_equal(length(a), 3)
+    expect_equal(a[1], c(1.1))
+    expect_equal(a[2], c(2.1))
+    expect_equal(a[3], c(3.1))
+
+    a <- .jarray(c(1L, 2L, 3L))
+    expect_true(.fastr.java.isArray(a))
+    expect_equal(length(a), 3)
+    expect_equal(a[1], c(1))
+    expect_equal(a[2], c(2))
+    expect_equal(a[3], c(3))
+
+    a <- .jarray(c(TRUE, FALSE))
+    expect_true(.fastr.java.isArray(a))
+    expect_equal(length(a), 2)
+    expect_equal(a[1], TRUE)
+    expect_equal(a[2], FALSE)
+
+    a <- .jarray(c(.jbyte(1), .jchar("a"), .jfloat(1.1), .jlong(2), .jshort(123)))
+    expect_true(.fastr.java.isArray(a))
+    expect_equal(length(a), 5)
+    expect_equal(a[1], 1)
+    expect_equal(a[2], "a")
+    expect_true((a[3] - 1.1)^2 < 1e-8)
+    expect_equal(a[4], 2)
+    expect_equal(a[5], 123)
+
+    to <- .jnew('java.util.ArrayList')
+    a <- .jarray(to)
+    expect_true(.fastr.java.isArray(a))
+    expect_equal(length(a), 1)
+    # fails at the moment
+    # expect_equal(a[1], to)
+
+    to <- .jnew('java.util.ArrayList')
+    a <- .jarray(c(to, to))
+    expect_true(.fastr.java.isArray(a))
+    expect_equal(length(a), 2)
+    # fails at the moment    
+    # expect_equal(a[1], to)
+    # expect_equal(a[2], to)
+
+    a <- .jarray(list(1, 2, 3))
+    expect_true(.fastr.java.isArray(a))
+    expect_equal(length(a), 3)
+    expect_equal(a[1], 1)
+    expect_equal(a[2], 2)
+    expect_equal(a[3], 3)
+})
+
+testName <- "test .jevalArray"
+test_that(testName, {
+    cat(paste0(testName, "\n"))
+
+    expectedValues <- list(
+        Boolean=list("logical", TRUE, FALSE, TRUE), 
+        Byte=list("integer", 1,2,3), 
+        Char=list("character", "a", "b", "c"), 
+        Double=list("double",1.1, 2.1, 3.1), 
+        Float=list("double", 1.1, 2.1, 3.1), 
+        Int=list("integer",1,2,3), 
+        Long=list("double", 1,2,3), 
+        Short=list("integer",1,2,3), 
+        String=list("character", "a", "b", "c"))
+    testClassName <- "com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass"
+    t<-.jnew(class=testClassName)
+
+    for(expectedName in names(expectedValues)) {                
+        fieldName <- paste0("fieldStatic", expectedName, "Array")
+        ev<-expectedValues[expectedName][[1]]
+        arrayType <- ev[[1]]
+        arrayLength <- length(ev) - 1
+        a<-t[fieldName]
+        expect_true(.fastr.java.isArray(a), info=paste0("the array was returned for ", fieldName), label=".fastr.java.isArray")
+        ae<-.jevalArray(a)
+        expect_true(is.vector(ae), info=paste0("the array was returned for ", fieldName), label="is.vector")
+        expect_equal(typeof(ae), arrayType, info=paste0("the array was returned for ", fieldName), label="typeof")
+        expect_equal(length(ae), arrayLength, info=paste0("the array was returned for ", fieldName), label="array length")
+        for(i in 1:arrayLength) {
+            if(expectedName != "Float") {
+                expect_equal(a[i], ev[[i+1]], info=paste0("the array was returned for ", fieldName), label=paste0("value at", i))
+            } else {
+                expect_true((ev[[i+1]] - a[i])^2 < 1e-8, info=paste0("the array was returned for ", fieldName), label=paste0("value at", i))
+            }
+        }
+    }
+
+})
\ No newline at end of file
diff --git a/com.oracle.truffle.r.pkgs/rJava/tests/testthat/testBasic.R b/com.oracle.truffle.r.pkgs/rJava/tests/testthat/testBasic.R
new file mode 100644
index 0000000000000000000000000000000000000000..72945437d159500915125e077db805376574defe
--- /dev/null
+++ b/com.oracle.truffle.r.pkgs/rJava/tests/testthat/testBasic.R
@@ -0,0 +1,135 @@
+# prerequisites:
+# - 'testthat' package has to be installed: install.packages("testthat")
+# - FastR`s rJava package has to be installed: bin/r CMD INSTALL com.oracle.truffle.r.pkgs/rjava
+# - mxbuild/dists/fastr-unit-tests.jar has to be on FastR classpath
+
+library(testthat)
+library(rJava)
+
+bo <- TRUE
+bt <- 123
+ch <- 'a'
+d  <- 1.123456
+f  <- 1.123
+i  <- 12345L
+l  <- 123456
+sh <- 1234
+st <- "a test string"
+
+jbt <- .jbyte(bt)
+jch <- .jchar(ch)
+jf  <- .jfloat(f)
+jl  <- .jlong(l)
+jsh <- .jshort(sh)
+
+primitiveTypeNames <- c("Boolean", "Byte", "Char", "Double", "Float", "Integer", "Long", "Short")
+expectedValues <- list(bo, bt, ch, d, f, i, l, sh, st)
+
+testClassName <- "com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass"
+t<-.jnew(class=testClassName, bo, jbt, jch, d, jf, i, jl, jsh, st)
+
+testForMember <- function(valueProvider, memberNameProvider, typeNames) {
+	for(idx in 1:length(typeNames)) {	
+		typeName <- typeNames[idx]
+		member <- memberNameProvider(typeName)
+		expectedValue <- expectedValues[[idx]]
+		value <- valueProvider(t, member)
+		testValue(member, typeName, expectedValue, value)
+	}
+}
+
+testValue <- function(memberName, typeName, expectedValue, value) {
+	cat(paste0("  ", memberName, " returned value [", value, "] and is expected to be [", expectedValue, "]"), "\n")
+	if(typeName != "Float") {
+		expect_that(expectedValue, equals(value), info=memberName, label=memberName)
+	} else {
+		expect_true((expectedValue - value)^2 < 1e-8, info=memberName, label=memberName)
+	}
+}
+
+testName <- "test if primitive field access works"
+test_that(testName, {
+	cat(paste0(testName, "\n"))
+	testForMember( valueProvider = function(t, member) { .jfield(t, , member) },
+                   memberNameProvider = function(typeName) { paste0("field", typeName) },
+                   primitiveTypeNames )
+})
+
+testName <- "test if primitive static field access works"
+test_that(testName, {
+	cat(paste0(testName, "\n"))
+	testForMember( valueProvider = function(t, member) { .jfield(t, , member) },
+                   memberNameProvider = function(typeName) { paste0("fieldStatic", typeName) },
+                   primitiveTypeNames )
+})
+
+testName <- "test if static field access works"
+test_that("test if static field access works", {
+	testForMember( valueProvider = function(t, member) { .jfield(t, , member) },
+                   memberNameProvider = function(typeName) { paste0("fieldStatic", typeName, "Object") },
+                   c(primitiveTypeNames, "String") )
+})
+
+testName <- "test if field access works"
+test_that(testName, {
+	cat(paste0(testName, "\n"))
+	testForMember( valueProvider = function(t, member) { .jfield(t, , member) },
+                   memberNameProvider = function(typeName) { paste0("field", typeName, "Object")},
+                   c(primitiveTypeNames, "String") )
+})
+
+testName <- "test if calling static method returning primitive values works"
+test_that(testName, {
+	cat(paste0(testName, "\n"))
+	testForMember( valueProvider = function(t, member) { .jcall(t, , member) },
+                   memberNameProvider = function(typeName) { paste0("methodStatic", typeName) },
+                   primitiveTypeNames )
+})
+
+testName <- "test if calling method returning primitive values works"
+test_that(testName, {
+	cat(paste0(testName, "\n"))
+	testForMember( valueProvider = function(t, member) { .jcall(t, , member) },
+                   memberNameProvider = function(typeName) { paste0("method", typeName) },
+                   primitiveTypeNames )
+})
+
+testName <- "test if calling static method returning object values works"
+test_that(testName, {
+	cat(paste0(testName, "\n"))
+	testForMember( valueProvider = function(t, member) { .jcall(t, , member) },
+                   memberNameProvider = function(typeName) { paste0("methodStatic", typeName, "Object") },
+                   c(primitiveTypeNames, "String") )
+})
+
+testName <- "test if calling method returning object values works"
+test_that(testName, {
+	cat(paste0(testName, "\n"))
+	testForMember( valueProvider = function(t, member) { .jcall(t, , member) },
+                   memberNameProvider = function(typeName) { paste0("method", typeName, "Object") },
+                   c(primitiveTypeNames, "String") )
+})
+
+testName <- "test if static access via class name works"
+test_that(testName, {
+	cat(paste0(testName, "\n"))
+	value <- .jfield(testClassName, , "fieldStaticInteger")
+	testValue("fieldStaticInteger", "Integer", i, value)
+
+	value <- .jcall(testClassName, , "methodStaticInteger")
+	testValue("methodStaticInteger", "Integer", i, value)
+})
+
+testName <- "test if calling method with all primitive type parameters + string works"
+test_that(testName, {
+	cat(paste0(testName, "\n"))
+	value <- .jcall(t, , "allTypesMethod", bo, jbt, jch, d, jf, i, jl, jsh, st)
+	expect_false(is.null(value))
+})
+
+testName <- "test if calling method with all primitive type parameters + string works"
+test_that(testName, {
+	cat(paste0(testName, "\n"))
+	value <- .jcall(t, , "allTypesStaticMethod", bo, jbt, jch, d, jf, i, jl, jsh, st)
+	expect_false(is.null(value))
+})
\ No newline at end of file
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PkgInit.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PkgInit.java
index d5c2450edf354b3af039346cfa290d3e68556823..0cf12986f0869a1a7d5bf39ec1c75cc62332af46 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PkgInit.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PkgInit.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,8 +22,11 @@
  */
 package com.oracle.truffle.r.runtime.ffi.jni;
 
+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.ffi.DLL;
+import com.oracle.truffle.r.runtime.ffi.DLL.CEntry;
 import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo;
 import com.oracle.truffle.r.runtime.ffi.DLL.DotSymbol;
 import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
@@ -43,13 +46,18 @@ final class JNI_PkgInit {
 
     @SuppressWarnings("unused")
     private static void registerCCallable(String pkgName, String functionName, long address) {
-        // TBD
+        DLLInfo lib = safeFindLibrary(pkgName);
+        lib.registerCEntry(new CEntry(functionName, new SymbolHandle(address)));
     }
 
     @SuppressWarnings("unused")
-    private static long getCCallable(String pkgName, String functionName) {
-        // TBD
-        throw RInternalError.unimplemented();
+    public static long getCCallable(String pkgName, String functionName) {
+        DLLInfo lib = safeFindLibrary(pkgName);
+        CEntry result = lib.lookupCEntry(functionName);
+        if (result == null) {
+            throw RError.error(RError.NO_CALLER, Message.UNKNOWN_OBJECT, functionName);
+        }
+        return result.address.asAddress();
     }
 
     /**
@@ -77,4 +85,14 @@ final class JNI_PkgInit {
     public static int findSymbol(String name, String pkg, DLL.RegisteredNativeSymbol rns) {
         throw RInternalError.unimplemented();
     }
+
+    private static DLLInfo safeFindLibrary(String pkgName) {
+        DLLInfo lib = DLL.findLibrary(pkgName);
+        if (lib == null) {
+            // It seems GNU R would create an C entry even for non-existing package, we are more
+            // defensive
+            throw RError.error(RError.NO_CALLER, Message.DLL_NOT_LOADED, pkgName);
+        }
+        return lib;
+    }
 }
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 20acad69f07ff206c3be83053d1d928b41138016..d5b2a0fd389ec17fdc974497bfbca268f42cf772 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -149,6 +149,10 @@ public final class ArgumentsSignature implements Iterable<String> {
         return names[index] == UNMATCHED;
     }
 
+    public boolean isVarArg(int index) {
+        return this.isVarArg[index];
+    }
+
     /**
      * Returns the index of given name, {@code -1} if it is not present. The search key must be
      * interned string.
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 7c250e88e7fb001ded28431cf715138ffc026fcf..73ebc61f284e076ec2ef3fe10e19d66db4133e09 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
@@ -26,8 +26,6 @@ import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Iterator;
 
-import javax.xml.bind.DatatypeConverter;
-
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.nodes.RootNode;
@@ -86,9 +84,9 @@ public class RDeparse {
     public static final int SIMPLEDEPARSE = 0;
     public static final int DEFAULTDEPARSE = 65; /* KEEPINTEGER | KEEPNA, used for calls */
 
-    public static final int MIN_Cutoff = 20;
-    public static final int MAX_Cutoff = 500;
-    public static final int DEFAULT_Cutoff = 60;
+    public static final int MIN_CUTOFF = 20;
+    public static final int MAX_CUTOFF = 500;
+    public static final int DEFAULT_CUTOFF = 60;
     public static final char BACKTICK = '`';
     public static final char DQUOTE = '"';
 
@@ -264,22 +262,29 @@ public class RDeparse {
 
         private final ArrayList<SourceSectionElement> sources;
 
-        private final int cutoff;
+        private final int listCutoff;
+        private final int debugCutoff;
         private final boolean backtick;
         private int opts;
-        @SuppressWarnings("unused") private final int nlines;
+        private final int nlines;
 
         private int inCurly = 0;
         private int inList = 0;
         private int indent = 0;
         private int lastLineStart = 0;
+        private int curLine = 1;
 
         DeparseVisitor(boolean storeSource, int cutoff, boolean backtick, int opts, int nlines) {
-            this.cutoff = cutoff;
+            this(storeSource, cutoff, backtick, opts, nlines, -1);
+        }
+
+        DeparseVisitor(boolean storeSource, int cutoff, boolean backtick, int opts, int nlines, int debugCutoff) {
+            this.listCutoff = cutoff;
             this.backtick = backtick;
             this.opts = opts;
             this.nlines = nlines;
             this.sources = storeSource ? new ArrayList<>() : null;
+            this.debugCutoff = debugCutoff;
         }
 
         public String getContents() {
@@ -304,13 +309,22 @@ public class RDeparse {
             return (opts & QUOTEEXPRESSIONS) != 0;
         }
 
+        private void checkLength(int nchar) {
+            if (debugCutoff >= 0 && sb.length() + nchar > debugCutoff) {
+                throw new MaxLengthReachedException();
+            }
+        }
+
         private DeparseVisitor append(char ch) {
             assert ch != '\n';
+            checkLength(1);
             sb.append(ch);
             return this;
         }
 
         private DeparseVisitor append(String str) {
+            assert !str.contains("\n");
+            checkLength(str.length());
             sb.append(str);
             return this;
         }
@@ -342,7 +356,7 @@ public class RDeparse {
                 if (digest == null) {
                     digest = MessageDigest.getInstance("SHA-256");
                 }
-                String printHexBinary = DatatypeConverter.printHexBinary(digest.digest(sb.toString().getBytes()));
+                String printHexBinary = Utils.toHexString(digest.digest(sb.toString().getBytes()));
                 assert printHexBinary.length() > 10;
 
                 // just use the first 10 hex digits to have a nicer file name
@@ -357,6 +371,7 @@ public class RDeparse {
             if (!Files.exists(path)) {
                 try (BufferedWriter bw = Files.newBufferedWriter(path, CREATE_NEW, WRITE)) {
                     bw.write(sb.toString());
+                    bw.newLine();
                 }
             }
             return path;
@@ -370,7 +385,9 @@ public class RDeparse {
                     Path path = emitToFile(name);
                     Source source = RSource.fromFile(path.toFile());
                     for (SourceSectionElement s : sources) {
-                        s.element.setSourceSection(source.createSection(s.start, s.length));
+                        if (s.element.getLazySourceSection() == null || s.element.getLazySourceSection() == RSyntaxNode.LAZY_DEPARSE) {
+                            s.element.setSourceSection(source.createSection(s.start, s.length));
+                        }
                     }
                 } catch (IOException e) {
                     RInternalError.reportError(e);
@@ -406,13 +423,20 @@ public class RDeparse {
         public DeparseVisitor append(RSyntaxElement element) {
             try (C c = withContext(element)) {
                 visitor.accept(element);
+            } catch (AbortDeparsingException e) {
+                // stop deparsing; indicate that there is something missing
+                sb.append("...");
             }
             return this;
         }
 
         private void printline() {
             sb.append("\n");
+            curLine++;
             lastLineStart = sb.length();
+            if (nlines > 0 && curLine >= nlines) {
+                throw new MaxLinesReachedException();
+            }
             for (int i = 0; i < indent; i++) {
                 sb.append(i < 4 ? "    " : "  ");
             }
@@ -436,9 +460,9 @@ public class RDeparse {
             return null;
         }
 
-        private boolean linebreak(boolean lbreak) {
+        private boolean listLinebreak(boolean lbreak) {
             boolean result = lbreak;
-            if ((sb.length() - lastLineStart) > cutoff) {
+            if ((sb.length() - lastLineStart) > listCutoff) {
                 if (!lbreak) {
                     result = true;
                     indent++;
@@ -719,7 +743,7 @@ public class RDeparse {
                     if (i++ > 0) {
                         append(", ");
                     }
-                    lbreak = linebreak(lbreak);
+                    lbreak = listLinebreak(lbreak);
                     if (arglist.getTag() != RNull.instance) {
                         String argName = ((RSymbol) arglist.getTag()).getName();
                         if (!argName.isEmpty()) {
@@ -784,7 +808,7 @@ public class RDeparse {
                 if (i > start) {
                     append(", ");
                 }
-                lbreak = linebreak(lbreak);
+                lbreak = listLinebreak(lbreak);
                 RSyntaxElement argument = args[i];
                 String name = signature.getName(i);
 
@@ -821,22 +845,27 @@ public class RDeparse {
             Object value = RRuntime.asAbstractVector(v);
             assert value instanceof RTypedValue : v.getClass();
 
-            RSyntaxElement element;
-            if (value instanceof RSymbol) {
-                element = RSyntaxLookup.createDummyLookup(RSyntaxNode.INTERNAL, ((RSymbol) value).getName(), false);
-            } else if (value instanceof RLanguage) {
-                element = ((RLanguage) value).getRep().asRSyntaxNode();
-            } else if (value instanceof RMissing) {
-                element = RSyntaxLookup.createDummyLookup(null, "", false);
-            } else {
-                return appendConstant(value);
-            }
-            if (!quoteExpressions() || element instanceof RSyntaxConstant) {
-                append(element);
-            } else {
-                append("quote(");
-                append(element);
-                append(')');
+            try {
+                RSyntaxElement element;
+                if (value instanceof RSymbol) {
+                    element = RSyntaxLookup.createDummyLookup(RSyntaxNode.INTERNAL, ((RSymbol) value).getName(), false);
+                } else if (value instanceof RLanguage) {
+                    element = ((RLanguage) value).getRep().asRSyntaxNode();
+                } else if (value instanceof RMissing) {
+                    element = RSyntaxLookup.createDummyLookup(null, "", false);
+                } else {
+                    return appendConstant(value);
+                }
+                if (!quoteExpressions() || element instanceof RSyntaxConstant) {
+                    append(element);
+                } else {
+                    append("quote(");
+                    append(element);
+                    append(')');
+                }
+            } catch (AbortDeparsingException e) {
+                // stop deparsing; indicate that there is something missing
+                sb.append("...");
             }
             return this;
         }
@@ -962,7 +991,7 @@ public class RDeparse {
                 if (i > 0) {
                     append(", ");
                 }
-                lbreak = linebreak(lbreak);
+                lbreak = listLinebreak(lbreak);
                 if (snames != null) {
                     append(quotify(snames.getDataAt(i), '\"'));
                     append(" = ");
@@ -1042,12 +1071,12 @@ public class RDeparse {
 
     @TruffleBoundary
     public static String deparseSyntaxElement(RSyntaxElement element) {
-        return new DeparseVisitor(false, RDeparse.MAX_Cutoff, true, KEEPINTEGER, -1).append(element).getContents();
+        return new DeparseVisitor(false, RDeparse.MAX_CUTOFF, true, KEEPINTEGER, -1).append(element).getContents();
     }
 
     @TruffleBoundary
     public static String deparse(Object value) {
-        return new DeparseVisitor(false, RDeparse.MAX_Cutoff, true, KEEPINTEGER, -1).appendValue(value).getContents();
+        return new DeparseVisitor(false, RDeparse.MAX_CUTOFF, true, KEEPINTEGER, -1).appendValue(value).getContents();
     }
 
     @TruffleBoundary
@@ -1055,6 +1084,11 @@ public class RDeparse {
         return new DeparseVisitor(false, cutoff, backtick, opts, nlines).appendValue(expr).getContents();
     }
 
+    @TruffleBoundary
+    public static String deparse(Object expr, int cutoff, boolean backtick, int opts, int nlines, int debugCutoff) {
+        return new DeparseVisitor(false, cutoff, backtick, opts, nlines, debugCutoff).appendValue(expr).getContents();
+    }
+
     /**
      * Ensure that {@code node} has a {@link SourceSection} by deparsing if necessary.
      */
@@ -1070,11 +1104,11 @@ public class RDeparse {
                 }
             }
             // try to generate the source from the root node and hopefully it includes this node
-            new DeparseVisitor(true, RDeparse.MAX_Cutoff, false, -1, 0).append(nodeToFixup).fixupSources();
+            new DeparseVisitor(true, RDeparse.MAX_CUTOFF, false, -1, 0).append(nodeToFixup).fixupSources();
 
             // if not, we have to deparse the node in isolation
             if (node.getLazySourceSection() == RSyntaxNode.LAZY_DEPARSE) {
-                new DeparseVisitor(true, RDeparse.MAX_Cutoff, false, -1, 0).append(node).fixupSources();
+                new DeparseVisitor(true, RDeparse.MAX_CUTOFF, false, -1, 0).append(node).fixupSources();
             }
             assert node.getLazySourceSection() != RSyntaxNode.LAZY_DEPARSE;
         }
@@ -1134,4 +1168,16 @@ public class RDeparse {
             return 0;
         }
     }
+
+    @SuppressWarnings("serial")
+    private static class AbortDeparsingException extends RuntimeException {
+    }
+
+    @SuppressWarnings("serial")
+    private static final class MaxLinesReachedException extends AbortDeparsingException {
+    }
+
+    @SuppressWarnings("serial")
+    private static final class MaxLengthReachedException extends AbortDeparsingException {
+    }
 }
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 fbb3953558a93d1e1a604db5ce01d7ce14dc455e..4b34f2b46d44749447c232785181bc6f170c3b1e 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
@@ -590,7 +590,6 @@ public final class RError extends RuntimeException {
         NROW_ZERO("nr(0 for non-null data"),
         CANNOT_EXCEED_X("'%s' cannot exceed %s(x) = %d"),
         SAMPLE_LARGER_THAN_POPULATION("cannot take a sample larger than the population when 'replace(FALSE'\n"),
-        SAMPLE_OBJECT_NOT_FOUND("object '%s' not found"),
         ERROR_IN_SAMPLE("Error in sample.int(x, size, replace, prob) :  "),
         INCORRECT_NUM_PROB("incorrect number of probabilities"),
         NA_IN_PROB_VECTOR("NA in probability vector"),
@@ -614,6 +613,7 @@ public final class RError extends RuntimeException {
         INVALID_FORMAT_LOGICAL("invalid format '%s'; use format %%d or %%i for logical objects"),
         INVALID_FORMAT_INTEGER("invalid format '%s'; use format %%d, %%i, %%o, %%x or %%X for integer objects"),
         POS_NOT_ALLOWED_WITH_NUMERIC("pos argument not allowed with a numeric value"),
+        OBJ_CANNOT_BE_ATTRIBUTED("external object cannot be attributed"),
         // the following list is incomplete (but like GNU-R)
         INVALID_FORMAT_DOUBLE("invalid format '%s'; use format %%f, %%e, %%g or %%a for numeric objects"),
         INVALID_LOGICAL("'%s' must be TRUE or FALSE"),
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java
index eda8d1fee8af05be6eb5d8add2d77776f0b80202..8415803a341c9c2496490671d9afc65f6739c5be 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java
@@ -1474,7 +1474,8 @@ public class RSerialize {
                             attributes = null;
                         }
                     }
-                    boolean hasTag = gnuRType == SEXPTYPE.CLOSXP || (gnuRType == SEXPTYPE.PROMSXP && !((RPromise) obj).isEvaluated()) || (type == SEXPTYPE.LISTSXP && !((RPairList) obj).isNullTag());
+                    boolean hasTag = gnuRType == SEXPTYPE.CLOSXP || gnuRType == SEXPTYPE.DOTSXP || (gnuRType == SEXPTYPE.PROMSXP && !((RPromise) obj).isEvaluated()) ||
+                                    (type == SEXPTYPE.LISTSXP && !((RPairList) obj).isNullTag());
                     int gpbits = getGPBits(obj);
                     int flags = Flags.packFlags(gnuRType, gpbits, isObject(obj), attributes != null, hasTag);
                     stream.writeInt(flags);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSource.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSource.java
index e1ef2d2fc9afa9196652aa5e6cec3fb6600fdc12..16f3e223d16b0c343dba84208bd6e57da4c54d0e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSource.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSource.java
@@ -56,6 +56,7 @@ public class RSource {
         SHELL_INPUT("<shell_input>"),
         EXPRESSION_INPUT("<expression_input>"),
         GET_ECHO("<get_echo>"),
+        GET_CONTINUE_PROMPT("<get_continue_prompt>"),
         QUIT_EOF("<<quit_eof>>"),
         STARTUP_SHUTDOWN("<startup/shutdown>"),
         REPL_WRAPPER("<repl wrapper>"),
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ConsoleHandler.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ConsoleHandler.java
index c30feafca92621778beef7300111b91d03aab0b7..cd21de478bcbbc641621ce8c4e41ec50082b40e5 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ConsoleHandler.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ConsoleHandler.java
@@ -31,24 +31,27 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
  * implementations for different contexts. Since I/O is involved, all methods are tagged with
  * {@link TruffleBoundary} as a hint that so should the associated implementation methods.
  */
-public interface ConsoleHandler {
+public abstract class ConsoleHandler {
+
+    private RContext ctx;
+
     /**
      * Normal output with a new line.
      */
     @TruffleBoundary
-    void println(String s);
+    public abstract void println(String s);
 
     /**
      * Normal output without a newline.
      */
     @TruffleBoundary
-    void print(String s);
+    public abstract void print(String s);
 
     /**
      * Formatted output.
      */
     @TruffleBoundary
-    default void printf(String format, Object... args) {
+    public void printf(String format, Object... args) {
         print(String.format(format, args));
     }
 
@@ -58,20 +61,20 @@ public interface ConsoleHandler {
      * @param s
      */
     @TruffleBoundary
-    void printErrorln(String s);
+    public abstract void printErrorln(String s);
 
     /**
      * Error output without a newline.
      */
     @TruffleBoundary
-    void printError(String s);
+    public abstract void printError(String s);
 
     /**
      * Read a line of input, newline is <b>NOT</b> included in result. Returns null if
      * {@link #isInteractive() == false}. TODO worry about "\r\n"?
      */
     @TruffleBoundary
-    String readLine();
+    public abstract String readLine();
 
     /**
      * Denote whether the FastR instance is running in 'interactive' mode. This can be set in a
@@ -79,27 +82,35 @@ public interface ConsoleHandler {
      * final once set.
      */
     @TruffleBoundary
-    boolean isInteractive();
+    public abstract boolean isInteractive();
 
     /**
      * Get the current prompt.
      */
     @TruffleBoundary
-    String getPrompt();
+    public abstract String getPrompt();
 
     /**
      * Set the R prompt.
      */
     @TruffleBoundary
-    void setPrompt(String prompt);
+    public abstract void setPrompt(String prompt);
+
+    public abstract String getInputDescription();
 
-    String getInputDescription();
+    public void setContext(RContext ctx) {
+        this.ctx = ctx;
+    }
+
+    public RContext getContext() {
+        return ctx;
+    }
 
-    default void setHistoryFrom(@SuppressWarnings("unused") File file) {
+    public void setHistoryFrom(@SuppressWarnings("unused") File file) {
         // by default, do nothing
     }
 
-    default void flushHistory() {
+    public void flushHistory() {
         // by default, do nothing
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java
index 93ef3ba544ff1b8f3799caae8fc1aa1ebf65e5d7..5a680554e95df9da0769f3809a8e8aedc9e2dff5 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java
@@ -94,6 +94,13 @@ public final class ContextInfo {
         }
         PolyglotEngine newVM = builder.config("application/x-r", CONFIG_KEY, this).build();
         this.vm = newVM;
+
+        // retrieve context and set for console handler
+        if (consoleHandler != null) {
+            RContext ctx = newVM.eval(Engine.GET_CONTEXT).as(RContext.class);
+            consoleHandler.setContext(ctx);
+        }
+
         return newVM;
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/DefaultConsoleHandler.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/DefaultConsoleHandler.java
index 18f2a36cceb1ed6df87252416c914869ebb2d624..3bb4b182ccaf24cfbba29e1930d0fa3308614bf5 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/DefaultConsoleHandler.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/DefaultConsoleHandler.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,7 +29,7 @@ import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.io.PrintStream;
 
-public class DefaultConsoleHandler implements ConsoleHandler {
+public class DefaultConsoleHandler extends ConsoleHandler {
 
     private final BufferedReader in;
     private final PrintStream out;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
index 2a790546b7aeb33940bd9065e5bcea352b5f911e..aca66505b2857a49062c21ee187782489dc2e01f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
@@ -33,6 +33,7 @@ import java.util.TimeZone;
 import java.util.WeakHashMap;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Semaphore;
+import java.util.concurrent.atomic.AtomicInteger;
 
 import com.oracle.truffle.api.Assumption;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
@@ -265,10 +266,14 @@ public final class RContext extends com.oracle.truffle.api.ExecutionContext impl
 
         public static final Map<Integer, Thread> threads = new ConcurrentHashMap<>();
 
+        /** We use a separate counter for threads since ConcurrentHashMap.size() is not reliable. */
+        public static final AtomicInteger threadCnt = new AtomicInteger(0);
+
         public EvalThread(ContextInfo info, Source source) {
             super(null);
             this.info = info;
             this.source = source;
+            threadCnt.incrementAndGet();
             threads.put(info.getId(), this);
         }
 
@@ -286,6 +291,7 @@ public final class RContext extends com.oracle.truffle.api.ExecutionContext impl
             } finally {
                 vm.dispose();
                 threads.remove(info.getId());
+                threadCnt.decrementAndGet();
             }
         }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/AgentObjectSizeFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/AgentObjectSizeFactory.java
index 884bd82b483ac87d172232764e2f24536d3431dd..85c44026426c8740cc9155fb4b5212df37939219 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/AgentObjectSizeFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/AgentObjectSizeFactory.java
@@ -59,7 +59,6 @@ import com.oracle.truffle.r.runtime.data.RObjectSize.TypeCustomizer;
 public class AgentObjectSizeFactory extends ObjectSizeFactory {
 
     private final Map<Class<?>, ArrayList<Field>> objectFieldsMap = new HashMap<>();
-    private static Map<Class<?>, TypeCustomizer> customizerMap = new HashMap<>(); // system wide
 
     public AgentObjectSizeFactory() {
         if (!ObjSizeAgent.isInitialized()) {
@@ -208,19 +207,4 @@ public class AgentObjectSizeFactory extends ObjectSizeFactory {
             }
         }
     }
-
-    private static TypeCustomizer getCustomizer(Class<?> objClass) {
-        for (Map.Entry<Class<?>, TypeCustomizer> entry : customizerMap.entrySet()) {
-            if (entry.getKey().isAssignableFrom(objClass)) {
-                return entry.getValue();
-            }
-        }
-        return null;
-
-    }
-
-    @Override
-    public void registerTypeCustomizer(Class<?> klass, TypeCustomizer typeCustomizer) {
-        customizerMap.put(klass, typeCustomizer);
-    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/ObjectSizeFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/ObjectSizeFactory.java
index dc5b6529b927da17c556388083bd25322e654b8d..9de56a9bce0f448008af12b9b98b81bfee49e8ff 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/ObjectSizeFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/ObjectSizeFactory.java
@@ -22,12 +22,16 @@
  */
 package com.oracle.truffle.r.runtime.data;
 
+import java.util.ArrayList;
+
 import com.oracle.truffle.r.runtime.FastRConfig;
 import com.oracle.truffle.r.runtime.data.RObjectSize.IgnoreObjectHandler;
 import com.oracle.truffle.r.runtime.data.RObjectSize.TypeCustomizer;
 
 public abstract class ObjectSizeFactory {
 
+    private static ArrayList<TypeCustomizerData> typeCustomizers = new ArrayList<>(); // system wide
+
     static {
         String prop = System.getProperty("fastr.objectsize.factory.class");
         if (prop == null) {
@@ -56,6 +60,26 @@ public abstract class ObjectSizeFactory {
      */
     public abstract long getObjectSize(Object obj, IgnoreObjectHandler ignoreObjectHandler);
 
-    public abstract void registerTypeCustomizer(Class<?> klass, TypeCustomizer typeCustomizer);
+    public void registerTypeCustomizer(Class<?> klass, TypeCustomizer typeCustomizer) {
+        typeCustomizers.add(new TypeCustomizerData(klass, typeCustomizer));
+    }
+
+    protected static TypeCustomizer getCustomizer(Class<?> objClass) {
+        for (TypeCustomizerData customizer : typeCustomizers) {
+            if (customizer.type.isAssignableFrom(objClass)) {
+                return customizer.customizer;
+            }
+        }
+        return null;
+    }
+
+    private static final class TypeCustomizerData {
+        private final TypeCustomizer customizer;
+        private final Class<?> type;
 
+        private TypeCustomizerData(Class<?> type, TypeCustomizer customizer) {
+            this.customizer = customizer;
+            this.type = type;
+        }
+    }
 }
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 c5610b4945cca913c5e900bdb8458be8353432bb..1f874d0842786b2e9c4e944544a9815dc2941bab 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, 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -51,7 +51,9 @@ public final class RArgsValuesAndNames extends Arguments<Object> implements RTyp
 
     @Override
     public int getTypedValueInfo() {
-        throw RInternalError.shouldNotReachHere();
+        // RArgsValuesAndNames can get serialized under specific circumstances (ggplot2 does that)
+        // and getTypedValueInfo() must be defined for this to work.
+        return 0;
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/SimpleObjectSizeFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/SimpleObjectSizeFactory.java
index 6f5d17a46638257c775d94e706d334cadf5426f5..9df6c25f3cc4b19d98f7a2168e4c717c71179112 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/SimpleObjectSizeFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/SimpleObjectSizeFactory.java
@@ -22,8 +22,6 @@
  */
 package com.oracle.truffle.r.runtime.data;
 
-import java.util.HashMap;
-
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.data.RObjectSize.IgnoreObjectHandler;
@@ -40,16 +38,13 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
  * Very simple object size calculation that does not need an instrumentation agent.
  */
 public class SimpleObjectSizeFactory extends ObjectSizeFactory {
-    private HashMap<Class<?>, TypeCustomizer> typeCustomizers;
-
     @Override
     public long getObjectSize(Object obj, IgnoreObjectHandler ignoreObjectHandler) {
         RError.warning(RError.NO_CALLER, Message.OBJECT_SIZE_ESTIMATE);
         // Customizers
-        for (Class<?> klass : typeCustomizers.keySet()) {
-            if (obj.getClass().equals(klass)) {
-                return typeCustomizers.get(klass).getObjectSize(obj);
-            }
+        TypeCustomizer customizer = getCustomizer(obj.getClass());
+        if (customizer != null) {
+            return customizer.getObjectSize(obj);
         }
         // Well known vector types
         if (obj instanceof RAbstractDoubleVector) {
@@ -76,12 +71,4 @@ public class SimpleObjectSizeFactory extends ObjectSizeFactory {
         }
         return 4;
     }
-
-    @Override
-    public void registerTypeCustomizer(Class<?> klass, TypeCustomizer typeCustomizer) {
-        if (typeCustomizers == null) {
-            typeCustomizers = new HashMap<>();
-        }
-        typeCustomizers.put(klass, typeCustomizer);
-    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java
index d44fd73c8796a4725c679e55032c7030a1be91f6..c93bf6935e6818f563f04f9fb608e2a658bee006 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java
@@ -24,6 +24,7 @@ package com.oracle.truffle.r.runtime.env;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.frame.Frame;
+import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.interop.MessageResolution;
@@ -31,6 +32,7 @@ import com.oracle.truffle.api.interop.Resolve;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.interop.UnknownIdentifierException;
 import com.oracle.truffle.api.interop.UnsupportedMessageException;
+import com.oracle.truffle.api.interop.UnsupportedTypeException;
 import com.oracle.truffle.api.metadata.ScopeProvider.AbstractScope;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
@@ -39,6 +41,7 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.env.REnvironment.PutException;
 
 /**
@@ -103,10 +106,9 @@ public final class RScope extends AbstractScope {
 
     @Override
     protected AbstractScope findParent() {
-        if (this.env == REnvironment.emptyEnv()) {
+        if (env == REnvironment.emptyEnv() || env.getParent() == REnvironment.emptyEnv()) {
             return null;
         }
-
         return new RScope(env.getParent());
     }
 
@@ -136,8 +138,16 @@ public final class RScope extends AbstractScope {
         return new RScope(node.getRootNode(), getEnv(frame));
     }
 
-    private static Object getInteropValue(Object value) {
-        return value;
+    /**
+     * Explicitly convert some known types to interop types.
+     */
+    private static Object getInteropValue(Object obj) {
+        if (obj instanceof Frame) {
+            MaterializedFrame materialized = ((Frame) obj).materialize();
+            assert RArguments.isRFrame(materialized);
+            return REnvironment.frameToEnvironment(materialized);
+        }
+        return obj;
     }
 
     static final class VariablesMapObject implements TruffleObject {
@@ -167,11 +177,13 @@ public final class RScope extends AbstractScope {
 
                 @TruffleBoundary
                 public Object access(VariablesMapObject varMap) {
+                    String[] names;
                     if (varMap.argumentsOnly) {
-                        return new ArgumentNamesObject(collectArgs(varMap.env));
+                        names = collectArgs(varMap.env);
                     } else {
-                        return new VariableNamesObject(varMap.env);
+                        names = ls(varMap.env);
                     }
+                    return new ArgumentNamesObject(names);
                 }
             }
 
@@ -223,6 +235,9 @@ public final class RScope extends AbstractScope {
                     if (varMap.env == null) {
                         throw UnsupportedMessageException.raise(Message.WRITE);
                     }
+                    if (!(value instanceof RTypedValue)) {
+                        throw UnsupportedTypeException.raise(new Object[]{value});
+                    }
                     try {
                         varMap.env.put(name, value);
                         return value;
@@ -235,60 +250,6 @@ public final class RScope extends AbstractScope {
         }
     }
 
-    static final class VariableNamesObject implements TruffleObject {
-
-        private final REnvironment env;
-
-        private VariableNamesObject(REnvironment env) {
-            this.env = env;
-        }
-
-        @Override
-        public ForeignAccess getForeignAccess() {
-            return VariableNamesMessageResolutionForeign.ACCESS;
-        }
-
-        public static boolean isInstance(TruffleObject obj) {
-            return obj instanceof VariableNamesObject;
-        }
-
-        @MessageResolution(receiverType = VariableNamesObject.class)
-        static final class VariableNamesMessageResolution {
-
-            @Resolve(message = "HAS_SIZE")
-            abstract static class VarNamesHasSizeNode extends Node {
-
-                @SuppressWarnings("unused")
-                public Object access(VariableNamesObject varNames) {
-                    return true;
-                }
-            }
-
-            @Resolve(message = "GET_SIZE")
-            abstract static class VarNamesGetSizeNode extends Node {
-
-                public Object access(VariableNamesObject varNames) {
-                    return ls(varNames.env).length;
-                }
-            }
-
-            @Resolve(message = "READ")
-            abstract static class VarNamesReadNode extends Node {
-
-                @TruffleBoundary
-                public Object access(VariableNamesObject varNames, int index) {
-                    String[] names = ls(varNames.env);
-                    if (index >= 0 && index < names.length) {
-                        return names[index];
-                    } else {
-                        throw UnknownIdentifierException.raise(Integer.toString(index));
-                    }
-                }
-            }
-
-        }
-    }
-
     static final class ArgumentNamesObject implements TruffleObject {
 
         private final String[] names;
@@ -331,8 +292,9 @@ public final class RScope extends AbstractScope {
 
                 @TruffleBoundary
                 public Object access(ArgumentNamesObject varNames, int index) {
-                    if (index >= 0 && index < varNames.names.length) {
-                        return varNames.names[index];
+                    String[] names = varNames.names;
+                    if (index >= 0 && index < names.length) {
+                        return names[index];
                     } else {
                         throw UnknownIdentifierException.raise(Integer.toString(index));
                     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java
index 2bb5d9a64ae5afc53428ec640de1594bb98a051a..b6969e1e37aca0b51d612c706f7f30191e31d3cc 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java
@@ -17,8 +17,8 @@ import java.util.concurrent.atomic.AtomicInteger;
 
 import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.frame.FrameDescriptor;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.TruffleObject;
@@ -180,6 +180,7 @@ public class DLL {
         private boolean dynamicLookup;
         private boolean forceSymbols;
         private final DotSymbol[][] nativeSymbols = new DotSymbol[NativeSymbolType.values().length][];
+        private ArrayList<CEntry> cEntryTable = null;
 
         private DLLInfo(String name, String path, boolean dynamicLookup, Object handle) {
             this.id = ID.getAndIncrement();
@@ -229,6 +230,24 @@ public class DLL {
             }
         }
 
+        public void registerCEntry(CEntry entry) {
+            if (cEntryTable == null) {
+                cEntryTable = new ArrayList<>();
+            }
+            cEntryTable.add(entry);
+        }
+
+        public CEntry lookupCEntry(String symbol) {
+            if (cEntryTable != null) {
+                for (CEntry entry : cEntryTable) {
+                    if (entry.symbol.equals(symbol)) {
+                        return entry;
+                    }
+                }
+            }
+            return null;
+        }
+
         /**
          * Return array of values that can be plugged directly into an {@code RList}.
          */
@@ -256,7 +275,7 @@ public class DLL {
         }
     }
 
-    public static class SymbolInfo {
+    public static final class SymbolInfo {
         public final DLLInfo libInfo;
         public final String symbol;
         public final SymbolHandle address;
@@ -305,6 +324,21 @@ public class DLL {
         }
     }
 
+    /**
+     * R has an interface for exporting and importing functions between packages' native code. The
+     * functions have to be exported, i.e. registered in a directory, called CEntry table in GNU R.
+     * Another package can they as the directory for address or a function with specified name.
+     */
+    public static final class CEntry {
+        public final String symbol;
+        public final SymbolHandle address;
+
+        public CEntry(String symbol, SymbolHandle address) {
+            this.symbol = symbol;
+            this.address = address;
+        }
+    }
+
     /**
      * Abstracts the way that DLL function symbols are represented, either as a machine address (
      * {@link Long}) or a {@link TruffleObject}. At the present time, both forms can exists within a
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 c700f6b474620a0bc5151920c9259f33a5920e76..ad6a7f6d381ca1e8949a34b3864d8283eab9cbc3 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
@@ -36123,6 +36123,16 @@ list
 sys.call(1)
 
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_mget.testMGetWithVarArgs#
+#{ find_args <- function(...) !vapply(mget('...', envir = parent.frame()), function(x) identical(x, quote(expr = )), logical(1));func <- function(...) find_args(...);func(); }
+  ...
+FALSE
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_mget.testMGetWithVarArgs#
+#{ find_args <- function(...) !vapply(mget('...', envir = parent.frame()), function(x) identical(x, quote(expr = )), logical(1));func <- function(...) find_args(...);func(a=3); }
+ ...
+TRUE
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum#
 #min(c(1,NA,2), na.rm=NA)
 [1] 1
@@ -62402,6 +62412,10 @@ Error in seq.int(NaN) : 'from' cannot be NA, NaN or infinite
 #argv <- list(from = 0, to = 0.793110173512391, length.out = FALSE);do.call('seq.int', argv);
 integer(0)
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testSerializeWithPromises#
+#{ f <- function(...) serialize(mget('...'),NULL); length(unserialize(f(a=3,b=2,c=1))[[1]]); }
+[1] 3
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testserialize#Ignored.ImplementationError#
 #options(keep.source=FALSE); fc <- setClass('FooSerial1', representation(a = 'call')); serialize(fc, connection=NULL)
   [1] 58 0a 00 00 00 02 00 03 03 02 00 02 03 00 00 01 07 03 00 00 04 02 00 00 00
@@ -64259,6 +64273,14 @@ $`2`
 [1]  2  4  6  8 10
 
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_split.testSplit#
+#{ split(as.raw(1:10), as.factor(c('a', 'b', 'a')); }
+Error: unexpected ';' in "{ split(as.raw(1:10), as.factor(c('a', 'b', 'a'));"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_split.testSplit#
+#{ split(list(1, 2L, 'x', T), as.factor(c('a', 'b', 'a')); }
+Error: unexpected ';' in "{ split(list(1, 2L, 'x', T), as.factor(c('a', 'b', 'a'));"
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_split.testSplit#
 #{ x <- factor(c("a", "b", "a")); attr(x, "levels")<-c(7L, 42L) ; split(1:3, x) }
 $`7`
@@ -64268,6 +64290,24 @@ $`42`
 [1] 2
 
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_split.testSplitWithNames#Ignored.Unimplemented#
+#{ split(list(q=1, w=2L, e='x', r=T), as.factor(c('a', 'b', 'a')); }
+Error: unexpected ';' in "{ split(list(q=1, w=2L, e='x', r=T), as.factor(c('a', 'b', 'a'));"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_split.testSplitWithNames#Ignored.Unimplemented#
+#{ tmp <- c(1,2,3); names(tmp) <- c('x','y','z'); split(tmp, as.factor(c('a','b'))); }
+$a
+x z
+1 3
+
+$b
+y
+2
+
+Warning message:
+In split.default(tmp, as.factor(c("a", "b"))) :
+  data length is not a multiple of split variable
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_split.testsplit1#
 #argv <- list(1:6, structure(1:2, .Label = c('1', '2'), class = 'factor')); .Internal(split(argv[[1]], argv[[2]]))
 $`1`
@@ -76753,6 +76793,12 @@ Error in rnorm(s = 1, s = 1) :
 #{ f <- match.fun(length) ; f(c(1,2,3)) }
 [1] 3
 
+##com.oracle.truffle.r.test.functions.TestFunctions.testMatching#
+#list(`...`=NULL);
+$...
+NULL
+
+
 ##com.oracle.truffle.r.test.functions.TestFunctions.testMatching#
 #{ f <- function(a) { a } ; f(1,2) }
 Error in f(1, 2) : unused argument (2)
@@ -79115,6 +79161,42 @@ Error in get("x") : object 'x' not found
 #{ pi/180; pi }
 [1] 3.141593
 
+##com.oracle.truffle.r.test.library.base.TestSharedCluster.testSharedCluster#
+#fun <- function(data) { cl <- makeCluster(1, 'SHARED'); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100)
+Error in fun(1:100) : could not find function "makeCluster"
+
+##com.oracle.truffle.r.test.library.base.TestSharedCluster.testSharedCluster#
+#fun <- function(data) { cl <- makeCluster(2, 'SHARED'); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100)
+Error in fun(1:100) : could not find function "makeCluster"
+
+##com.oracle.truffle.r.test.library.base.TestSharedCluster.testSharedCluster#
+#fun <- function(data) { cl <- makeCluster(3, 'SHARED'); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100)
+Error in fun(1:100) : could not find function "makeCluster"
+
+##com.oracle.truffle.r.test.library.base.TestSharedCluster.testSharedCluster#
+#fun <- function(data) { cl <- makeCluster(4, 'SHARED'); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100)
+Error in fun(1:100) : could not find function "makeCluster"
+
+##com.oracle.truffle.r.test.library.base.TestSharedCluster.testSharedCluster#
+#fun <- function(data) { cl <- makeCluster(5, 'SHARED'); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100)
+Error in fun(1:100) : could not find function "makeCluster"
+
+##com.oracle.truffle.r.test.library.base.TestSharedCluster.testSharedCluster#
+#fun <- function(data) { cl <- makeCluster(6, 'SHARED'); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100)
+Error in fun(1:100) : could not find function "makeCluster"
+
+##com.oracle.truffle.r.test.library.base.TestSharedCluster.testSharedCluster#
+#fun <- function(data) { cl <- makeCluster(7, 'SHARED'); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100)
+Error in fun(1:100) : could not find function "makeCluster"
+
+##com.oracle.truffle.r.test.library.base.TestSharedCluster.testSharedCluster#
+#fun <- function(data) { cl <- makeCluster(8, 'SHARED'); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100)
+Error in fun(1:100) : could not find function "makeCluster"
+
+##com.oracle.truffle.r.test.library.base.TestSharedCluster.testSharedCluster#
+#fun <- function(data) { cl <- makeCluster(9, 'SHARED'); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100)
+Error in fun(1:100) : could not find function "makeCluster"
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testArithmeticUpdate#
 #{ x <- 3 ; f <- function(z) { if (z) { x <- 1 } ; x <- 1L + x ; x } ; f(FALSE) }
 [1] 4
@@ -130465,10 +130547,10 @@ NULL
 [1] "Error reading file: /a/b.R"
 
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropEvalFile#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { x<-c(1);cat(x) } else { fileConn<-file("testScript.R");writeLines(c("x<-c(1)","cat(x)"), fileConn);close(fileConn);.fastr.interop.evalFile("testScript.R") }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { x<-c(1);cat(x) } else { fileConn<-file("_testInteropEvalFile_testScript_.R");writeLines(c("x<-c(1)","cat(x)"), fileConn);close(fileConn);.fastr.interop.evalFile("_testInteropEvalFile_testScript_.R") }
 1
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropEvalFile#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { x<-c(1);cat(x) } else { fileConn<-file("testScript.R");writeLines(c("x<-c(1)","cat(x)"), fileConn);close(fileConn);.fastr.interop.evalFile("testScript.R","application/x-r") }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { x<-c(1);cat(x) } else { fileConn<-file("_testInteropEvalFile_testScript_.R");writeLines(c("x<-c(1)","cat(x)"), fileConn);close(fileConn);.fastr.interop.evalFile("_testInteropEvalFile_testScript_.R","application/x-r") }
 1
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropExport#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { invisible() } else { .fastr.interop.export('foo', 'foo') }
@@ -130488,7 +130570,8 @@ NULL
 [6] "stringValue"
 
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testPrinting#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('$intValue\n[1] 1\n\n$longValue\n[1] 123412341234\n\n$charValue\n[1] "R"\n\n$shortValue\n[1] -100\n\n$booleanValue\n[1] TRUE\n\n$stringValue\n[1] "foo"\n\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { v <- .fastr.interop.import('testPOJO'); print(v) }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n$intValue\n[1] 1\n\n$longValue\n[1] 123412341234\n\n$charValue\n[1] "R"\n\n$shortValue\n[1] -100\n\n$booleanValue\n[1] TRUE\n\n$stringValue\n[1] "foo"\n\n') } else { v <- .fastr.interop.import('testPOJO'); print(v) }
+[external object]
 $intValue
 [1] 1
 
@@ -130507,26 +130590,21 @@ $booleanValue
 $stringValue
 [1] "foo"
 
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testPrinting#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1]   1  -5 199\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { v <- .fastr.interop.import('testIntArray'); print(v) }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1]   1  -5 199\n') } else { v <- .fastr.interop.import('testIntArray'); print(v) }
+[external object]
 [1]   1  -5 199
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testPrinting#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1]   1  -5 199\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { v <- .fastr.interop.import('testIntArray'); v }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1]   1  -5 199\n') } else { v <- .fastr.interop.import('testIntArray'); v }
+[external object]
 [1]   1  -5 199
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testPrinting#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a"   ""    "foo"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { v <- .fastr.interop.import('testStringArray'); print(v) }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] "a"   ""    "foo"\n') } else { v <- .fastr.interop.import('testStringArray'); print(v) }
+[external object]
 [1] "a"   ""    "foo"
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAllTypes#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { "true127a32767214748364792233720368547758071.7976931348623157E3083.4028235E38testString" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$allTypesMethod(TRUE,127,"a",32767,2147483647,9223372036854775807,1.7976931348623157E308,3.4028235E38,"testString") }
@@ -130537,31 +130615,31 @@ attr(,"is.truffle.object")
 [1] "true127a32767214748364792233720368547758071.7976931348623157E3083.4028235E38testString"
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntArray[1]; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { a <- .fastr.java.toArray(c(1,2,3)); a[1] }
 [1] 1
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntArray[[1]]; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { a <- .fastr.java.toArray(c(1,2,3)); a[[1]] }
 [1] 1
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.toArray(c(1,2,3)); a[1] }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntArray[1]; }
 [1] 1
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.toArray(c(1,2,3)); a[[1]] }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntArray[[1]]; }
 [1] 1
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 123 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntArray[1] <- 123L; t$fieldIntArray[1] }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 123 } else { a <- .fastr.java.toArray(c(1,2,3)); a[1] <- 123; a[1] }
 [1] 123
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 123 } else { tc <- .fastr.java.toArray(c(1,2,3)); a[1] <- 123; a[1] }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 123 } else { a <- .fastr.java.toArray(c(1,2,3)); a[[1]] <- 123; a[[1]] }
 [1] 123
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 123 } else { tc <- .fastr.java.toArray(c(1,2,3)); a[[1]] <- 123; a[[1]] }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { 123 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntArray[1] <- 123L; t$fieldIntArray[1] }
 [1] 123
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
@@ -130589,16 +130667,26 @@ attr(,"is.truffle.object")
 NULL
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$int2DimArray[1] }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2 3\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$int2DimArray[1] }
+[external object]
 [1] 1 2 3
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$int2DimArray[[1]] }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2 3\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$int2DimArray[[1]] }
+[external object]
 [1] 1 2 3
-attr(,"is.truffle.object")
-[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAttributes#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); attributes(to) }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAttributes#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('Error in attr(to, "a") <- "a" : external object cannot be attributed<<<NEWLINE>>>') } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); attr(to, 'a')<-'a' }
+Error in attr(to, "a") <- "a" : external object cannot be attributed
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAttributes#
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('Error in attr(to, which = "a") : external object cannot be attributed<<<NEWLINE>>>') } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); attr(to, which = 'a') }
+Error in attr(to, which = "a") : external object cannot be attributed
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testClassAsParameter#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { "com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$classAsArg(tc) }
@@ -130789,112 +130877,94 @@ NULL
 [1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1]  TRUE FALSE  TRUE\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldBooleanArray }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1]  TRUE FALSE  TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldBooleanArray }
+[external object]
 [1]  TRUE FALSE  TRUE
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1]  TRUE FALSE  TRUE\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticBooleanArray }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1]  TRUE FALSE  TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticBooleanArray }
+[external object]
 [1]  TRUE FALSE  TRUE
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a" "b" "c"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldCharArray }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] "a" "b" "c"\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldCharArray }
+[external object]
 [1] "a" "b" "c"
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a" "b" "c"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticCharArray }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] "a" "b" "c"\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticCharArray }
+[external object]
 [1] "a" "b" "c"
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a" "b" "c"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticStringArray }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] "a" "b" "c"\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticStringArray }
+[external object]
 [1] "a" "b" "c"
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a" "b" "c"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStringArray }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] "a" "b" "c"\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStringArray }
+[external object]
 [1] "a" "b" "c"
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldByteArray }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2 3\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldByteArray }
+[external object]
 [1] 1 2 3
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntArray }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2 3\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntArray }
+[external object]
 [1] 1 2 3
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldLongArray }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2 3\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldLongArray }
+[external object]
 [1] 1 2 3
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldShortArray }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2 3\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldShortArray }
+[external object]
 [1] 1 2 3
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticByteArray }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2 3\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticByteArray }
+[external object]
 [1] 1 2 3
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticIntArray }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2 3\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticIntArray }
+[external object]
 [1] 1 2 3
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticLongArray }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2 3\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticLongArray }
+[external object]
 [1] 1 2 3
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticShortArray }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2 3\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticShortArray }
+[external object]
 [1] 1 2 3
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1.1 2.1 3.1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldDoubleArray }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1.1 2.1 3.1\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldDoubleArray }
+[external object]
 [1] 1.1 2.1 3.1
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1.1 2.1 3.1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldFloatArray }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1.1 2.1 3.1\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldFloatArray }
+[external object]
 [1] 1.1 2.1 3.1
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1.1 2.1 3.1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticDoubleArray }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1.1 2.1 3.1\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticDoubleArray }
+[external object]
 [1] 1.1 2.1 3.1
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1.1 2.1 3.1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticFloatArray }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1.1 2.1 3.1\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticFloatArray }
+[external object]
 [1] 1.1 2.1 3.1
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { "character" } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticCharArray); typeof(v) }
@@ -131159,28 +131229,24 @@ NULL
 [1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a" "b" "c"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticStringArray() }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] "a" "b" "c"\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticStringArray() }
+[external object]
 [1] "a" "b" "c"
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a" "b" "c"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStringArray() }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] "a" "b" "c"\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStringArray() }
+[external object]
 [1] "a" "b" "c"
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodIntArray() }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2 3\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodIntArray() }
+[external object]
 [1] 1 2 3
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2 3\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticIntArray() }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2 3\n') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticIntArray() }
+[external object]
 [1] 1 2 3
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForJavaObject#
 #if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { cl <- .fastr.java.class('java.util.Collections'); em<-cl$EMPTY_MAP; names(em) }
@@ -131287,189 +131353,158 @@ Error: object 'java.lang.String' not found
 [1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1]  TRUE FALSE\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(T, F)); a; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1]  TRUE FALSE\n') } else { a <- .fastr.java.toArray(c(T, F)); a; }
+[external object]
 [1]  TRUE FALSE
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1]  TRUE FALSE\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(T, F),,T); a; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1]  TRUE FALSE\n') } else { a <- .fastr.java.toArray(c(T, F),,T); a; }
+[external object]
 [1]  TRUE FALSE
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a" "b"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c('a', 'b')); a; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] "a" "b"\n') } else { a <- .fastr.java.toArray(c('a', 'b')); a; }
+[external object]
 [1] "a" "b"
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a" "b"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c('a', 'b'),,T); a; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] "a" "b"\n') } else { a <- .fastr.java.toArray(c('a', 'b'),,T); a; }
+[external object]
 [1] "a" "b"
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray('a'); a; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] "a"\n') } else { a <- .fastr.java.toArray('a'); a; }
+[external object]
 [1] "a"
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "a"\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray('a',,T); a; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] "a"\n') } else { a <- .fastr.java.toArray('a',,T); a; }
+[external object]
 [1] "a"
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2))); a; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2\n') } else { a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2))); a; }
+[external object]
 [1] 1 2
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)), 'int'); a; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2\n') } else { a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)), 'int'); a; }
+[external object]
 [1] 1 2
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)), 'java.lang.Short'); a; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2\n') } else { a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)), 'java.lang.Short'); a; }
+[external object]
 [1] 1 2
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)), 'java.lang.Short', T); a; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2\n') } else { a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)), 'java.lang.Short', T); a; }
+[external object]
 [1] 1 2
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)),,T); a; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2\n') } else { a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)),,T); a; }
+[external object]
 [1] 1 2
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(1L, 2L)); a; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2\n') } else { a <- .fastr.java.toArray(c(1L, 2L)); a; }
+[external object]
 [1] 1 2
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1 2\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(1L, 2L),,T); a; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1 2\n') } else { a <- .fastr.java.toArray(c(1L, 2L),,T); a; }
+[external object]
 [1] 1 2
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1.1 1.2\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(1.1, 1.2)); a; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1.1 1.2\n') } else { a <- .fastr.java.toArray(c(1.1, 1.2)); a; }
+[external object]
 [1] 1.1 1.2
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1.1 1.2\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(1.1, 1.2),,T); a; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1.1 1.2\n') } else { a <- .fastr.java.toArray(c(1.1, 1.2),,T); a; }
+[external object]
 [1] 1.1 1.2
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1.123 2.123\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(c(1.123, 2.123), 'double'); a; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1.123 2.123\n') } else { a <- .fastr.java.toArray(c(1.123, 2.123), 'double'); a; }
+[external object]
 [1] 1.123 2.123
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1.1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(1.1); a; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1.1\n') } else { a <- .fastr.java.toArray(1.1); a; }
+[external object]
 [1] 1.1
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1.1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(1.1,,T); a; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1.1\n') } else { a <- .fastr.java.toArray(1.1,,T); a; }
+[external object]
 [1] 1.1
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(.fastr.interop.toShort(1)); .fastr.java.toArray(a); }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1\n') } else { a <- .fastr.java.toArray(.fastr.interop.toShort(1)); .fastr.java.toArray(a); }
+[external object]
 [1] 1
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(.fastr.interop.toShort(1)); a; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1\n') } else { a <- .fastr.java.toArray(.fastr.interop.toShort(1)); a; }
+[external object]
 [1] 1
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(.fastr.interop.toShort(1), 'double'); a; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1\n') } else { a <- .fastr.java.toArray(.fastr.interop.toShort(1), 'double'); a; }
+[external object]
 [1] 1
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(.fastr.interop.toShort(1), 'java.lang.Short'); a; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1\n') } else { a <- .fastr.java.toArray(.fastr.interop.toShort(1), 'java.lang.Short'); a; }
+[external object]
 [1] 1
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(.fastr.interop.toShort(1), 'java.lang.Short', T); a; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1\n') } else { a <- .fastr.java.toArray(.fastr.interop.toShort(1), 'java.lang.Short', T); a; }
+[external object]
 [1] 1
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(.fastr.interop.toShort(1),,T); a; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1\n') } else { a <- .fastr.java.toArray(.fastr.interop.toShort(1),,T); a; }
+[external object]
 [1] 1
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(1L); .fastr.java.toArray(a); }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1\n') } else { a <- .fastr.java.toArray(1L); .fastr.java.toArray(a); }
+[external object]
 [1] 1
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(1L); .fastr.java.toArray(a,,T); }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1\n') } else { a <- .fastr.java.toArray(1L); .fastr.java.toArray(a,,T); }
+[external object]
 [1] 1
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(1L); a; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1\n') } else { a <- .fastr.java.toArray(1L); a; }
+[external object]
 [1] 1
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#Ignored.Unimplemented#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(1L,,F); a; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1\n') } else { a <- .fastr.java.toArray(1L,,F); a; }
+[external object]
 [1] 1
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] 1\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(1L,,T); a; }
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1\n') } else { a <- .fastr.java.toArray(1L,,T); a; }
+[external object]
 [1] 1
-attr(,"is.truffle.object")
-[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] TRUE\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(T); a; }
-[1] TRUE
-attr(,"is.truffle.object")
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] TRUE\n') } else { a <- .fastr.java.toArray(T); a; }
+[external object]
 [1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] TRUE\nattr(,"is.truffle.object")\n[1] TRUE\n') } else { a <- .fastr.java.toArray(T,,T); a; }
-[1] TRUE
-attr(,"is.truffle.object")
+#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] TRUE\n') } else { a <- .fastr.java.toArray(T,,T); a; }
+[external object]
 [1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java
index 1eb1faf9b642b24dbb7711d5c867c97feea8e5bc..6fa10c3bd8c69b28d712e5a989b84171be46d764 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java
@@ -49,7 +49,6 @@ import com.oracle.truffle.r.runtime.context.RContext.ContextKind;
 import com.oracle.truffle.r.test.generate.FastRSession;
 import com.oracle.truffle.r.test.generate.GnuROneShotRSession;
 import com.oracle.truffle.r.test.generate.TestOutputManager;
-import java.io.OutputStream;
 
 /**
  * Base class for all unit tests. The unit tests are actually arranged as a collection of
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mget.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mget.java
index e27d7728fc5c1f0ad654ae6a0d25cf668c7bb9a3..27f45c65f1dcf52a61f9af79cde406208c08008e 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mget.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mget.java
@@ -34,4 +34,11 @@ public class TestBuiltin_mget extends TestBase {
         assertEval("{ x<-mget(\"_foo_\", ifnotfound=list(function(x) sys.call(0))); print(x[[1]][[1]]); print(x[[1]][[2]]) }");
         assertEval("{ x<-mget(\"_foo_\", ifnotfound=list(function(x) sys.call(1))); list(x[[1]][[1]], x[[1]][[2]], x[[1]][[3]][[1]], x[[1]][[3]][[2]][[1]], x[[1]][[3]][[2]][[2]], x[[1]][[3]][[2]][[3]]) }");
     }
+
+    @Test
+    public void testMGetWithVarArgs() {
+        assertEval(template("{ find_args <- function(...) !vapply(mget('...', envir = parent.frame()), function(x) identical(x, quote(expr = )), logical(1));" +
+                        "func <- function(...) find_args(...);" +
+                        "%0; }", new String[]{"func()", "func(a=3)"}));
+    }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_serialize.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_serialize.java
index 3e031ad10ee498a5d31a0b7b12cf40732aa86c79..018b22c6522e7f87fd641f22e554eb5fe53ca58d 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_serialize.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_serialize.java
@@ -111,4 +111,9 @@ public class TestBuiltin_serialize extends TestBase {
 
         assertEval("{ options(keep.source=FALSE); f <- function() NULL; attributes(f) <- list(skeleton=quote(`<undef>`())); data <- serialize(f, conn=NULL); unserialize(conn=data) }");
     }
+
+    @Test
+    public void testSerializeWithPromises() {
+        assertEval("{ f <- function(...) serialize(mget('...'),NULL); length(unserialize(f(a=3,b=2,c=1))[[1]]); }");
+    }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_split.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_split.java
index 234bd45d0266926805884872852794e57ed378de..d551d2225e677fb93c52e60517b814c17b2d78ff 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_split.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_split.java
@@ -116,5 +116,13 @@ public class TestBuiltin_split extends TestBase {
         assertEval("{ fu <- c(\"a\",\"b\") ; split(1:8,fu) }");
         assertEval("{ g <- factor(round(c(0.4,1.3,0.6,1.8,2.5,4.1,2.2,1.0))) ; x <- c(0.1,3.2,1,0.6,1.9,3.3,1.6,1.7) + sqrt(as.numeric(g)) ; xg <- split(x, g) ; xg }");
         assertEval("{ x <- factor(c(\"a\", \"b\", \"a\")); attr(x, \"levels\")<-c(7L, 42L) ; split(1:3, x) }");
+        assertEval("{ split(list(1, 2L, 'x', T), as.factor(c('a', 'b', 'a')); }");
+        assertEval("{ split(as.raw(1:10), as.factor(c('a', 'b', 'a')); }");
+    }
+
+    @Test
+    public void testSplitWithNames() {
+        assertEval(Ignored.Unimplemented, "{ split(list(q=1, w=2L, e='x', r=T), as.factor(c('a', 'b', 'a')); }");
+        assertEval(Ignored.Unimplemented, "{ tmp <- c(1,2,3); names(tmp) <- c('x','y','z'); split(tmp, as.factor(c('a','b'))); }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_weekdaysDate.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_weekdaysDate.java
index 8ab38d35b6fa007071c805b3adece9147947dcb4..00e6bb6e1914232d71750858acce129c3c46be5b 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_weekdaysDate.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_weekdaysDate.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -13,6 +13,7 @@ package com.oracle.truffle.r.test.builtins;
 import org.junit.Test;
 
 import com.oracle.truffle.r.test.TestBase;
+import java.util.Locale;
 
 // Checkstyle: stop line length check
 
@@ -20,6 +21,11 @@ public class TestBuiltin_weekdaysDate extends TestBase {
 
     @Test
     public void testweekdaysDate1() {
+        // Explicit locale setting is a workaround to run this test on JDK9.
+        // Otherwise the test was returning "Thu" instead of "Thursday"
+        // due to JDK bug 8130845.
+        Locale.setDefault(Locale.ENGLISH);
+
         assertEval("argv <- structure(list(x = structure(16352, class = 'Date')),     .Names = 'x');do.call('weekdays.Date', argv)");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RInteropScalarMRTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RInteropScalarMRTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..e216b0d234ace50a4797da899c09b5a9b0c77035
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RInteropScalarMRTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.engine.interop;
+
+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.UnknownIdentifierException;
+import com.oracle.truffle.api.interop.UnsupportedMessageException;
+import com.oracle.truffle.api.interop.UnsupportedTypeException;
+import com.oracle.truffle.api.source.Source;
+import com.oracle.truffle.api.vm.PolyglotEngine;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+public class RInteropScalarMRTest {
+
+    @Test
+    public void testRInteroptScalar() throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException {
+        testRIS("toByte", "" + Byte.MAX_VALUE, Byte.class);
+        testRIS("toChar", "'a'", Character.class);
+        testRIS("toFloat", "" + Float.MAX_VALUE, Float.class);
+        testRIS("toLong", "" + Long.MAX_VALUE, Long.class);
+        testRIS("toShort", "" + Short.MAX_VALUE, Short.class);
+    }
+
+    private void testRIS(String toInteropScalarBuiltin, String value, Class<?> unboxedType) throws UnsupportedMessageException {
+        TruffleObject l = createRInteroptScalarTO(toInteropScalarBuiltin, value);
+
+        assertFalse(ForeignAccess.sendIsNull(Message.IS_NULL.createNode(), l));
+        assertFalse(ForeignAccess.sendHasSize(Message.HAS_SIZE.createNode(), l));
+
+        assertTrue(ForeignAccess.sendIsBoxed(Message.IS_BOXED.createNode(), l));
+        Object ub = ForeignAccess.sendUnbox(Message.UNBOX.createNode(), l);
+        assertEquals(unboxedType, ub.getClass());
+    }
+
+    private TruffleObject createRInteroptScalarTO(String toInteropScalarBuiltin, String value) {
+        PolyglotEngine engine = PolyglotEngine.newBuilder().build();
+        Source src = Source.newBuilder(".fastr.interop." + toInteropScalarBuiltin + "(" + value + ")").mimeType("text/x-r").name("test.R").build();
+        PolyglotEngine.Value result = engine.eval(src);
+        return result.as(TruffleObject.class);
+    }
+
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/shell/TestJLineConsoleCompleter.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/shell/TestJLineConsoleCompleter.java
index e7d55912a9dfb820431d590ee1ffa684acb7c531..015fa4ff405ce362e1a4378cbb4b82877f07e0e0 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/shell/TestJLineConsoleCompleter.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/shell/TestJLineConsoleCompleter.java
@@ -118,7 +118,8 @@ public class TestJLineConsoleCompleter {
         }
     }
 
-    private class DummyConsoleHandler implements ConsoleHandler {
+    private class DummyConsoleHandler extends ConsoleHandler {
+
         @Override
         public void println(String s) {
         }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestFunctions.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestFunctions.java
index 8265d0daad743fd31606eca36322bfbe3c7629ab..19068de2cbd7721c7c16ebf3b64365df6616c799 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestFunctions.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestFunctions.java
@@ -240,6 +240,7 @@ public class TestFunctions extends TestBase {
         assertEval("{ foo <- function(xa, ...) list(xa=xa, ...); foo(x=4,xa=5); }");
         // however, two partial matches produce error, even if one is "longer"
         assertEval("{ foo <- function(xaaa, ...) list(xaa=xaaa, ...); foo(xa=4,xaa=5); }");
+        assertEval("list(`...`=NULL);");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java
index 0b51a3d92da5c30b1872b21f4e31c429aeaa6403..ca61843663b6891e0e6bfea2f7358a2495c30ee8 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java
@@ -66,7 +66,7 @@ public final class FastRSession implements RSession {
      * A (virtual) console handler that collects the output in a {@link StringBuilder} for
      * comparison. It does not separate error output as the test analysis doesn't need it.
      */
-    public static class TestConsoleHandler implements ConsoleHandler {
+    public static class TestConsoleHandler extends ConsoleHandler {
         private final StringBuilder buffer = new StringBuilder();
         private final Deque<String> input = new ArrayDeque<>();
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSharedCluster.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSharedCluster.java
new file mode 100644
index 0000000000000000000000000000000000000000..22c14a3b209d3193f91d206d4f692c246a569823
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSharedCluster.java
@@ -0,0 +1,37 @@
+/*
+ * 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.library.base;
+
+import org.junit.Test;
+
+import com.oracle.truffle.r.test.TestBase;
+
+// Checkstyle: stop line length check
+public class TestSharedCluster extends TestBase {
+
+    @Test
+    public void testSharedCluster() {
+        assertEval(TestBase.template("fun <- function(data) { cl <- makeCluster(%0, 'SHARED'); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100)", "123456789".split("")));
+    }
+
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java
index 0997d603ee8d5b361ee38ac003ee33fa13cb8362..6ce8c916abceface6107b8994e53e785f0abc5f7 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestInterop.java
@@ -39,10 +39,11 @@ public class TestInterop extends TestBase {
 
     private static final SeekableMemoryByteChannel CHANNEL = new SeekableMemoryByteChannel();
     private static final String CHANNEL_NAME = "_fastr_channel0";
+    private static final String TEST_EVAL_FILE = "_testInteropEvalFile_testScript_.R";
 
     @After
     public void cleanup() {
-        File f = new File("testScript.R");
+        File f = new File(TEST_EVAL_FILE);
         if (f.exists()) {
             f.delete();
         }
@@ -67,9 +68,11 @@ public class TestInterop extends TestBase {
 
     @Test
     public void testInteropEvalFile() {
-        assertEvalFastR("fileConn<-file(\"testScript.R\");writeLines(c(\"x<-c(1)\",\"cat(x)\"), fileConn);close(fileConn);.fastr.interop.evalFile(\"testScript.R\",\"application/x-r\")",
+        assertEvalFastR("fileConn<-file(\"" + TEST_EVAL_FILE + "\");writeLines(c(\"x<-c(1)\",\"cat(x)\"), fileConn);close(fileConn);.fastr.interop.evalFile(\"" + TEST_EVAL_FILE +
+                        "\",\"application/x-r\")",
+                        "x<-c(1);cat(x)");
+        assertEvalFastR("fileConn<-file(\"" + TEST_EVAL_FILE + "\");writeLines(c(\"x<-c(1)\",\"cat(x)\"), fileConn);close(fileConn);.fastr.interop.evalFile(\"" + TEST_EVAL_FILE + "\")",
                         "x<-c(1);cat(x)");
-        assertEvalFastR("fileConn<-file(\"testScript.R\");writeLines(c(\"x<-c(1)\",\"cat(x)\"), fileConn);close(fileConn);.fastr.interop.evalFile(\"testScript.R\")", "x<-c(1);cat(x)");
         assertEvalFastR("tryCatch(.fastr.interop.evalFile(\"/a/b.R\"),  error = function(e) e$message)", "cat('[1] \"Error reading file: /a/b.R\"\\n')");
     }
 
@@ -108,7 +111,8 @@ public class TestInterop extends TestBase {
 
     @Test
     public void testPrinting() {
-        assertEvalFastR("v <- .fastr.interop.import('testPOJO'); print(v)", "cat('$intValue\\n" +
+        assertEvalFastR("v <- .fastr.interop.import('testPOJO'); print(v)", "cat('[external object]\\n" +
+                        "$intValue\\n" +
                         "[1] 1\\n" +
                         "\\n" +
                         "$longValue\\n" +
@@ -124,19 +128,10 @@ public class TestInterop extends TestBase {
                         "[1] TRUE\\n" +
                         "\\n" +
                         "$stringValue\\n" +
-                        "[1] \"foo\"\\n" +
-                        "\\n" +
-                        "attr(,\"is.truffle.object\")\\n" +
-                        "[1] TRUE\\n')");
-        assertEvalFastR("v <- .fastr.interop.import('testStringArray'); print(v)", "cat('[1] \"a\"   \"\"    \"foo\"\\n" +
-                        "attr(,\"is.truffle.object\")\\n" +
-                        "[1] TRUE\\n')");
-        assertEvalFastR("v <- .fastr.interop.import('testIntArray'); print(v)", "cat('[1]   1  -5 199\\n" +
-                        "attr(,\"is.truffle.object\")\\n" +
-                        "[1] TRUE\\n')");
-        assertEvalFastR("v <- .fastr.interop.import('testIntArray'); v", "cat('[1]   1  -5 199\\n" +
-                        "attr(,\"is.truffle.object\")\\n" +
-                        "[1] TRUE\\n')");
+                        "[1] \"foo\"\\n\\n')");
+        assertEvalFastR("v <- .fastr.interop.import('testStringArray'); print(v)", "cat('[external object]\\n[1] \"a\"   \"\"    \"foo\"\\n')");
+        assertEvalFastR("v <- .fastr.interop.import('testIntArray'); print(v)", "cat('[external object]\\n[1]   1  -5 199\\n')");
+        assertEvalFastR("v <- .fastr.interop.import('testIntArray'); v", "cat('[external object]\\n[1]   1  -5 199\\n')");
         assertEvalFastR("v <- .fastr.interop.import('testPOJO'); names(v)", "c('intValue', 'longValue', 'charValue', 'shortValue', 'booleanValue', 'stringValue')");
     }
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java
index 05db254460ed61f551c61cb87e6f2fc1bcc1c1ba..4296cd975d7f5f4ce129f80438c5e621cba937ac 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/fastr/TestJavaInterop.java
@@ -260,7 +260,8 @@ public class TestJavaInterop extends TestBase {
 
     @Test
     public void testClassAsParameter() {
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$classAsArg(tc)", getRValue(TEST_CLASS));
+        // fails in testdownstream
+        assertEvalFastR(Ignored.ImplementationError, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$classAsArg(tc)", getRValue(TEST_CLASS));
     }
 
     private void getValueForAllTypesMethod(String method) {
@@ -339,6 +340,13 @@ public class TestJavaInterop extends TestBase {
         assertEvalFastR("tc <- .fastr.java.class('" + TestNamesClassMap.class.getName() + "'); t <- .fastr.interop.new(tc); sort(names(t$m()))", "c('one', 'two')");
     }
 
+    @Test
+    public void testAttributes() {
+        assertEvalFastR("to <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); attributes(to)", "NULL");
+        assertEvalFastR("to <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); attr(to, 'a')<-'a'", "cat('Error in attr(to, \"a\") <- \"a\" : external object cannot be attributed\n')");
+        assertEvalFastR("to <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); attr(to, which = 'a')", "cat('Error in attr(to, which = \"a\") : external object cannot be attributed\n')");
+    }
+
     private String getRValue(Object value) {
         if (value == null) {
             return "NULL";
@@ -362,7 +370,7 @@ public class TestJavaInterop extends TestBase {
         }
         if (value.getClass().isArray()) {
             StringBuilder sb = new StringBuilder();
-            sb.append("cat('[1] ");
+            sb.append("cat('[external object]\\n[1] ");
             int lenght = Array.getLength(value);
             for (int i = 0; i < lenght; i++) {
                 if (lenght > 1 && value.getClass().getComponentType() == Boolean.TYPE && (boolean) Array.get(value, i)) {
@@ -374,7 +382,7 @@ public class TestJavaInterop extends TestBase {
                     sb.append(" ");
                 }
             }
-            sb.append("\\nattr(,\"is.truffle.object\")\\n[1] TRUE\\n')");
+            sb.append("\\n')");
             return sb.toString();
         }
         return value.toString();
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index 3479fff1b86814164245efe99a1b38315fe81fe1..b2505b0cb646d5b616d1a72e2a6f7d02099ab07c 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -770,6 +770,7 @@ com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLine
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortTransform.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LGridDirty.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridColorUtils.java,gnu_r.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/PaletteExternals.java,gnu_r.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircle.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/EdgeDetection.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java,gnu_r_murrel_core.copyright
diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py
index 16bd646f2ebe8403c5c61ecc2bd36e425a978db4..db642349a852df098c51eef7fbe99dc476f55188 100644
--- a/mx.fastr/suite.py
+++ b/mx.fastr/suite.py
@@ -29,7 +29,7 @@ suite = {
             {
                "name" : "truffle",
                "subdir" : True,
-               "version" : "acbe9ec935090e0824372e508563c122b0e46682",
+               "version" : "538d97d5e696be8a0f882cf970e70689674651c2",
                "urls" : [
                     {"url" : "https://github.com/graalvm/graal", "kind" : "git"},
                     {"url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind" : "binary"},